DI Integration
The sharedLockFactoryResolverDiFactory function creates an ISharedLockFactoryResolver whose underlying resolver is resolved from a DI container.
The returned proxy implements both ISharedLockFactoryResolver and ISharedLockFactory:
use(adapterName?)selects an adapter on the resolvedSharedLockFactoryResolver.create(key, settings)creates a shared lock through the resolver's default adapter.
The proxy is wired to the container during container.init(). Create it before calling init(); calling use() or create() before the container is initialized throws an error.
Initial configuration
Set up the memory and Redis shared-lock adapters, create the container, then register the SharedLockFactoryResolver and wrap it with sharedLockFactoryResolverDiFactory:
1. Set up the memory shared-lock adapter
import { MemorySharedLockAdapter } from "eridu-tech/shared-lock/memory-shared-lock-adapter";
export const memorySharedLockAdapter = new MemorySharedLockAdapter();
2. Set up the Redis shared-lock adapter
import { RedisSharedLockAdapter } from "eridu-tech/shared-lock/redis-shared-lock-adapter";
import { Redis } from "ioredis";
export const redisSharedLockAdapter = new RedisSharedLockAdapter(
new Redis("YOUR_REDIS_CONNECTION_STRING"),
);
3. Create the dependency injection container
import { Container } from "eridu-tech/di";
import { ExecutionContext } from "eridu-tech/execution-context";
import { AlsExecutionContextAdapter } from "eridu-tech/execution-context/als-execution-context-adapter";
export const executionContext = new ExecutionContext(
new AlsExecutionContextAdapter(),
);
export const container = new Container({ executionContext });
4. Register and initialize the shared-lock factory resolver
import { SharedLockFactoryResolver } from "eridu-tech/shared-lock";
import { ProxySharedLockFactoryResolver } from "eridu-tech/shared-lock/di";
import { container } from "./container.js";
import { memorySharedLockAdapter } from "./memory-shared-lock-adapter.js";
import { redisSharedLockAdapter } from "./redis-shared-lock-adapter.js";
type Adapters = "memory" | "redis";
const sharedLockFactoryResolver = new SharedLockFactoryResolver<Adapters>({
adapters: {
memory: memorySharedLockAdapter,
redis: redisSharedLockAdapter,
},
defaultAdapter: "memory",
});
await sharedLockFactoryResolver.init();
container.registerValue({
token: SharedLockFactoryResolver,
value: sharedLockFactoryResolver,
});
// Create the proxy before container.init()
export const sharedLockFactory = new ProxySharedLockFactoryResolver<Adapters>({
container,
resolverToken: SharedLockFactoryResolver,
});
await container.init();
Usage
1. Using the default adapter
import { sharedLockFactory } from "./shared-lock-factory-resolver-di-factory.js";
// Uses the adapter configured as the default (memory)
await sharedLockFactory
.create("shared-resource", {
limit: 4,
})
.runWriterOrFail(async () => {
// code to run
});
2. Specifying an adapter explicitly
import { sharedLockFactory } from "./shared-lock-factory-resolver-di-factory.js";
// Uses the Redis adapter
await sharedLockFactory
.use("redis")
.create("shared-resource", {
limit: 4,
})
.runWriterOrFail(async () => {
// code to run
});
Using it with the middlewares
Because the proxy implements ISharedLockFactoryResolver, it can be passed straight to the shared-lock middleware factories:
import { use } from "eridu-tech/middleware";
import {
SHARED_LOCK_WHEN,
withSharedLockFactory,
} from "eridu-tech/shared-lock/middlewares";
import { sharedLockFactory } from "./shared-lock-factory-resolver-di-factory.js";
const withSharedLock = withSharedLockFactory(sharedLockFactory);
const readData = async (key: string): Promise<unknown> => {
// Safe to run concurrently with other readers
return { data: "..." };
};
const safeRead = use(
readData,
withSharedLock.use("redis")({
key: ([resourceKey]) => `data:${resourceKey}`,
when: SHARED_LOCK_WHEN.READER,
limit: 10,
}),
);
await safeRead("config");
Further information
For further information refer to eridu-tech/shared-lock API docs.