This library provides a mutex that works with async functions. It guarantees that a certain async code section is never executed concurrently. ⚙️⚡
Furthermore, it provides an @synchronized
decorator for usage in typescript.
yarn add synchronized-ts
# or
npm i synchronized-ts
Synchronized decorator:
class Runner {
// Synchronized works on methods.
// Creates a seperate lock context for each instance.
@synchronized
public async run() {
// Do some async work that can never race for an instance of this instance.
}
}
Locking based on context:
const synchronizePayment = new MutexLibrary<number>()
app.post('/payment/:userId?', async (ctx: any) => {
const userId = ctx.params.userId
ctx.response.body = await synchronizePayment.by(userId).sync(async () => {
// Do dangerous things that can never race for a user.
return 0
})
})
Global locking:
const synchronizePayment = new Mutex<number>()
app.post('/signup/', async (ctx: any) => {
ctx.response.body = await synchronizePayment.sync(async () => {
// Do dangerous things that can never race at all.
return 0
})
})
For more detailed examples, please look into the examples
and test
folders.
Generally speaking, you should always aim for lock-free concurrency mechanisms when building web applications. However, there might be corner cases: I ran into a case with 3rd party APIs, where executing concurrent calls to certain API in the same user context broke things, hence I wrote this library.
- Only works locally, e.g. within a single node instance. For synchronization between different instances or serverless functions, please look into other projects. That's a hard problem though.