History

feat(orchestration): bound thread history and resume payloads

- Add paginated thread history with bounded snapshots and replay limits - Trim oversized wire payloads and support progressive mobile history loading

Julius Marminge committed 3 months ago

Commit 7d42d311 parent e3883a943 files · +4239 −211Browse files

Showing the changes to apps/server/src/orchestration-v2/ThreadStream.test.ts (1 of 43 files). Show all

Unified · Split

apps/server/src/orchestration-v2/ThreadStream.test.ts+75−0
@@ -0,0 +1,75 @@
1+import { describe, expect, it } from "vite-plus/test";
2+
3+import {
4+ decideThreadResume,
5+ threadReplayEncodedBytes,
6+ THREAD_RESUME_MAX_REPLAY_ENCODED_BYTES,
7+ THREAD_RESUME_MAX_REPLAY_EVENTS,
8+} from "./ThreadStream.ts";
9+
10+describe("decideThreadResume", () => {
11+ it("replays when the gap is zero", () => {
12+ expect(
13+ decideThreadResume({
14+ afterSequence: 10,
15+ highWater: 10,
16+ replayEventCount: 0,
17+ replayEncodedBytes: 0,
18+ }),
19+ ).toEqual({ mode: "replay", afterSequence: 10, throughSequence: 10 });
20+ });
21+
22+ it("replays when the event count is within the bound", () => {
23+ expect(
24+ decideThreadResume({
25+ afterSequence: 10,
26+ highWater: 20_000,
27+ replayEventCount: THREAD_RESUME_MAX_REPLAY_EVENTS,
28+ replayEncodedBytes: THREAD_RESUME_MAX_REPLAY_ENCODED_BYTES,
29+ }),
30+ ).toEqual({
31+ mode: "replay",
32+ afterSequence: 10,
33+ throughSequence: 20_000,
34+ });
35+ });
36+
37+ it("falls back to a snapshot when the event count exceeds the bound", () => {
38+ expect(
39+ decideThreadResume({
40+ afterSequence: 10,
41+ highWater: 20_000,
42+ replayEventCount: THREAD_RESUME_MAX_REPLAY_EVENTS + 1,
43+ replayEncodedBytes: 1,
44+ }),
45+ ).toEqual({ mode: "snapshot" });
46+ });
47+
48+ it("falls back to a snapshot when encoded replay bytes exceed the bound", () => {
49+ expect(
50+ decideThreadResume({
51+ afterSequence: 10,
52+ highWater: 11,
53+ replayEventCount: 1,
54+ replayEncodedBytes: THREAD_RESUME_MAX_REPLAY_ENCODED_BYTES + 1,
55+ }),
56+ ).toEqual({ mode: "snapshot" });
57+ });
58+
59+ it("falls back to a snapshot when the client cursor is ahead of the store", () => {
60+ expect(
61+ decideThreadResume({
62+ afterSequence: 50,
63+ highWater: 40,
64+ replayEventCount: 0,
65+ replayEncodedBytes: 0,
66+ }),
67+ ).toEqual({ mode: "snapshot" });
68+ });
69+
70+ it("counts UTF-8 bytes across projected stream items", () => {
71+ expect(threadReplayEncodedBytes([{ value: "a" }, { value: "🦊" }])).toBe(
72+ Buffer.byteLength('{"value":"a"}', "utf8") + Buffer.byteLength('{"value":"🦊"}', "utf8"),
73+ );
74+ });
75+});

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t