You don’t need that. Do you have access to the cloud flare dashboard
You don’t need that. Do you have access to the cloud flare dashboard
idFromString only accepts the result of an id.toString()
idFromStringid.toString()const lockId = env.LOCK.idFromString(`${storeId}-${data.userEmail}`);
const lock = env.LOCK.get(lockId);
const lockUrl = new URL("http://0.0.0.0/lock");
lockUrl.searchParams.set("durationSecs", "30");
const lockResponse = await lock.fetch(lockUrl.toString());
if (lockResponse.status !== 204)
return new Error("Request being processed.");async fetch(request: Request) {
const url = new URL(request.url);
switch (url.pathname) {
case "/unlock": {
await this.state.storage.delete("lock");
return new Response(null, {
status: 204,
});
}
case "/lock": {
const lockedUntil = await this.state.storage.get<number>("lock");
if (lockedUntil && lockedUntil > Date.now())
return new Response(null, {
status: 409,
});
const durationSecsString = url.searchParams.get("durationSecs");
if (!durationSecsString)
return new Response(null, {
status: 400,
});
const durationSecsNumber = parseInt(durationSecsString);
if (
!Number.isSafeInteger(durationSecsNumber) ||
durationSecsNumber <= 0
)
return new Response(null, {
status: 400,
});
await this.state.storage.put("lock", Date.now());
return new Response(null, {
status: 204,
});
}
}
}export enum LockResult {
Success,
AlreadyLocked,
}
export class Lock {
private lockId: DurableObjectId;
private stub: DurableObjectStub;
constructor(name: string, cloudflareEnv: CloudflareEnv) {
this.lockId = cloudflareEnv.LOCK.idFromName(name);
this.stub = cloudflareEnv.LOCK.get(this.lockId);
}
async unlock() {
const unlockUrl = new URL("http://0.0.0.0/unlock");
const response = await this.stub.fetch(unlockUrl.toString());
if (response.status !== 204) throw new Error(await response.text());
}
async lock(durationSecs: number) {
const lockUrl = new URL("http://0.0.0.0/lock");
lockUrl.searchParams.set("durationSecs", durationSecs.toFixed(0));
const response = await this.stub.fetch(lockUrl.toString());
if (response.status === 204) return LockResult.Success;
if (response.status === 409) return LockResult.AlreadyLocked;
throw new Error(await response.text());
}
}
export class LockError extends Error {
constructor(msg: string) {
super(msg);
// Set the prototype explicitly.
Object.setPrototypeOf(this, LockError.prototype);
}
}
export async function withLock<T>(
name: string,
cloudflareEnv: CloudflareEnv,
lockExpirySecs: number,
fn: () => T,
unlockOnEnd = true,
): Promise<T> {
const lock = new Lock(name, cloudflareEnv);
const lockResult = await lock.lock(lockExpirySecs);
if (lockResult === LockResult.AlreadyLocked)
throw new LockError("Lock is already locked.");
try {
return fn();
} finally {
if (unlockOnEnd) await lock.unlock();
}
}