Durable Objects
2 Durable Object classes for real-time WebSocket communication. Each society gets its own DO instance. Stateful, single-threaded per instance.
1. GateSyncDO — Real-Time Guard Terminal Sync
File: src/durable_objects/GateSyncDO.ts (368 lines)
WebSocket hub connecting all guard terminals in a society. Handles real-time events for visitor entry/exit, ANPR readings, boom barrier signals, and overstay alerts.
WebSocket Protocol
| Event | Direction | Payload |
|---|---|---|
visitor.entry | Guard → Hub → All | { visitorId, name, flatNumber, gate, timestamp } |
visitor.exit | Guard → Hub → All | { visitorId, gate, duration, timestamp } |
anpr.reading | Camera → Hub → All | { plateNumber, cameraId, match: boolean, vehicle? } |
boom.signal | Hub → Barrier | { barrierId, action: 'open'|'close' } |
overstay.alert | Hub → All Guards | { visitorId, name, flatNumber, duration, threshold } |
sos.trigger | Guard → Hub → All | { message, location, severity } |
State Management
// In-memory state per society DO instance:
- activeConnections: Map<WebSocket, { guardId, gate }>
- activeVisitors: Map<visitorId, { entryTime, flat, gate }>
- barrierStatus: Map<barrierId, { isOpen, lastSignal }>
- overstayThresholds: { default: 4h, delivery: 1h, guest: 24h }
2. EmergencySosDO — Emergency SOS Broadcast
File: src/durable_objects/EmergencySosDO.ts (377 lines)
Emergency SOS hub. When any resident or guard triggers an SOS, it broadcasts to all connected guards and administrators in real-time.
WebSocket Protocol
| Event | Direction | Payload |
|---|---|---|
sos.triggered | Trigger → Hub → All | { sosId, type, triggeredBy, flat, location, timestamp } |
sos.acknowledged | Guard → Hub → All | { sosId, acknowledgedBy, eta } |
sos.resolved | Guard → Hub → All | { sosId, resolvedBy, resolutionNotes } |
sos.false_alarm | Guard → Hub → All | { sosId, reportedBy } |
lockdown.broadcast | Admin → Hub → All | { reason, gates: ['entry', 'exit'] } |
active.alarms | New Client → Hub | Returns all currently active SOS alarms |
State Management
// Per-society DO instance:
- activeAlarms: Map<sosId, { type, status, triggeredBy, timestamp }>
- connectedClients: Map<WebSocket, { role, userId }>
- lockdownState: { isLocked, gates, reason, timestamp }
- escalationTimers: Map<sosId, Timeout> // auto-escalate after 5min
DO Usage Pattern
// From any route handler:
const gateHub = c.env.GATE_SYNC_HUB.get(
c.env.GATE_SYNC_HUB.idFromName(societyId)
);
const stub = gateHub.get(societyId);
await stub.fetch(new Request('https://do/visitor.entry', {
method: 'POST',
body: JSON.stringify({ visitorId, flatNumber, gate })
}));