mutex-server

Mutex Server using WebSocket

Usage no npm install needed!

<script type="module">
  import mutexServer from 'https://cdn.skypack.dev/mutex-server';
</script>

README

Mutex Server

1. Outline

npm install --save mutex-server

GitHub license npm version Downloads Build Status FOSSA Status

Critical sections in the network level.

The mutex-server is an npm module that can be used for building a mutex server. When you need to control a critical section on the entire system level, like distributed processing system using the network communications, this mutex-server can be a good solution.

Installs and opens a mutex-server and let clients to connect to the server. The clients who're connecting to the mutex-server can utilize remote critical section components like mutex or semaphore.

Also, mutex-server has a safety device for network disconnections. When a client has been suddenly disconnected, all of the locks had acquired or tried by the client would be automatically unlocked or cancelled. Therefore, you don't worry about any network disconnection accident and just enjoy the mutex-server with confidence.

2. Features

2.1. Network Level

When you want to open a mutex-server, utilize the MutexServer class and accept or reject connections from the remote clients by using the MutexAcceptor class. Otherwise, you want to connect to a remote mutex-server as a client, utilize the MutexConnector class.

2.2. Critical Section Components

If you succeeded to connect to a mutex-server, as a client through the MutexConnector class, you can utilize lots of remote critical section components like below. For reference, all of those critical section components are following the STL (Standard Template Library) design.

Also, std.UniqueLock and std.SharedLock can be a good choice for safe development. They always ensure that acquired lock to be automatically unlocked, in any circumstance, even if an error occurs in your business code.

3. Usage

mutex-server

Let's learn how to use the mutex-server through a sample project. I'll open a server and let 4 clients to connect to the server. After those 4 clients' connections, they'll monopoly a critical section through RemoteMutex.lock() method and start printing a line very slowly.

After printing has been completed, each client will act one of them randomly: unlock the mutex or close the connection without the unlock. As you know and as I've mentioned, if a client has been disconnected without returning locks that it had been acquired, the mutex-server will automatically release them.

Therefore, two random actions would be confirmed to the same result: RemoteMutex.unlock().

import msv from "mutex-server";
import std from "tstl";

const PASSWORD = "qweqwe123!";
const PORT = 37119;

async function client(index: number, character: string): Promise<void>
{
    // CONNECT TO THE SERVER
    let connector: msv.MutexConnector<string, null> = new msv.MutexConnector(PASSWORD, null);
    await connector.connect(`ws://127.0.0.1:${PORT}`);
    
    // GET LOCK
    let mutex: msv.RemoteMutex = await connector.getMutex("printer");
    await mutex.lock();

    // PRINTS A LINE VERY SLOWLY MONOPOLYING THE MUTEX
    process.stdout.write(`Connector #${index} is monopolying a mutex: `);
    for (let i: number = 0; i < 20; ++i)
    {
        process.stdout.write(character);
        await std.sleep_for(50);
    }
    process.stdout.write("\n");

    // ALTHOUGH THE CLIENT DOES NOT RELEASE THE LOCK
    if (Math.random() < 0.5)
        await mutex.unlock();
    else // SERVER WILL UNLOCK IT AUTOMATICALLY AFTER THE DISCONNECTION
        await connector.close();
}

async function main(): Promise<void>
{
    // OPEN SERVER
    let server: msv.MutexServer<string, null> = new msv.MutexServer();
    await server.open(PORT, async acceptor =>
    {
        if (acceptor.header === PASSWORD)
            await acceptor.accept(null);
        else
            await acceptor.reject();
    });

    // CREATE 10 CLIENTS LOCKING MUTEX
    let promises: Promise<void>[] = [];
    for (let i: number = 0; i < 4; ++i)
    {
        let character: string = std.randint(0, 9).toString();
        promises.push( client(i + 1, character) );
    }

    // WAIT THE CLIENTS TO BE DISCONNCTED AND CLOSE SERVER
    await Promise.all(promises);
    await server.close();
}
main();

4. Appendix

4.1. Repositories

mutex-server is an open source project following the MIT license.

4.2. Documents

Someone who wants to know more about this mutex-server, I've prepared the API documents. Through the API documents, you can travel all of the features defined in this mutex-server.

Also, I'm planning to write the guide documents providing detailed learning course and lots of example projects handling network level critical sections. When the guide documents has been published, its URL address would be https://mutex.dev and it would form like the TGrid's.

4.3. Dependencies

4.3.1. TypeScript

I've developed this mutex-server with the TypeScript.

Also, I hope all users of this mutex-server to use the TypeScript too, for the safe development. As this mutex-server is designed to handling critical section in the network level, a tiny mistake like mis-typing can be a critical damage on the entire network system.

It's the reason why I recommend you to use the TypeScript when using this mutex-server.

4.3.2. TSTL

This mutex-server is an extension module of the TSTL.

TSTL is an open source project migrating C++ STL (Standrad Template Library) to the TypeScript. Therefore, TSTL is following designs from the C++ standard committee and providing many modules like containers, iterators, algorithms and functors following the standard.

However, TypeScript is not C++ and it's development environment is different with the C++, either. Therefore, there're some STL features that are not suitable for the TypeScript development. Also, there can be a feature not supported by STL, but it's an important one in the TypeScript development environment, too.

To resolve such problems, TSTL is providing extension modules. This mutex-server is one of those extension module from the TSTL, designed to support the network level critical sections: tstl#74.

4.3.3. TGrid

TGrid is also an extension module of the TSTL, designed to support the thread and network, too.

The TGrid has implemented thread and network by inventing a new concept; RFC (Remote Function Call). Also, this mutex-server has realized its remote, network level critical section, components by utilizing the RFC concepts invented by the TGrid.