@catalyst-cloud/sdk 0.9.1 → 0.10.0
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/README.md +27 -0
- package/dist/events.d.ts +79 -0
- package/dist/events.d.ts.map +1 -0
- package/dist/events.js +492 -0
- package/dist/events.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/live-sync-client.d.ts +4 -1
- package/dist/live-sync-client.d.ts.map +1 -1
- package/dist/live-sync-client.js +28 -7
- package/dist/live-sync-client.js.map +1 -1
- package/dist/replica/browser/browser-replica.d.ts +2 -0
- package/dist/replica/browser/browser-replica.d.ts.map +1 -1
- package/dist/replica/browser/browser-replica.js +10 -0
- package/dist/replica/browser/browser-replica.js.map +1 -1
- package/dist/replica/browser/delta-queue.d.ts +3 -1
- package/dist/replica/browser/delta-queue.d.ts.map +1 -1
- package/dist/replica/browser/protocol.d.ts +3 -1
- package/dist/replica/browser/protocol.d.ts.map +1 -1
- package/dist/replica/browser/worker-core.d.ts.map +1 -1
- package/dist/replica/browser/worker-core.js +3 -1
- package/dist/replica/browser/worker-core.js.map +1 -1
- package/dist/replica/catalyst-replica.d.ts +2 -0
- package/dist/replica/catalyst-replica.d.ts.map +1 -1
- package/dist/replica/catalyst-replica.js +11 -0
- package/dist/replica/catalyst-replica.js.map +1 -1
- package/dist/types.d.ts +8 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +6 -1
package/README.md
CHANGED
|
@@ -244,6 +244,32 @@ switch (moved.outcome) {
|
|
|
244
244
|
|
|
245
245
|
The contract cache is in memory per client by default; pass `contractCache: { get, set }` to keep it on disk (the bundle does). `fetch`, `now` and `timeoutMs` are injectable so a test never opens a socket.
|
|
246
246
|
|
|
247
|
+
### Durable event cache for node and Bun
|
|
248
|
+
|
|
249
|
+
`@catalyst-cloud/sdk/events` mirrors the tenant's exact durable Catalyst event backbone into an append-only local cache. It uses bounded HTTP replay with an idle backoff; local consumers tail files and never poll GitHub, Linear, or cloud tables. Start and stop it with the process that currently needs the tenant instead of installing another permanent daemon.
|
|
250
|
+
|
|
251
|
+
```ts
|
|
252
|
+
import { CatalystEventSync, tailCachedEvents } from "@catalyst-cloud/sdk/events";
|
|
253
|
+
|
|
254
|
+
const sync = new CatalystEventSync({
|
|
255
|
+
baseUrl: "https://staging.catalystcloud.dev",
|
|
256
|
+
auth: { kind: "token", token: process.env.CATALYST_CLOUD_TOKEN! },
|
|
257
|
+
tenantId: "tenant-1",
|
|
258
|
+
});
|
|
259
|
+
const running = sync.start();
|
|
260
|
+
for await (const event of tailCachedEvents({ tenantId: "tenant-1", signal })) {
|
|
261
|
+
console.log(event.type, event.sequence);
|
|
262
|
+
}
|
|
263
|
+
await sync.stop();
|
|
264
|
+
await running;
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
The default path is `$XDG_STATE_HOME/catalyst/events/<tenant>/backbone/`, falling back to `~/.local/state/catalyst/events/<tenant>/backbone/`. Daily `YYYY-MM-DD[-NNN].jsonl` segments contain the cloud's `CatalystEvent` envelope unchanged. `cursor.json` is owned by the one sync writer; readers keep their own offsets elsewhere and do not write into this directory. The stable replay identity is `(tenantId, sequence, eventId)`.
|
|
268
|
+
|
|
269
|
+
The writer fsyncs appended records before atomically advancing its cursor. On restart it truncates an incomplete final line and derives the resume cursor from the last complete record, making a crash between append and checkpoint safe. Server archive gaps and reads behind the local retention floor raise `EventHistoryGapError` with the head, suggested resume point, and reason; the SDK does not silently skip history. New caches bootstrap at the current backbone head. Closed daily segments are retained for seven days or until the cache reaches 256 MiB, whichever happens first. The active segment rotates before the same byte bound, so it cannot grow without limit; `retainDays` and `maxCacheBytes` configure these bounds.
|
|
270
|
+
|
|
271
|
+
This API only reads the durable backbone. It does not publish events or treat raw provider events, the legacy coordination feed, or analytical samples as execution or billing authority. Use the existing authorized cloud operations to report outcomes and changes.
|
|
272
|
+
|
|
247
273
|
## API
|
|
248
274
|
|
|
249
275
|
| Export | What it is |
|
|
@@ -256,6 +282,7 @@ The contract cache is in memory per client by default; pass `contractCache: { ge
|
|
|
256
282
|
| `createTenantClient` | The typed HTTP client — `contract()`, `me()`, `issues.list/get`, `pulls.list/get`, `projects.list`, `agent.*` (issueState, issueLabel, issueComment, issueCreate, reaction, attachment, attachments, session, ask, askAccept). |
|
|
257
283
|
| `TenantContract` · `routeByName` · `teamByKey` · `teamForTicket` · `stageIdForSlot` · `labelIdFor` | The contract document's shape and the pure accessors over it, each returning a typed miss rather than throwing. |
|
|
258
284
|
| `TenantClientFailure` · `PageCursor` · `pageCursor` · `memoryContractCache` | The shared failure arms, the opaque page token, and the default contract cache store. |
|
|
285
|
+
| `CatalystEventSync` · `readCachedEvents` · `tailCachedEvents` · `EventHistoryGapError` | Node/Bun durable-backbone replay, local cache readers, and explicit history-gap handling from `@catalyst-cloud/sdk/events`. |
|
|
259
286
|
|
|
260
287
|
`start()` resolves only when `stop()` is called. On a backend, `await` it to keep the process alive; in a browser, never await it — just call `stop()` on teardown.
|
|
261
288
|
|
package/dist/events.d.ts
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import type { CatalystEvent } from "@catalyst-cloud/schema";
|
|
2
|
+
import type { AuthStrategy } from "./live-sync-client.js";
|
|
3
|
+
import { type WriterGuardOptions } from "./replica/writer-lock.js";
|
|
4
|
+
export type { CatalystEvent } from "@catalyst-cloud/schema";
|
|
5
|
+
export interface EventCachePaths {
|
|
6
|
+
directory: string;
|
|
7
|
+
cursor: string;
|
|
8
|
+
lock: string;
|
|
9
|
+
}
|
|
10
|
+
export interface EventSyncOptions {
|
|
11
|
+
baseUrl: string;
|
|
12
|
+
auth: Exclude<AuthStrategy, {
|
|
13
|
+
kind: "cookie";
|
|
14
|
+
}>;
|
|
15
|
+
tenantId: string;
|
|
16
|
+
directory?: string;
|
|
17
|
+
fetch?: typeof fetch;
|
|
18
|
+
requestTimeoutMs?: number;
|
|
19
|
+
idleMinMs?: number;
|
|
20
|
+
idleMaxMs?: number;
|
|
21
|
+
retainDays?: number;
|
|
22
|
+
maxCacheBytes?: number;
|
|
23
|
+
writerGuard?: WriterGuardOptions;
|
|
24
|
+
now?: () => Date;
|
|
25
|
+
sleep?: (ms: number, signal: AbortSignal) => Promise<void>;
|
|
26
|
+
}
|
|
27
|
+
export interface EventSyncStatus {
|
|
28
|
+
state: "idle" | "syncing" | "stopped" | "failed";
|
|
29
|
+
cursor: number | null;
|
|
30
|
+
head: number | null;
|
|
31
|
+
lastSyncAt: string | null;
|
|
32
|
+
error: string | null;
|
|
33
|
+
}
|
|
34
|
+
export interface EventSyncResult {
|
|
35
|
+
appended: number;
|
|
36
|
+
cursor: number;
|
|
37
|
+
head: number;
|
|
38
|
+
}
|
|
39
|
+
export declare class EventHistoryGapError extends Error {
|
|
40
|
+
readonly head: number;
|
|
41
|
+
readonly resumeFrom: number;
|
|
42
|
+
readonly reason: string;
|
|
43
|
+
constructor(message: string, head: number, resumeFrom: number, reason: string);
|
|
44
|
+
}
|
|
45
|
+
export declare function defaultEventCacheDirectory(tenantId: string): string;
|
|
46
|
+
export declare function eventCachePaths(tenantId: string, directory?: string): EventCachePaths;
|
|
47
|
+
export declare class CatalystEventSync {
|
|
48
|
+
private readonly options;
|
|
49
|
+
readonly paths: EventCachePaths;
|
|
50
|
+
private readonly fetchImpl;
|
|
51
|
+
private readonly now;
|
|
52
|
+
private readonly sleeper;
|
|
53
|
+
private lock;
|
|
54
|
+
private controller;
|
|
55
|
+
private running;
|
|
56
|
+
private recoveredCursor;
|
|
57
|
+
private floor;
|
|
58
|
+
private current;
|
|
59
|
+
constructor(options: EventSyncOptions);
|
|
60
|
+
status(): EventSyncStatus;
|
|
61
|
+
syncOnce(signal?: AbortSignal): Promise<EventSyncResult>;
|
|
62
|
+
start(): Promise<void>;
|
|
63
|
+
stop(): Promise<void>;
|
|
64
|
+
private loop;
|
|
65
|
+
private request;
|
|
66
|
+
private readCurrentHead;
|
|
67
|
+
private readPage;
|
|
68
|
+
}
|
|
69
|
+
export interface ReadCachedEventsOptions {
|
|
70
|
+
tenantId: string;
|
|
71
|
+
directory?: string;
|
|
72
|
+
after?: number;
|
|
73
|
+
}
|
|
74
|
+
export declare function readCachedEvents(options: ReadCachedEventsOptions): Promise<CatalystEvent[]>;
|
|
75
|
+
export declare function tailCachedEvents(options: ReadCachedEventsOptions & {
|
|
76
|
+
signal: AbortSignal;
|
|
77
|
+
}): AsyncGenerator<CatalystEvent>;
|
|
78
|
+
export declare function eventIdentity(event: CatalystEvent): string;
|
|
79
|
+
//# sourceMappingURL=events.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../src/events.ts"],"names":[],"mappings":"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"}
|
package/dist/events.js
ADDED
|
@@ -0,0 +1,492 @@
|
|
|
1
|
+
import { mkdir, open, readFile, readdir, rename, rm, stat, truncate, watch, writeFile, } from "node:fs/promises";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { claimWriterLock, } from "./replica/writer-lock.js";
|
|
5
|
+
const HEAD_HEADER = "x-catalyst-event-backbone-head-seq";
|
|
6
|
+
const MAX_EVENT_LINE_BYTES = 1024 * 1024;
|
|
7
|
+
const DEFAULT_REQUEST_TIMEOUT_MS = 15_000;
|
|
8
|
+
const DEFAULT_IDLE_MIN_MS = 1_000;
|
|
9
|
+
const DEFAULT_IDLE_MAX_MS = 30_000;
|
|
10
|
+
const DEFAULT_RETAIN_DAYS = 7;
|
|
11
|
+
const DEFAULT_MAX_CACHE_BYTES = 256 * 1024 * 1024;
|
|
12
|
+
const SEGMENT_PATTERN = /^\d{4}-\d{2}-\d{2}(?:-\d{3})?\.jsonl$/;
|
|
13
|
+
export class EventHistoryGapError extends Error {
|
|
14
|
+
head;
|
|
15
|
+
resumeFrom;
|
|
16
|
+
reason;
|
|
17
|
+
constructor(message, head, resumeFrom, reason) {
|
|
18
|
+
super(message);
|
|
19
|
+
this.head = head;
|
|
20
|
+
this.resumeFrom = resumeFrom;
|
|
21
|
+
this.reason = reason;
|
|
22
|
+
this.name = "EventHistoryGapError";
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
class EventSyncHttpError extends Error {
|
|
26
|
+
status;
|
|
27
|
+
constructor(status) {
|
|
28
|
+
super(`event sync: backbone returned ${status}`);
|
|
29
|
+
this.status = status;
|
|
30
|
+
this.name = "EventSyncHttpError";
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
export function defaultEventCacheDirectory(tenantId) {
|
|
34
|
+
const state = globalThis
|
|
35
|
+
.process?.env?.XDG_STATE_HOME || join(homedir(), ".local", "state");
|
|
36
|
+
return join(state, "catalyst", "events", tenantId, "backbone");
|
|
37
|
+
}
|
|
38
|
+
export function eventCachePaths(tenantId, directory) {
|
|
39
|
+
const root = directory ?? defaultEventCacheDirectory(tenantId);
|
|
40
|
+
return {
|
|
41
|
+
directory: root,
|
|
42
|
+
cursor: join(root, "cursor.json"),
|
|
43
|
+
lock: join(root, ".sync"),
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
function positiveInteger(value, name) {
|
|
47
|
+
if ((typeof value !== "string" && typeof value !== "number") ||
|
|
48
|
+
String(value).trim() === "")
|
|
49
|
+
throw new Error(`event sync: invalid ${name}`);
|
|
50
|
+
const parsed = Number(value);
|
|
51
|
+
if (!Number.isSafeInteger(parsed) || parsed < 0)
|
|
52
|
+
throw new Error(`event sync: invalid ${name}`);
|
|
53
|
+
return parsed;
|
|
54
|
+
}
|
|
55
|
+
function parseEvent(value) {
|
|
56
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
57
|
+
throw new Error("event sync: invalid event");
|
|
58
|
+
const event = value;
|
|
59
|
+
if (typeof event.tenantId !== "string" ||
|
|
60
|
+
!Number.isSafeInteger(event.sequence) ||
|
|
61
|
+
(event.sequence ?? -1) < 0 ||
|
|
62
|
+
typeof event.eventId !== "string" ||
|
|
63
|
+
typeof event.type !== "string" ||
|
|
64
|
+
!Number.isSafeInteger(event.schemaVersion) ||
|
|
65
|
+
typeof event.recordedAt !== "string" ||
|
|
66
|
+
!("payload" in event))
|
|
67
|
+
throw new Error("event sync: invalid event");
|
|
68
|
+
return event;
|
|
69
|
+
}
|
|
70
|
+
async function readNdjson(response) {
|
|
71
|
+
if (!response.body)
|
|
72
|
+
return [];
|
|
73
|
+
const reader = response.body.getReader();
|
|
74
|
+
const decoder = new TextDecoder();
|
|
75
|
+
let pending = "";
|
|
76
|
+
const rows = [];
|
|
77
|
+
const consume = (line) => {
|
|
78
|
+
if (!line)
|
|
79
|
+
return;
|
|
80
|
+
if (new TextEncoder().encode(line).byteLength > MAX_EVENT_LINE_BYTES)
|
|
81
|
+
throw new Error("event sync: event line exceeds 1 MiB");
|
|
82
|
+
rows.push({ event: parseEvent(JSON.parse(line)), line });
|
|
83
|
+
};
|
|
84
|
+
for (;;) {
|
|
85
|
+
const { done, value } = await reader.read();
|
|
86
|
+
pending += decoder.decode(value, { stream: !done });
|
|
87
|
+
let newline = pending.indexOf("\n");
|
|
88
|
+
while (newline >= 0) {
|
|
89
|
+
consume(pending.slice(0, newline));
|
|
90
|
+
pending = pending.slice(newline + 1);
|
|
91
|
+
newline = pending.indexOf("\n");
|
|
92
|
+
}
|
|
93
|
+
if (pending.length > MAX_EVENT_LINE_BYTES)
|
|
94
|
+
throw new Error("event sync: event line exceeds 1 MiB");
|
|
95
|
+
if (done)
|
|
96
|
+
break;
|
|
97
|
+
}
|
|
98
|
+
if (pending)
|
|
99
|
+
consume(pending);
|
|
100
|
+
return rows;
|
|
101
|
+
}
|
|
102
|
+
function segmentName(date, index = 0) {
|
|
103
|
+
const day = date.toISOString().slice(0, 10);
|
|
104
|
+
return index === 0
|
|
105
|
+
? `${day}.jsonl`
|
|
106
|
+
: `${day}-${String(index).padStart(3, "0")}.jsonl`;
|
|
107
|
+
}
|
|
108
|
+
async function writeJsonAtomic(path, value) {
|
|
109
|
+
const pid = globalThis.process?.pid ?? 0;
|
|
110
|
+
const temporary = `${path}.${pid}.tmp`;
|
|
111
|
+
await writeFile(temporary, JSON.stringify(value) + "\n", { mode: 0o600 });
|
|
112
|
+
await rename(temporary, path);
|
|
113
|
+
}
|
|
114
|
+
async function readCursor(path) {
|
|
115
|
+
try {
|
|
116
|
+
const value = JSON.parse(await readFile(path, "utf8"));
|
|
117
|
+
return typeof value.cursor === "number" &&
|
|
118
|
+
Number.isSafeInteger(value.cursor) &&
|
|
119
|
+
value.cursor >= 0
|
|
120
|
+
? {
|
|
121
|
+
cursor: value.cursor,
|
|
122
|
+
floor: typeof value.floor === "number" &&
|
|
123
|
+
Number.isSafeInteger(value.floor)
|
|
124
|
+
? value.floor
|
|
125
|
+
: -1,
|
|
126
|
+
}
|
|
127
|
+
: null;
|
|
128
|
+
}
|
|
129
|
+
catch (error) {
|
|
130
|
+
if (error.code === "ENOENT")
|
|
131
|
+
return null;
|
|
132
|
+
throw error;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
async function repairTail(directory) {
|
|
136
|
+
const segments = (await readdir(directory))
|
|
137
|
+
.filter((name) => SEGMENT_PATTERN.test(name))
|
|
138
|
+
.sort();
|
|
139
|
+
for (const name of segments.reverse()) {
|
|
140
|
+
const path = join(directory, name);
|
|
141
|
+
const bytes = await readFile(path);
|
|
142
|
+
if (bytes.length === 0)
|
|
143
|
+
continue;
|
|
144
|
+
const lastNewline = bytes.lastIndexOf(10);
|
|
145
|
+
if (lastNewline !== bytes.length - 1)
|
|
146
|
+
await truncate(path, lastNewline < 0 ? 0 : lastNewline + 1);
|
|
147
|
+
const complete = bytes
|
|
148
|
+
.subarray(0, lastNewline < 0 ? 0 : lastNewline)
|
|
149
|
+
.toString("utf8")
|
|
150
|
+
.trimEnd();
|
|
151
|
+
const line = complete.slice(complete.lastIndexOf("\n") + 1);
|
|
152
|
+
if (line)
|
|
153
|
+
return parseEvent(JSON.parse(line)).sequence;
|
|
154
|
+
}
|
|
155
|
+
return null;
|
|
156
|
+
}
|
|
157
|
+
async function retainBoundedSegments(directory, now, retainDays, maxBytes, current, floor) {
|
|
158
|
+
const segments = (await readdir(directory))
|
|
159
|
+
.filter((name) => SEGMENT_PATTERN.test(name))
|
|
160
|
+
.sort();
|
|
161
|
+
const sizes = new Map();
|
|
162
|
+
for (const name of segments)
|
|
163
|
+
sizes.set(name, (await stat(join(directory, name))).size);
|
|
164
|
+
let total = [...sizes.values()].reduce((sum, size) => sum + size, 0);
|
|
165
|
+
const cutoff = new Date(now);
|
|
166
|
+
cutoff.setUTCDate(cutoff.getUTCDate() - retainDays);
|
|
167
|
+
const remove = [];
|
|
168
|
+
for (const name of segments) {
|
|
169
|
+
if (name === current)
|
|
170
|
+
continue;
|
|
171
|
+
const expired = name.slice(0, 10) < cutoff.toISOString().slice(0, 10);
|
|
172
|
+
if (!expired && total <= maxBytes)
|
|
173
|
+
continue;
|
|
174
|
+
remove.push(name);
|
|
175
|
+
total -= sizes.get(name) ?? 0;
|
|
176
|
+
}
|
|
177
|
+
for (const name of remove) {
|
|
178
|
+
const body = await readFile(join(directory, name), "utf8");
|
|
179
|
+
const lines = body.trimEnd().split("\n");
|
|
180
|
+
const last = lines.at(-1);
|
|
181
|
+
if (last)
|
|
182
|
+
floor = Math.max(floor, parseEvent(JSON.parse(last)).sequence);
|
|
183
|
+
}
|
|
184
|
+
await Promise.all(remove.map((name) => rm(join(directory, name), { force: true })));
|
|
185
|
+
return floor;
|
|
186
|
+
}
|
|
187
|
+
async function appendBoundedRows(directory, date, rows, maxBytes) {
|
|
188
|
+
if (!Number.isSafeInteger(maxBytes) || maxBytes < MAX_EVENT_LINE_BYTES)
|
|
189
|
+
throw new Error("event sync: maxCacheBytes must be at least 1 MiB");
|
|
190
|
+
const day = date.toISOString().slice(0, 10);
|
|
191
|
+
const existing = (await readdir(directory))
|
|
192
|
+
.filter((name) => name.startsWith(day) && SEGMENT_PATTERN.test(name))
|
|
193
|
+
.sort();
|
|
194
|
+
let index = existing.length === 0 ? 0 : existing.length - 1;
|
|
195
|
+
let name = segmentName(date, index);
|
|
196
|
+
let size = 0;
|
|
197
|
+
try {
|
|
198
|
+
size = (await stat(join(directory, name))).size;
|
|
199
|
+
}
|
|
200
|
+
catch (error) {
|
|
201
|
+
if (error.code !== "ENOENT")
|
|
202
|
+
throw error;
|
|
203
|
+
}
|
|
204
|
+
let handle = await open(join(directory, name), "a", 0o600);
|
|
205
|
+
try {
|
|
206
|
+
for (const row of rows) {
|
|
207
|
+
const line = `${row.line}\n`;
|
|
208
|
+
const bytes = new TextEncoder().encode(line).byteLength;
|
|
209
|
+
if (size > 0 && size + bytes > maxBytes) {
|
|
210
|
+
await handle.sync();
|
|
211
|
+
await handle.close();
|
|
212
|
+
name = segmentName(date, ++index);
|
|
213
|
+
handle = await open(join(directory, name), "a", 0o600);
|
|
214
|
+
size = 0;
|
|
215
|
+
}
|
|
216
|
+
await handle.write(line);
|
|
217
|
+
size += bytes;
|
|
218
|
+
}
|
|
219
|
+
await handle.sync();
|
|
220
|
+
}
|
|
221
|
+
finally {
|
|
222
|
+
await handle.close();
|
|
223
|
+
}
|
|
224
|
+
return name;
|
|
225
|
+
}
|
|
226
|
+
function abortableSleep(ms, signal) {
|
|
227
|
+
return new Promise((resolve, reject) => {
|
|
228
|
+
if (signal.aborted) {
|
|
229
|
+
reject(signal.reason);
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
const finish = () => {
|
|
233
|
+
signal.removeEventListener("abort", abort);
|
|
234
|
+
resolve();
|
|
235
|
+
};
|
|
236
|
+
const timer = setTimeout(finish, ms);
|
|
237
|
+
const abort = () => {
|
|
238
|
+
clearTimeout(timer);
|
|
239
|
+
signal.removeEventListener("abort", abort);
|
|
240
|
+
reject(signal.reason);
|
|
241
|
+
};
|
|
242
|
+
signal.addEventListener("abort", abort, { once: true });
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
export class CatalystEventSync {
|
|
246
|
+
options;
|
|
247
|
+
paths;
|
|
248
|
+
fetchImpl;
|
|
249
|
+
now;
|
|
250
|
+
sleeper;
|
|
251
|
+
lock = null;
|
|
252
|
+
controller = null;
|
|
253
|
+
running = null;
|
|
254
|
+
recoveredCursor = null;
|
|
255
|
+
floor = -1;
|
|
256
|
+
current = {
|
|
257
|
+
state: "stopped",
|
|
258
|
+
cursor: null,
|
|
259
|
+
head: null,
|
|
260
|
+
lastSyncAt: null,
|
|
261
|
+
error: null,
|
|
262
|
+
};
|
|
263
|
+
constructor(options) {
|
|
264
|
+
this.options = options;
|
|
265
|
+
this.paths = eventCachePaths(options.tenantId, options.directory);
|
|
266
|
+
this.fetchImpl = options.fetch ?? fetch;
|
|
267
|
+
this.now = options.now ?? (() => new Date());
|
|
268
|
+
this.sleeper = options.sleep ?? abortableSleep;
|
|
269
|
+
}
|
|
270
|
+
status() {
|
|
271
|
+
return { ...this.current };
|
|
272
|
+
}
|
|
273
|
+
async syncOnce(signal = new AbortController().signal) {
|
|
274
|
+
await mkdir(this.paths.directory, { recursive: true, mode: 0o700 });
|
|
275
|
+
if (!this.lock) {
|
|
276
|
+
this.lock = claimWriterLock(this.paths.lock, this.options.writerGuard ?? {});
|
|
277
|
+
this.recoveredCursor = await repairTail(this.paths.directory);
|
|
278
|
+
}
|
|
279
|
+
this.current = { ...this.current, state: "syncing", error: null };
|
|
280
|
+
const checkpoint = await readCursor(this.paths.cursor);
|
|
281
|
+
this.floor = Math.max(this.floor, checkpoint?.floor ?? -1);
|
|
282
|
+
let cursor = Math.max(checkpoint?.cursor ?? -1, this.recoveredCursor ?? -1, this.current.cursor ?? -1);
|
|
283
|
+
if (cursor < 0) {
|
|
284
|
+
cursor = await this.readCurrentHead(signal);
|
|
285
|
+
this.floor = cursor;
|
|
286
|
+
}
|
|
287
|
+
const result = await this.readPage(cursor, signal);
|
|
288
|
+
const now = this.now();
|
|
289
|
+
const maxCacheBytes = this.options.maxCacheBytes ?? DEFAULT_MAX_CACHE_BYTES;
|
|
290
|
+
let segment = segmentName(now);
|
|
291
|
+
if (result.rows.length > 0) {
|
|
292
|
+
segment = await appendBoundedRows(this.paths.directory, now, result.rows, maxCacheBytes);
|
|
293
|
+
cursor = result.rows[result.rows.length - 1].event.sequence;
|
|
294
|
+
this.recoveredCursor = cursor;
|
|
295
|
+
}
|
|
296
|
+
this.floor = await retainBoundedSegments(this.paths.directory, now, this.options.retainDays ?? DEFAULT_RETAIN_DAYS, maxCacheBytes, segment, this.floor);
|
|
297
|
+
await writeJsonAtomic(this.paths.cursor, {
|
|
298
|
+
version: 1,
|
|
299
|
+
cursor,
|
|
300
|
+
floor: this.floor,
|
|
301
|
+
});
|
|
302
|
+
this.current = {
|
|
303
|
+
state: "idle",
|
|
304
|
+
cursor,
|
|
305
|
+
head: result.head,
|
|
306
|
+
lastSyncAt: this.now().toISOString(),
|
|
307
|
+
error: null,
|
|
308
|
+
};
|
|
309
|
+
return { appended: result.rows.length, cursor, head: result.head };
|
|
310
|
+
}
|
|
311
|
+
start() {
|
|
312
|
+
if (this.running)
|
|
313
|
+
return this.running;
|
|
314
|
+
this.controller = new AbortController();
|
|
315
|
+
this.running = this.loop(this.controller.signal).finally(() => {
|
|
316
|
+
if (this.current.state !== "failed")
|
|
317
|
+
this.current = { ...this.current, state: "stopped" };
|
|
318
|
+
this.lock?.release();
|
|
319
|
+
this.lock = null;
|
|
320
|
+
this.recoveredCursor = null;
|
|
321
|
+
this.running = null;
|
|
322
|
+
this.controller = null;
|
|
323
|
+
});
|
|
324
|
+
return this.running;
|
|
325
|
+
}
|
|
326
|
+
async stop() {
|
|
327
|
+
const controller = this.controller;
|
|
328
|
+
if (!this.running) {
|
|
329
|
+
this.lock?.release();
|
|
330
|
+
this.lock = null;
|
|
331
|
+
this.current = { ...this.current, state: "stopped" };
|
|
332
|
+
return;
|
|
333
|
+
}
|
|
334
|
+
controller?.abort(new Error("event sync stopped"));
|
|
335
|
+
try {
|
|
336
|
+
await this.running;
|
|
337
|
+
}
|
|
338
|
+
catch (error) {
|
|
339
|
+
if (!controller?.signal.aborted)
|
|
340
|
+
throw error;
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
async loop(signal) {
|
|
344
|
+
let idle = this.options.idleMinMs ?? DEFAULT_IDLE_MIN_MS;
|
|
345
|
+
const maxIdle = this.options.idleMaxMs ?? DEFAULT_IDLE_MAX_MS;
|
|
346
|
+
try {
|
|
347
|
+
while (!signal.aborted) {
|
|
348
|
+
try {
|
|
349
|
+
const result = await this.syncOnce(signal);
|
|
350
|
+
idle =
|
|
351
|
+
result.appended > 0
|
|
352
|
+
? (this.options.idleMinMs ?? DEFAULT_IDLE_MIN_MS)
|
|
353
|
+
: Math.min(maxIdle, idle * 2);
|
|
354
|
+
}
|
|
355
|
+
catch (error) {
|
|
356
|
+
if (error instanceof EventHistoryGapError ||
|
|
357
|
+
(error instanceof EventSyncHttpError && error.status < 500))
|
|
358
|
+
throw error;
|
|
359
|
+
this.current = {
|
|
360
|
+
...this.current,
|
|
361
|
+
state: "idle",
|
|
362
|
+
error: error instanceof Error ? error.message : String(error),
|
|
363
|
+
};
|
|
364
|
+
idle = Math.min(maxIdle, idle * 2);
|
|
365
|
+
}
|
|
366
|
+
await this.sleeper(idle, signal);
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
catch (error) {
|
|
370
|
+
if (signal.aborted)
|
|
371
|
+
return;
|
|
372
|
+
this.current = {
|
|
373
|
+
...this.current,
|
|
374
|
+
state: "failed",
|
|
375
|
+
error: error instanceof Error ? error.message : String(error),
|
|
376
|
+
};
|
|
377
|
+
throw error;
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
async request(since, signal) {
|
|
381
|
+
const timeout = AbortSignal.timeout(this.options.requestTimeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS);
|
|
382
|
+
const token = this.options.auth.kind === "token"
|
|
383
|
+
? this.options.auth.token
|
|
384
|
+
: await this.options.auth.getToken();
|
|
385
|
+
return this.fetchImpl(`${this.options.baseUrl.replace(/\/$/, "")}/api/v1/events/backbone?since=${since}`, {
|
|
386
|
+
headers: { authorization: `Bearer ${token}` },
|
|
387
|
+
signal: AbortSignal.any([signal, timeout]),
|
|
388
|
+
});
|
|
389
|
+
}
|
|
390
|
+
async readCurrentHead(signal) {
|
|
391
|
+
const response = await this.request(Number.MAX_SAFE_INTEGER, signal);
|
|
392
|
+
if (response.status !== 409)
|
|
393
|
+
throw new EventSyncHttpError(response.status);
|
|
394
|
+
const body = (await response.json());
|
|
395
|
+
if (body.error !== "cursor_ahead_of_head")
|
|
396
|
+
throw new Error("event sync: head bootstrap contract mismatch");
|
|
397
|
+
return positiveInteger(body.resumeFrom, "bootstrap cursor");
|
|
398
|
+
}
|
|
399
|
+
async readPage(cursor, signal) {
|
|
400
|
+
const response = await this.request(cursor, signal);
|
|
401
|
+
if (!response.ok && response.status !== 409)
|
|
402
|
+
throw new EventSyncHttpError(response.status);
|
|
403
|
+
const head = positiveInteger(response.headers.get(HEAD_HEADER), "head header");
|
|
404
|
+
if (response.status === 409) {
|
|
405
|
+
const body = (await response.json());
|
|
406
|
+
throw new EventHistoryGapError("event sync: durable history has a gap", head, positiveInteger(body.resumeFrom, "resume cursor"), typeof body.reason === "string"
|
|
407
|
+
? body.reason
|
|
408
|
+
: String(body.error ?? "cursor_refused"));
|
|
409
|
+
}
|
|
410
|
+
const rows = await readNdjson(response);
|
|
411
|
+
let previous = cursor;
|
|
412
|
+
for (const row of rows) {
|
|
413
|
+
if (row.event.tenantId !== this.options.tenantId)
|
|
414
|
+
throw new Error("event sync: tenant mismatch");
|
|
415
|
+
if (row.event.sequence <= previous)
|
|
416
|
+
throw new Error("event sync: non-monotonic sequence");
|
|
417
|
+
previous = row.event.sequence;
|
|
418
|
+
}
|
|
419
|
+
return { head, rows };
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
export async function readCachedEvents(options) {
|
|
423
|
+
const { directory } = eventCachePaths(options.tenantId, options.directory);
|
|
424
|
+
const checkpoint = await readCursor(eventCachePaths(options.tenantId, options.directory).cursor);
|
|
425
|
+
if (options.after !== undefined &&
|
|
426
|
+
checkpoint &&
|
|
427
|
+
options.after < checkpoint.floor)
|
|
428
|
+
throw new EventHistoryGapError("event cache: requested sequence precedes retained history", checkpoint.cursor, checkpoint.floor, "local-retention");
|
|
429
|
+
let names;
|
|
430
|
+
try {
|
|
431
|
+
names = (await readdir(directory))
|
|
432
|
+
.filter((name) => SEGMENT_PATTERN.test(name))
|
|
433
|
+
.sort();
|
|
434
|
+
}
|
|
435
|
+
catch (error) {
|
|
436
|
+
if (error.code === "ENOENT")
|
|
437
|
+
return [];
|
|
438
|
+
throw error;
|
|
439
|
+
}
|
|
440
|
+
const events = [];
|
|
441
|
+
for (const name of names) {
|
|
442
|
+
const body = await readFile(join(directory, name), "utf8");
|
|
443
|
+
const complete = body.endsWith("\n")
|
|
444
|
+
? body.slice(0, -1)
|
|
445
|
+
: body.slice(0, body.lastIndexOf("\n") + 1);
|
|
446
|
+
for (const line of complete.split("\n")) {
|
|
447
|
+
if (!line)
|
|
448
|
+
continue;
|
|
449
|
+
const event = parseEvent(JSON.parse(line));
|
|
450
|
+
if (event.sequence > (options.after ?? -1))
|
|
451
|
+
events.push(event);
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
return events;
|
|
455
|
+
}
|
|
456
|
+
export async function* tailCachedEvents(options) {
|
|
457
|
+
const paths = eventCachePaths(options.tenantId, options.directory);
|
|
458
|
+
const { directory } = paths;
|
|
459
|
+
let cursor = options.after ?? (await readCursor(paths.cursor))?.cursor ?? -1;
|
|
460
|
+
const emit = async () => {
|
|
461
|
+
const rows = await readCachedEvents({ ...options, after: cursor });
|
|
462
|
+
if (rows.length > 0)
|
|
463
|
+
cursor = rows[rows.length - 1].sequence;
|
|
464
|
+
return rows;
|
|
465
|
+
};
|
|
466
|
+
const changes = watch(directory, { signal: options.signal })[Symbol.asyncIterator]();
|
|
467
|
+
const nextChange = () => changes.next().then((value) => ({ value }), (error) => ({ error }));
|
|
468
|
+
let pending = nextChange();
|
|
469
|
+
try {
|
|
470
|
+
for (const event of await emit())
|
|
471
|
+
yield event;
|
|
472
|
+
for (;;) {
|
|
473
|
+
const outcome = await pending;
|
|
474
|
+
if ("error" in outcome)
|
|
475
|
+
throw outcome.error;
|
|
476
|
+
const change = outcome.value;
|
|
477
|
+
if (change.done)
|
|
478
|
+
return;
|
|
479
|
+
pending = nextChange();
|
|
480
|
+
for (const event of await emit())
|
|
481
|
+
yield event;
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
finally {
|
|
485
|
+
await changes.return?.();
|
|
486
|
+
await pending;
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
export function eventIdentity(event) {
|
|
490
|
+
return JSON.stringify([event.tenantId, event.sequence, event.eventId]);
|
|
491
|
+
}
|
|
492
|
+
//# sourceMappingURL=events.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events.js","sourceRoot":"","sources":["../src/events.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { LiveSyncClient, AuthError, CLOSE_REAUTHENTICATE, buildConnectUrl, parseFrame, toWsOrigin, type AuthStrategy, type LiveSyncClientOptions, type LiveSyncStatus, type LogLevel, type WebSocketLike, type WebSocketFactory, } from "./live-sync-client.js";
|
|
2
|
-
export { ENTITY_NAMES, CHANGE_OPS, PING_FRAME, PONG_FRAME, type AccountId, type EntityName, type ChangeOp, type ChangeFrame, type ResyncFrame, type SyncFrame, type PongFrame, type HeadFrame, type ServerFrame, } from "./types.js";
|
|
2
|
+
export { ENTITY_NAMES, CHANGE_OPS, PING_FRAME, PONG_FRAME, type AccountId, type EntityName, type ChangeOp, type ChangeFrame, type ResyncFrame, type SyncFrame, type PongFrame, type HeadFrame, type SkipFrame, type ServerFrame, } from "./types.js";
|
|
3
3
|
export { DEFAULT_SCOPE_NAME, CATALYST_ATTR, REPLICA_METRIC, REPLICA_LOG, REPLICA_SPAN, REPLICA_STATUS_CODE, type ReplicaApplyResult, type ReplicaGapEvent, type TelemetryConfig, } from "./otel.js";
|
|
4
4
|
export { createTenantClient, memoryContractCache, normalizeBaseUrl, DEFAULT_TIMEOUT_MS, NEXT_CURSOR_HEADER, HEAD_SEQ_HEADER, TOTAL_HEADER, BLOCKED_ON_ASK_TOTAL_HEADER, CONTRACT_VERSION_HEADER, type TenantClient, type TenantClientOptions, type TenantClientFailure, type ContractCacheEntry, type ContractCacheStore, type ContractOptions, type ContractResult, type ContractFailure, pageCursor, type PageCursor, type KeysetPageMeta, type IssueListParams, type IssueListResult, type IssueGetResult, type PullListParams, type PullListResult, type PullGetResult, type ProjectListParams, type ProjectListResult, type MeResult, type AgentRouteName, type AgentCallFailure, type ProxiedWriteOutcome, type ProxiedWriteBody, type IssueStateInput, type IssueStateResult, type IssueLabelInput, type IssueLabelItemResult, type IssueLabelResult, type IssueCommentInput, type IssueCommentResult, type IssueCreateInput, type IssueCreateResult, type ReactionInput, type ReactionResult, type ProxiedAttachment, type AttachmentInput, type AttachmentResult, type AttachmentsResult, type SessionPlanEntry, type SessionActivity, type SessionInput, type EnsureSessionOutcome, type SessionResult, type AskInput, type AskResult, type AskAcceptInput, type AskAcceptRefusal, type AskAcceptResult, } from "./tenant-client.js";
|
|
5
5
|
export { CONTRACT_ROUTE, TENANT_CONTRACT_KEYS, isTenantContract, readTenantContract, routeByName, teamByKey, teamForTicket, stageIdForSlot, labelIdFor, type TenantContract, type WorkflowSlot, type LabelScopeKind, type ContractLabel, type ContractStage, type ContractReadinessCheck, type ContractTeam, type ContractRoute, type ContractMergeRepository, type ContractMergeCleanPassShape, type ContractAdvanceRule, type TeamLookup, type StageLookup, type LabelLookup, } from "./tenant-contract.js";
|