3.1.4 • Published 5 years ago

key_mutex v3.1.4

Weekly downloads
11
License
996 license
Repository
github
Last release
5 years ago

Usage & Examples

key_mutex is a mutex module that supports -

  • reader-writer mutex
  • lock on a named key
  • nodejs cluster
  • distributed mutex on network

Example 1 - simple mutex

var key_mutex = require('key_mutex');
var mutex = key_mutex.mutex();

function delay(ms){
    return new Promise(function(resolve){
        setTimeout(resolve, ms);
    });
}

async function ex1_task_a(){
    mutex.lock(async function(){
        console.log('ex1_task_a, step 1');
        await delay(500);
        console.log('ex1_task_a, step 2, =======');
    });
}

async function ex1_task_b(){
    mutex.lock(async function(){
        console.log('ex1_task_b, step 1');
        await delay(500);
        console.log('ex1_task_b, step 2, =======');
    });
}

async function example1(){
    ex1_task_a();
    ex1_task_b();
}

output

ex1_task_a, step 1
ex1_task_a, step 2, =======
ex1_task_b, step 1
ex1_task_b, step 2, =======

Example 2 - await the return value

"key_mutex" can await the return value of internal function.

async function example2(){
    var ret = await mutex.lock(async function(){
        console.log('ex2_task, step 1');
        await delay(500);
        console.log('ex2_task, step 2, =======');
        await delay(500);
        return 'returns from ex2_task';
    });
    console.log(ret);   //output 'returns from ex2_task_a'
}

output

ex2_task, step 1
ex2_task, step 2, =======
returns from ex2_task

Example 3 - supports exceptions

"key_mutex" supports exceptions.

async function example3(){
    try{
        var ret = await mutex.lock(async function(){
            console.log('ex3_task, step 1');
            await delay(500);
            throw new Error('throw my error');
            console.log('ex3_task, step 2, =======');
            await delay(500);
            return 'returns from ex2_task';
        });
        console.log(ret);
    }catch(err){
        console.log(err.message);
    }
}

output

ex3_task, step 1
throw my error

Example 4 - mutex with named key

Bind "key_mutex" with a named key, only the same key can lock with each other, which is useful especially when we need to lock the very record line in database.

async function ex4_task_a(key){
    mutex.lock(key, async function(){
        console.log(`ex4_task_a, key = ${key}, step 1`);
        await delay(500);
        console.log(`ex4_task_a, key = ${key}, step 2, =======`);
    });
}

async function ex4_task_b(key){
    mutex.lock(key, async function(){
        console.log(`ex4_task_b, key = ${key}, step 1`);
        await delay(500);
        console.log(`ex4_task_b, key = ${key}, step 2, =======`);
    });
}

async function example4(){
    ex4_task_a(1234);    //use mutex with named key 1234
    ex4_task_b("abcd");  //use mutex with named key "abcd"

    ex4_task_a("abcd");  //use mutex with named key "abcd"
    ex4_task_b(1234);    //use mutex with named key 1234
}

output

ex4_task_a, key = 1234, step 1
ex4_task_b, key = abcd, step 1
ex4_task_a, key = 1234, step 2, =======
ex4_task_b, key = abcd, step 2, =======
ex4_task_b, key = 1234, step 1
ex4_task_a, key = abcd, step 1
ex4_task_b, key = 1234, step 2, =======
ex4_task_a, key = abcd, step 2, =======

Example 5 - Reader-writer mutex

"key_mutex" supports reader-writer mutex.

async function ex5_task_a(){
    mutex.rlock(async function(){
        console.log('ex5_task_a, reader step 1');
        await delay(500);
        console.log('ex5_task_a, reader step 2, =======');
    });
}

async function ex5_task_b(){
    mutex.wlock(async function(){
        console.log('ex5_task_b, writer step 1');
        await delay(500);
        console.log('ex5_task_b, write step 2, =======');
    });
}

