Skip to main content

DI Integration

The lockFactoryResolverDiFactory function creates an ILockFactoryResolver whose underlying resolver is resolved from a DI container.

The returned proxy implements both ILockFactoryResolver and ILockFactory:

  • use(adapterName?) selects an adapter on the resolved LockFactoryResolver.
  • create(key, settings?) creates a 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 lock adapters, create the container, then register the LockFactoryResolver and wrap it with lockFactoryResolverDiFactory:

1. Set up the memory lock adapter​

./samples/memory-lock-adapter.ts
import { MemoryLockAdapter } from "eridu-tech/lock/memory-lock-adapter";

export const memoryLockAdapter = new MemoryLockAdapter();

2. Set up the Redis lock adapter​

./samples/redis-lock-adapter.ts
import { RedisLockAdapter } from "eridu-tech/lock/redis-lock-adapter";
import { Redis } from "ioredis";

export const redisLockAdapter = new RedisLockAdapter(
new Redis("YOUR_REDIS_CONNECTION_STRING"),
);

3. Create the dependency injection container​

./samples/container.ts
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 lock factory resolver​

./samples/lock-factory-resolver-di-factory.ts
import { LockFactoryResolver } from "eridu-tech/lock";
import { ProxyLockFactoryResolver } from "eridu-tech/lock/di";
import { container } from "./container.js";
import { memoryLockAdapter } from "./memory-lock-adapter.js";
import { redisLockAdapter } from "./redis-lock-adapter.js";

type Adapters = "memory" | "redis";

const lockFactoryResolver = new LockFactoryResolver<Adapters>({
adapters: {
memory: memoryLockAdapter,
redis: redisLockAdapter,
},
defaultAdapter: "memory",
});

await lockFactoryResolver.init();

container.registerValue({
token: LockFactoryResolver,
value: lockFactoryResolver,
});

// Create the proxy before container.init()
export const lockFactory = new ProxyLockFactoryResolver<Adapters>({
container,
resolverToken: LockFactoryResolver,
});

await container.init();

Usage​

1. Using the default adapter​

./samples/lock-factory-resolver-di-factory-default-adapter.ts
import { lockFactory } from "./lock-factory-resolver-di-factory.js";

// Uses the adapter configured as the default (memory)
await lockFactory.create("shared-resource").runOrFail(async () => {
// code to run
});

2. Specifying an adapter explicitly​

./samples/lock-factory-resolver-di-factory-specific-adapter.ts
import { lockFactory } from "./lock-factory-resolver-di-factory.js";

// Uses the Redis adapter
await lockFactory
.use("redis")
.create("shared-resource")
.runOrFail(async () => {
// code to run
});

Using it with the middlewares​

Because the proxy implements ILockFactoryResolver, it can be passed straight to the lock middleware factories:

./samples/lock-factory-resolver-di-factory-with-middleware.ts
import { withLockFactory } from "eridu-tech/lock/middlewares";
import { use } from "eridu-tech/middleware";
import { lockFactory } from "./lock-factory-resolver-di-factory.js";

const withLock = withLockFactory(lockFactory);

const processJob = async (jobId: string): Promise<void> => {
// ... process the job
};

const safeProcess = use(
processJob,
withLock.use("redis")({
key: ([jobId]) => `job:${jobId}`,
}),
);

await safeProcess("job-123");

Further information​

For further information refer to eridu-tech/lock API docs.