pub const DURABLE_OBJECT_TEMPLATE_JS: &str = r#"
// Auto-generated. One class per shard type.
// Wires up fetch handling, WebSocket accept/hibernation, and alarm-based ticks.
export class ShardDO {
constructor(state, env) {
this.state = state;
this.env = env;
this.sockets = new Map(); // sid -> WebSocket
this.tickRateHz = env.TICK_RATE_HZ || 20;
}
async fetch(req) {
const url = new URL(req.url);
const sid = url.searchParams.get('sid') || 'anon';
if (req.headers.get('Upgrade') === 'websocket') {
const pair = new WebSocketPair();
const [client, server] = Object.values(pair);
this.state.acceptWebSocket(server); // hibernation-compatible
this.sockets.set(sid, server);
if (!(await this.state.storage.get('alarm_set'))) {
await this.state.storage.setAlarm(Date.now() + (1000 / this.tickRateHz));
await this.state.storage.put('alarm_set', true);
}
return new Response(null, { status: 101, webSocket: client });
}
return new Response('not found', { status: 404 });
}
async webSocketMessage(ws, message) {
// Forward input JSON into the shard's input queue (via bound Wasm fn).
this.env.SHARD_IMPORT.pushInput(this.state.id.toString(), message);
}
async webSocketClose(ws) {
for (const [sid, s] of this.sockets) {
if (s === ws) this.sockets.delete(sid);
}
}
async alarm() {
// Run one tick and broadcast to all connected sockets.
const snapshot = this.env.SHARD_IMPORT.runTick(this.state.id.toString());
for (const ws of this.sockets.values()) {
try { ws.send(snapshot); } catch {}
}
// Reschedule.
await this.state.storage.setAlarm(Date.now() + (1000 / this.tickRateHz));
}
}
"#;Expand description
The boilerplate a user adds to their Workers bundle’s JS entry file.
This can’t be generated from Rust alone (the DO class must be exported
from JS so the Workers runtime can instantiate it), so we ship this as
a string constant that the pylon deploy --target workers command
can drop into the generated bundle.