Ready for a crowd: idle rooms sleep, share cards render once
Memory now carries only live tables — a sweep puts finished rooms to bed after 30 minutes and anything untouched after a day, and getRoom wakes a sleeping room from its ledger the moment anyone asks (the seed plus the log IS the game). The room cap counts ledgers on disk, not just rooms awake. Share-card PNGs render once per share id and cache immutable. Rate-limit kicks use terminate() so an abuser cannot hold the socket open by ignoring the closing handshake. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015RCWSTnb1KYTPyL4GmhGnF
This commit is contained in:
co-authored by
Claude Fable 5
parent
9cc0430ee2
commit
002698085f
@@ -97,6 +97,29 @@ export function appendLine(roomId: string, line: RoomLine): void {
|
||||
appendFileSync(fileFor(roomId), JSON.stringify(line) + "\n", "utf8");
|
||||
}
|
||||
|
||||
/** Read one persisted room's lines, or null if it has no ledger. */
|
||||
export function readRoom(roomId: string): RoomLine[] | null {
|
||||
const file = fileFor(roomId);
|
||||
if (!existsSync(file)) return null;
|
||||
try {
|
||||
const lines = readFileSync(file, "utf8")
|
||||
.split("\n")
|
||||
.filter((l) => l.trim().length > 0)
|
||||
.map((l) => JSON.parse(l) as RoomLine);
|
||||
return lines.length > 0 && lines[0]!.kind === "meta" ? lines : null;
|
||||
} catch (e) {
|
||||
console.error(`unreadable room file ${roomId}:`, e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/** How many rooms have ledgers on disk — the server-wide cap counts these,
|
||||
* not just the rooms currently awake in memory. */
|
||||
export function countRoomFiles(): number {
|
||||
ensureDataDir();
|
||||
return readdirSync(DATA_DIR).filter((f) => f.endsWith(".jsonl")).length;
|
||||
}
|
||||
|
||||
/** Read every persisted room's lines, keyed by room id. */
|
||||
export function readAllRooms(): Map<string, RoomLine[]> {
|
||||
ensureDataDir();
|
||||
|
||||
Reference in New Issue
Block a user