Skip to content

Commit

Permalink
created mutex plugin to lock room operations
Browse files Browse the repository at this point in the history
  • Loading branch information
ggazzo committed Dec 18, 2024
1 parent b8d1e4a commit bdb9bab
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 0 deletions.
23 changes: 23 additions & 0 deletions packages/homeserver/src/mutex/Mutex.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
export class Mutex {
private map: Map<string, boolean> = new Map();
public async request(scope: string) {
if (this.map.has(scope)) {
return false;
}

const lock = new Lock(this, scope, () => this.map.delete(scope));
this.map.set(scope, true);
return lock;
}
}

export class Lock {
constructor(
protected m: Mutex,
public scope: string,
private unlock: () => void,
) {}
public async release() {
this.unlock();
}
}
41 changes: 41 additions & 0 deletions packages/homeserver/src/mutex/mutext.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { afterEach, beforeEach, describe, expect, it } from "bun:test";
import { Mutex, type Lock } from "./Mutex";

describe("Mutex", () => {
let mutex: Mutex;
let lock: Lock | false;

beforeEach(() => {
mutex = new Mutex();
});

afterEach(() => {
if (lock) {
lock.release();
}
});

it("should grant a lock if the scope is not already locked", async () => {
const scope = "test-scope";
lock = await mutex.request(scope);
expect(lock).toBeTruthy();
});

it("should not grant a lock if the scope is already locked", async () => {
const scope = "test-scope";
await mutex.request(scope);
const secondLock = await mutex.request(scope);
expect(secondLock).toBeFalsy();
});

it("should release a lock and allow re-locking the same scope", async () => {
const scope = "test-scope";
lock = await mutex.request(scope);
expect(lock).not.toBeFalse();

await (lock as Lock).release();

const newLock = await mutex.request(scope);
expect(newLock).toBeTruthy();
});
});
10 changes: 10 additions & 0 deletions packages/homeserver/src/plugins/mutex.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import Elysia, { type InferContext } from "elysia";
import { Mutex } from "../mutex/Mutex";

export const routerWithMutex = new Elysia().decorate("mutex", new Mutex());

export const isMutexContext = <T extends object>(
context: T,
): context is T & Context => "mutex" in context;

type Context = InferContext<typeof routerWithMutex>;

0 comments on commit bdb9bab

Please sign in to comment.