async function ex5_task_c(){
    mutex.rlock(async function(){
        console.log('ex5_task_c, reader step 1');
        await delay(500);
        console.log('ex5_task_c, reader step 2, =======');
    });
}

async function example5(){
    ex5_task_a();
    ex5_task_b();
    ex5_task_c();
}

output

ex5_task_a, reader step 1
ex5_task_c, reader step 1
ex5_task_a, reader step 2, =======
ex5_task_c, reader step 2, =======
ex5_task_b, writer step 1
ex1_task_b, writer step 2, =======

Example 6 - Reader-writer mutex with named key

Bind "reader-writer" mutex with a nemed key.

async function ex6_task_a(key){
    mutex.rlock(key, async function(){
        console.log(`ex6_task_a, key = ${key}, reader step 1`);
        await delay(500);
        console.log(`ex6_task_a, key = ${key}, reader step 2, =======`);
    });
}

async function ex6_task_b(key){
    mutex.wlock(key, async function(){
        console.log(`ex6_task_b, key = ${key}, writer step 1`);
        await delay(500);
        console.log(`ex6_task_b, key = ${key}, writer step 2, =======`);
    });
}

async function ex6_task_c(key){
    mutex.rlock(key, async function(){
        console.log(`ex6_task_c, key = ${key}, reader step 1`);
        await delay(500);
        console.log(`ex6_task_c, key = ${key}, reader step 2, =======`);
    });
}

async function ex6_task_d(key){
    mutex.rlock(key, async function(){
        console.log(`ex6_task_d, key = ${key}, reader step 1`);
        await delay(500);
        console.log(`ex6_task_d, key = ${key}, reader step 2, =======`);
    });
}

async function example6(){
    ex6_task_a(1234);
    ex6_task_b(5678);
    ex6_task_c(1234);
    ex6_task_d(5678);
}

output

ex6_task_a, key = 1234, reader step 1
ex6_task_b, key = 5678, writer step 1
ex6_task_c, key = 1234, reader step 1
ex6_task_a, key = 1234, reader step 2, =======
ex6_task_b, key = 5678, writer step 2, =======
ex6_task_c, key = 1234, reader step 2, =======
ex6_task_d, key = 5678, reader step 1
ex6_task_d, key = 5678, reader step 2, =======

APIs

Module

var key_mutex = require('key_mutex');

Create a mutex

var mutex = key_mutex.mutex();

Create a named mutex

For named mutex, you can specifiy a string name as parameters, which is useful if the mutex is created after cluster forked.

var mutex = key_mutex.mutex(name);

Create a distributed mutex on network

We can setup named mutex on server. for example --

  • On host 192.168.1.2, start a mutex server on port 8888,
key_mutex.server(8888);
  • Other client can create mutex on this server
key_mutex.mutex('my_mutex_name', '192.168.1.2:8888');

Distributed mutex API

key_mutex.server(port, [timeout_ms]);
var mutex = key_mutex.mutex(name, host, [timeout_ms]);

Simple lock

mutex.lock(async function(){
    ...
});

Simple lock with key

mutex.lock(key, async function(){
    ...
});

Reader lock

mutex.rlock(async function(){
    ...
});

Reader lock with named key

mutex.rlock(key, async function(){
    ...
});

Writer lock

mutex.wlock(async function(){
    ...
});

Writer lock with named key

mutex.wlock(key, async function(){
    ...
});

destroy the mutex (required by cluster or distributed mode only)

mutex.destroy();
3.1.4

5 years ago

3.1.3

7 years ago

3.1.2

7 years ago

3.1.1

7 years ago

3.1.0

7 years ago

3.0.0

7 years ago

2.1.21

7 years ago

2.1.20

7 years ago

2.1.9

7 years ago

2.1.8

7 years ago

2.1.7

7 years ago

2.1.5

7 years ago

2.1.3

7 years ago

2.1.2

7 years ago

2.1.1

7 years ago

2.1.0

7 years ago

2.0.2

7 years ago

2.0.1

7 years ago

1.0.1

7 years ago