Skip to content

Lock Middleware

The Lock Middleware is built-in middleware that gives you capability to lock messages. It’s available for CommandBus and QueryBus

How to use it

As for any Middleware, you can use it by adding it to the bus instance.

const commandBus = createCommandBus<CommandHandlerRegistry>();
commandBus.useLockMiddleware({
adapter,
ttl: 500, // the default ttl for all messages
tick: 100, // the delay between each try to get the lock
timeout: 1000 // the maximum time to wait for the lock
getLockKey: async (envelope) => envelope.message.__type,
intents: {
createUser: {
getLockKey: async (envelope) => envelope.message.something,
timeout: 20,
ttl: 50,
tick: 10,
},
},
});

Remember built-in middlewares are intent aware, therefore you can customize the behavior per intent using the key intents.

Of course, the key is in the adapter that you will provide to the createLockMiddleware function. This adapter must respect the LockAdapter interface.

Here is an example:

type LockerInfo = {
expiresAt: number;
};
export const createInMemoryLockAdapter = (): LockAdapter => {
const store: Map<string, LockerInfo> = new Map();
return {
acquire: async (key, ttl) => {
if (store.has(key)) {
if (store.get(key)!.expiresAt > Date.now()) {
return false;
}
}
const now = Date.now();
const expiresAt = now + ttl;
store.set(key, { expiresAt });
return true;
},
release: async (key) => {
store.delete(key);
},
};
};
const adapter = createInMemoryLockAdapter();

Explanation

With the Lock Middleware, if the intent is already locked, it will be returned directly without calling the handler.

You have to pass at least one of the following parameters to the createLockMiddleware function:

  • getLockKey: a function that takes an envelope and returns a string key (the one that will be used to identify the lock)

Then as a second argument, you can provide the following parameters (and per intent):

  • adapter: the adapter to use to store the lock (default: inMemoryLockAdapter)
  • ttl: number (default: 500) - the time to live in milliseconds
  • tick: number (default: 100) - the delay between each try to get the lock
  • timeout: number (default: 1000) - the maximum time to wait for the lock

Added Stamps

No stamps are added by this middleware.

Going further

Look at the code of the Lock Middleware


Missive.js. MIT License.
Powered by Astro Starlight.
Inspired by Symfony Messenger