Here's a further example in action to help demonstrate as well: ``` public executeTransaction(
Here's a further example in action to help demonstrate as well:
public executeTransaction(
queries: { sql: string; params?: unknown[] }[]
): unknown[] {
return this.storage.transactionSync(() => {
const results = []
try {
for (const queryObj of queries) {
const { sql, params } = queryObj
const result = this.executeQuery({ sql, params })
results.push(result)
}
return results
} catch (error) {
console.error('Transaction Execution Error:', error)
throw error
}
})
}https://cloudflare.com/cdn-cgi/trace from the DO to work out where it is and return early if in HKGwrangler dev --remote, to connect with KVsayHello RCP or the alarm API could be called from a WFP user script?await this.ctx.storage.setAlarm(Date.now()); ) could I run into any issues? Are there any gotchas here? I have been using this and it works, however, I have encountered (what seems to be) race conditions with this async work so I wonder if that immediate alarm has anything to do with this.this.state.acceptWebSocket(socket, topic), then to find connections by topic you would do this.state.getWebSockets(topic)this.storage.transactionSync(() => {...}) directly. In the callback, you can do a query, process it with code, do another query, etc. Then, every storage operation in that callback will either all-succeed or all-fail.this.state.acceptWebSocket(socket)async fetch(request) {
const upgradeHeader = request.headers.get("Upgrade");
if (upgradeHeader === "websocket") {
const [client, server] = Object.values(new WebSocketPair());
this.state.acceptWebSocket(server);
const isFirst = this.sessions.size === 0;
server.serializeAttachment({ isFirst });
this.sessions.set(server, { isFirst });
if (!isFirst) {
console.log("sessions.size: ", this.sessions.size);
// Debug
for (let [ws, data] of this.sessions.entries()) {
console.log("WS:", ws, "DATA:", data);
}
// find the connection with session.isFirst === true
const [firstWs, firstSession] = [...this.sessions.entries()].find(([_, session]) => session.isFirst) || [];
console.log("Found firstWs:", firstWs, "firstSession:", firstSession);
if (firstWs) {
console.log("Sending sync.")
firstWs.send(JSON.stringify({ Evento: "sincronizar_fila", Comando: "" }));
}
}
// When connect, send the stored musics
const storedMusics = await this.state.storage.get("musicas");
if (storedMusics) {
server.send(JSON.stringify({ Evento: "musicas", Comando: storedMusics }));
}
return new Response(null, { status: 101, webSocket: client });
}
return new Response("The request is not a websocket.", { status: 400 });
}
async webSocketClose(ws) {
let session = this.sessions.get(ws);
this.sessions.delete(ws);
if (session?.isFirst) {
console.log("The first. Closing all");
await this.state.storage.delete("musicas");
for (let [otherWs] of this.sessions.entries()) {
otherWs.close();
this.sessions.delete(otherWs);
}
}
ws.close();
}

[[durable_objects.bindings]]
name = "MY_DURABLE1"
class_name = "DO1"
[[durable_objects.bindings]]
name = "MY_DURABLE2"
class_name = "DO2"
[[migrations]]
tag = "v2"
new_sqlite_classes = ["DO1", "DO2"]✘ [ERROR] Uncaught (in promise) Error: Error: This Durable Object is not backed by SQLite storage, so the SQL API is not available. SQL can be enabled on a new Durable Object class by using the `new_sqlite_classes` instead of `new_classes` under `[[migrations]]` in your wrangler.toml, but an already-deployed class cannot be converted to SQLite (except by deleting the existing data).async fetch(request) {
const upgradeHeader = request.headers.get("Upgrade");
if (upgradeHeader === "websocket") {
const [client, server] = Object.values(new WebSocketPair());
this.state.acceptWebSocket(server);
const isFirst = this.sessions.size === 0;
server.serializeAttachment({ isFirst });
this.sessions.set(server, { isFirst });
if (!isFirst) {
console.log("sessions.size: ", this.sessions.size);
// Debug
for (let [ws, data] of this.sessions.entries()) {
console.log("WS:", ws, "DATA:", data);
}
// find the connection with session.isFirst === true
const [firstWs, firstSession] = [...this.sessions.entries()].find(([_, session]) => session.isFirst) || [];
console.log("Found firstWs:", firstWs, "firstSession:", firstSession);
if (firstWs) {
console.log("Sending sync.")
firstWs.send(JSON.stringify({ Evento: "sincronizar_fila", Comando: "" }));
}
}
// When connect, send the stored musics
const storedMusics = await this.state.storage.get("musicas");
if (storedMusics) {
server.send(JSON.stringify({ Evento: "musicas", Comando: storedMusics }));
}
return new Response(null, { status: 101, webSocket: client });
}
return new Response("The request is not a websocket.", { status: 400 });
}
async webSocketClose(ws) {
let session = this.sessions.get(ws);
this.sessions.delete(ws);
if (session?.isFirst) {
console.log("The first. Closing all");
await this.state.storage.delete("musicas");
for (let [otherWs] of this.sessions.entries()) {
otherWs.close();
this.sessions.delete(otherWs);
}
}
ws.close();
}