@chaos-overlords/worker 0.9.5 → 0.9.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +8 -8
- package/src/MatchHub.ts +17 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chaos-overlords/worker",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.6",
|
|
4
4
|
"description": "Cloudflare Workers runtime facade: the shared Hono app over D1, with one Durable Object per match for SSE fan-out and turn-deadline alarms.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"chaos-overlords",
|
|
@@ -47,17 +47,17 @@
|
|
|
47
47
|
"provenance": true
|
|
48
48
|
},
|
|
49
49
|
"dependencies": {
|
|
50
|
-
"@chaos-overlords/bug-reports": "0.9.
|
|
51
|
-
"@chaos-overlords/contracts": "0.9.
|
|
52
|
-
"@chaos-overlords/kernel": "0.9.
|
|
53
|
-
"@chaos-overlords/server": "0.9.
|
|
54
|
-
"@chaos-overlords/storage": "0.9.
|
|
50
|
+
"@chaos-overlords/bug-reports": "0.9.6",
|
|
51
|
+
"@chaos-overlords/contracts": "0.9.6",
|
|
52
|
+
"@chaos-overlords/kernel": "0.9.6",
|
|
53
|
+
"@chaos-overlords/server": "0.9.6",
|
|
54
|
+
"@chaos-overlords/storage": "0.9.6",
|
|
55
55
|
"drizzle-orm": "^0.45.2",
|
|
56
56
|
"hono": "^4.13.8"
|
|
57
57
|
},
|
|
58
58
|
"devDependencies": {
|
|
59
|
-
"@chaos-overlords/client": "0.9.
|
|
60
|
-
"@chaos-overlords/conformance": "0.9.
|
|
59
|
+
"@chaos-overlords/client": "0.9.6",
|
|
60
|
+
"@chaos-overlords/conformance": "0.9.6",
|
|
61
61
|
"@cloudflare/vitest-pool-workers": "^0.22.0",
|
|
62
62
|
"@cloudflare/workers-types": "^5.20260920.1",
|
|
63
63
|
"typescript": "^7.0.2",
|
package/src/MatchHub.ts
CHANGED
|
@@ -47,6 +47,15 @@ function retryFloor(
|
|
|
47
47
|
return Math.max(dueAtMs, fired.dueAtMs + EARLY_DEADLINE_RETRY_MS)
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
+
/** Whether a pending deadline is still exactly the one read earlier, due time included. */
|
|
51
|
+
function isSameDeadline(pending: PendingDeadline | undefined, seen: PendingDeadline): boolean {
|
|
52
|
+
return (
|
|
53
|
+
pending?.matchId === seen.matchId &&
|
|
54
|
+
pending.turn === seen.turn &&
|
|
55
|
+
pending.dueAtMs === seen.dueAtMs
|
|
56
|
+
)
|
|
57
|
+
}
|
|
58
|
+
|
|
50
59
|
/**
|
|
51
60
|
* One instance per match. It holds the open event streams of that match (so a notification from
|
|
52
61
|
* any Worker isolate reaches every subscriber) and the alarm for the open turn's deadline. The
|
|
@@ -160,6 +169,14 @@ export class MatchHub {
|
|
|
160
169
|
const stillDue =
|
|
161
170
|
match?.status === 'running' && turn?.status === 'open' && turn.deadlineAt !== null
|
|
162
171
|
if (stillDue) return
|
|
172
|
+
// Asked again after the D1 reads, which open the object's input gate: a ready seal in another
|
|
173
|
+
// isolate can arm its successor's deadline in between. Deleting on the first answer threw that
|
|
174
|
+
// deadline away, and the new turn then counted down to zero on every screen and sat there until
|
|
175
|
+
// a player ended it or the cron swept it. Nothing awaits between this read and the delete
|
|
176
|
+
// except the object's own storage, which keeps the gate shut.
|
|
177
|
+
if (!isSameDeadline(await this.state.storage.get<PendingDeadline>(DEADLINE_KEY), current)) {
|
|
178
|
+
return
|
|
179
|
+
}
|
|
163
180
|
await this.state.storage.delete(DEADLINE_KEY)
|
|
164
181
|
await this.state.storage.deleteAlarm()
|
|
165
182
|
}
|