Go to your pages project in the dashboard, go to the latest or active deployment details, and find t
Go to your pages project in the dashboard, go to the latest or active deployment details, and find the log streaming thing.
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();
}
}