@gscdump/engine 0.40.2 → 1.0.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 +4 -4
- package/dist/_chunks/duckdb.d.mts +2 -9
- package/dist/_chunks/engine.mjs +3 -7
- package/dist/_chunks/entities.mjs +1 -1
- package/dist/_chunks/index.d.mts +3 -8
- package/dist/_chunks/index2.d.mts +1 -2
- package/dist/_chunks/libs/hyparquet-compressors.mjs +1 -1
- package/dist/_chunks/libs/hyparquet.mjs +1 -63
- package/dist/_chunks/libs/icebird.d.mts +1 -81
- package/dist/_chunks/libs/icebird.mjs +4 -330
- package/dist/_chunks/parquet-plan.mjs +248 -3
- package/dist/_chunks/resolver.mjs +16 -2
- package/dist/_chunks/schema.d.mts +2 -2
- package/dist/_chunks/sink.d.mts +4 -5
- package/dist/_chunks/source.mjs +3 -3
- package/dist/_chunks/storage.d.mts +1 -43
- package/dist/_chunks/types.d.mts +8 -0
- package/dist/adapters/node.d.mts +1 -11
- package/dist/adapters/node.mjs +1 -1
- package/dist/analyzer/index.d.mts +1 -1
- package/dist/entities.d.mts +2 -10
- package/dist/entities.mjs +2 -2
- package/dist/iceberg/index.d.mts +2 -3
- package/dist/iceberg/index.mjs +12 -12
- package/dist/index.d.mts +83 -2
- package/dist/index.mjs +365 -6
- package/dist/period/index.d.mts +2 -2
- package/dist/period/index.mjs +1 -1
- package/dist/planner.mjs +1 -2
- package/dist/resolver/index.d.mts +2 -9
- package/dist/resolver/index.mjs +2 -2
- package/dist/rollups.d.mts +3 -20
- package/dist/rollups.mjs +5 -5
- package/dist/scope.d.mts +1 -2
- package/dist/scope.mjs +1 -1
- package/dist/source/index.d.mts +2 -2
- package/dist/source/index.mjs +2 -2
- package/dist/sql-bind.d.mts +1 -29
- package/dist/sql-bind.mjs +1 -1
- package/package.json +7 -22
- package/dist/_chunks/compaction.mjs +0 -251
- package/dist/adapters/r2-manifest.d.mts +0 -82
- package/dist/adapters/r2-manifest.mjs +0 -364
- package/dist/compaction-public.d.mts +0 -15
- package/dist/compaction-public.mjs +0 -5
- package/dist/snapshot.d.mts +0 -2
- package/dist/snapshot.mjs +0 -1
|
@@ -1,364 +0,0 @@
|
|
|
1
|
-
import { inferSearchType } from "../_chunks/layout.mjs";
|
|
2
|
-
import { engineErrorToException, engineErrors } from "../errors.mjs";
|
|
3
|
-
import { matchesManifestEntryFilter, matchesSyncStateFilter, matchesWatermarkFilter } from "../_chunks/manifest-store-utils.mjs";
|
|
4
|
-
import { err, ok, unwrapResult } from "gscdump/result";
|
|
5
|
-
const SHARD_RE = /^u_[^/]+\/manifest\/(?<siteId>[^/]+)\/(?<table>[^/]+)\/HEAD$/;
|
|
6
|
-
const CAS_BACKOFF_BASE_MS = 5;
|
|
7
|
-
const CAS_BACKOFF_CAP_MS = 250;
|
|
8
|
-
const SHARD_IO_CONCURRENCY = 8;
|
|
9
|
-
const R2_DELETE_BATCH_SIZE = 1e3;
|
|
10
|
-
async function casBackoff(attempt) {
|
|
11
|
-
const ceil = Math.min(CAS_BACKOFF_CAP_MS, CAS_BACKOFF_BASE_MS * 2 ** attempt);
|
|
12
|
-
await new Promise((resolve) => setTimeout(resolve, Math.random() * ceil));
|
|
13
|
-
}
|
|
14
|
-
async function mapWithConcurrency(items, concurrency, fn) {
|
|
15
|
-
if (items.length === 0) return [];
|
|
16
|
-
const workerCount = Math.max(1, Math.min(items.length, Math.floor(concurrency)));
|
|
17
|
-
const results = Array.from({ length: items.length }, () => void 0);
|
|
18
|
-
let nextIndex = 0;
|
|
19
|
-
async function worker() {
|
|
20
|
-
while (true) {
|
|
21
|
-
const index = nextIndex++;
|
|
22
|
-
if (index >= items.length) return;
|
|
23
|
-
results[index] = await fn(items[index], index);
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
await Promise.all(Array.from({ length: workerCount }, worker));
|
|
27
|
-
return results;
|
|
28
|
-
}
|
|
29
|
-
function defaultSnapshotId() {
|
|
30
|
-
return `${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;
|
|
31
|
-
}
|
|
32
|
-
function shardPrefix(userId, siteId, table) {
|
|
33
|
-
return `u_${userId}/manifest/${siteId}/${table}/`;
|
|
34
|
-
}
|
|
35
|
-
function headKey(userId, siteId, table) {
|
|
36
|
-
return `${shardPrefix(userId, siteId, table)}HEAD`;
|
|
37
|
-
}
|
|
38
|
-
function snapshotKey(userId, siteId, table, snapshotId) {
|
|
39
|
-
return `${shardPrefix(userId, siteId, table)}v${snapshotId}.json`;
|
|
40
|
-
}
|
|
41
|
-
function emptySnapshot() {
|
|
42
|
-
return {
|
|
43
|
-
version: 1,
|
|
44
|
-
entries: [],
|
|
45
|
-
watermarks: [],
|
|
46
|
-
syncStates: []
|
|
47
|
-
};
|
|
48
|
-
}
|
|
49
|
-
function shardScopesFromEntries(entries) {
|
|
50
|
-
const out = /* @__PURE__ */ new Set();
|
|
51
|
-
for (const e of entries) {
|
|
52
|
-
if (e.siteId === void 0) throw new Error("R2 manifest store requires entries to carry siteId; cross-site entries are unshardable");
|
|
53
|
-
out.add(`${e.siteId}\0${e.table}`);
|
|
54
|
-
}
|
|
55
|
-
return out;
|
|
56
|
-
}
|
|
57
|
-
function createR2ManifestStore(opts) {
|
|
58
|
-
const { bucket, userId } = opts;
|
|
59
|
-
const newSnapshotId = opts.newSnapshotId ?? defaultSnapshotId;
|
|
60
|
-
const now = opts.now ?? (() => Date.now());
|
|
61
|
-
const maxRetries = opts.maxRetries ?? 16;
|
|
62
|
-
const onEvent = opts.onEvent;
|
|
63
|
-
async function readShard(siteId, table) {
|
|
64
|
-
const head = await bucket.get(headKey(userId, siteId, table));
|
|
65
|
-
if (!head) return {
|
|
66
|
-
snapshot: emptySnapshot(),
|
|
67
|
-
headEtag: void 0
|
|
68
|
-
};
|
|
69
|
-
const snapshotId = (await head.text()).trim();
|
|
70
|
-
if (!snapshotId) return {
|
|
71
|
-
snapshot: emptySnapshot(),
|
|
72
|
-
headEtag: head.etag
|
|
73
|
-
};
|
|
74
|
-
const snap = await bucket.get(snapshotKey(userId, siteId, table, snapshotId));
|
|
75
|
-
if (!snap) return {
|
|
76
|
-
snapshot: emptySnapshot(),
|
|
77
|
-
headEtag: head.etag
|
|
78
|
-
};
|
|
79
|
-
const parsed = JSON.parse(await snap.text());
|
|
80
|
-
if (parsed.version !== 1) throw new Error(`unsupported manifest snapshot version: ${parsed.version}`);
|
|
81
|
-
return {
|
|
82
|
-
snapshot: parsed,
|
|
83
|
-
headEtag: head.etag
|
|
84
|
-
};
|
|
85
|
-
}
|
|
86
|
-
async function writeShardResult(siteId, table, snapshot, headEtag, attempt) {
|
|
87
|
-
const id = newSnapshotId();
|
|
88
|
-
const snapKey = snapshotKey(userId, siteId, table, id);
|
|
89
|
-
await bucket.put(snapKey, JSON.stringify(snapshot));
|
|
90
|
-
const conditional = headEtag ? { onlyIf: { etagMatches: headEtag } } : { onlyIf: { etagDoesNotMatch: "*" } };
|
|
91
|
-
return await bucket.put(headKey(userId, siteId, table), id, conditional) !== null ? ok(void 0) : err(engineErrors.manifestCasRoundLost(siteId, table, attempt));
|
|
92
|
-
}
|
|
93
|
-
async function mutateShardResult(siteId, table, mutate) {
|
|
94
|
-
let attempt = 0;
|
|
95
|
-
while (attempt < maxRetries) {
|
|
96
|
-
onEvent?.({
|
|
97
|
-
kind: "cas-attempt",
|
|
98
|
-
siteId,
|
|
99
|
-
table,
|
|
100
|
-
attempt
|
|
101
|
-
});
|
|
102
|
-
const { snapshot, headEtag } = await readShard(siteId, table);
|
|
103
|
-
await mutate(snapshot);
|
|
104
|
-
const round = await writeShardResult(siteId, table, snapshot, headEtag, attempt);
|
|
105
|
-
if (round.ok) {
|
|
106
|
-
onEvent?.({
|
|
107
|
-
kind: "cas-committed",
|
|
108
|
-
siteId,
|
|
109
|
-
table,
|
|
110
|
-
attempts: attempt + 1
|
|
111
|
-
});
|
|
112
|
-
return round;
|
|
113
|
-
}
|
|
114
|
-
onEvent?.({
|
|
115
|
-
kind: "cas-rejected",
|
|
116
|
-
siteId,
|
|
117
|
-
table,
|
|
118
|
-
attempt
|
|
119
|
-
});
|
|
120
|
-
attempt++;
|
|
121
|
-
if (attempt < maxRetries) await casBackoff(attempt);
|
|
122
|
-
}
|
|
123
|
-
return err(engineErrors.manifestCasExhausted(siteId, table, maxRetries));
|
|
124
|
-
}
|
|
125
|
-
async function mutateShard(siteId, table, mutate) {
|
|
126
|
-
return unwrapResult(await mutateShardResult(siteId, table, mutate), engineErrorToException);
|
|
127
|
-
}
|
|
128
|
-
async function listShards(siteId) {
|
|
129
|
-
const shards = [];
|
|
130
|
-
let cursor;
|
|
131
|
-
const prefix = siteId === void 0 ? `u_${userId}/manifest/` : `u_${userId}/manifest/${siteId}/`;
|
|
132
|
-
do {
|
|
133
|
-
const res = await bucket.list({
|
|
134
|
-
prefix,
|
|
135
|
-
cursor,
|
|
136
|
-
limit: 1e3
|
|
137
|
-
});
|
|
138
|
-
for (const obj of res.objects) {
|
|
139
|
-
const m = SHARD_RE.exec(obj.key);
|
|
140
|
-
if (m?.groups) shards.push({
|
|
141
|
-
siteId: m.groups.siteId,
|
|
142
|
-
table: m.groups.table
|
|
143
|
-
});
|
|
144
|
-
}
|
|
145
|
-
cursor = res.truncated ? res.cursor : void 0;
|
|
146
|
-
} while (cursor);
|
|
147
|
-
return shards;
|
|
148
|
-
}
|
|
149
|
-
async function shardsForFilter(filter) {
|
|
150
|
-
if (filter.siteId !== void 0 && filter.table !== void 0) return [{
|
|
151
|
-
siteId: filter.siteId,
|
|
152
|
-
table: filter.table
|
|
153
|
-
}];
|
|
154
|
-
return (await listShards(filter.siteId)).filter((s) => (filter.siteId === void 0 || s.siteId === filter.siteId) && (filter.table === void 0 || s.table === filter.table));
|
|
155
|
-
}
|
|
156
|
-
function assertScopedUser(got, op) {
|
|
157
|
-
if (got !== userId) throw new Error(`${op}: R2 manifest store is scoped to userId=${userId}, got ${got}`);
|
|
158
|
-
}
|
|
159
|
-
async function readEntriesAcrossShards(filter, includeRetired) {
|
|
160
|
-
assertScopedUser(filter.userId, includeRetired ? "listAll" : "listLive");
|
|
161
|
-
return (await mapWithConcurrency(await shardsForFilter(filter), SHARD_IO_CONCURRENCY, async ({ siteId, table }) => {
|
|
162
|
-
const { snapshot } = await readShard(siteId, table);
|
|
163
|
-
const entries = [];
|
|
164
|
-
for (const entry of snapshot.entries) {
|
|
165
|
-
if (!includeRetired && entry.retiredAt !== void 0) continue;
|
|
166
|
-
if (matchesManifestEntryFilter(entry, filter, { ignoreUserId: true })) entries.push(entry);
|
|
167
|
-
}
|
|
168
|
-
return entries;
|
|
169
|
-
})).flat();
|
|
170
|
-
}
|
|
171
|
-
function groupBySiteTable(entries) {
|
|
172
|
-
const out = /* @__PURE__ */ new Map();
|
|
173
|
-
for (const e of entries) {
|
|
174
|
-
const key = `${e.siteId}\0${e.table}`;
|
|
175
|
-
if (!out.has(key)) out.set(key, []);
|
|
176
|
-
out.get(key).push(e);
|
|
177
|
-
}
|
|
178
|
-
return out;
|
|
179
|
-
}
|
|
180
|
-
async function registerVersionsImpl(newEntries, superseding) {
|
|
181
|
-
if (newEntries.length === 0 && (!superseding || superseding.length === 0)) return;
|
|
182
|
-
const supersededAt = newEntries[0]?.createdAt ?? now();
|
|
183
|
-
const byShard = /* @__PURE__ */ new Map();
|
|
184
|
-
function bucket(entry, kind) {
|
|
185
|
-
assertScopedUser(entry.userId, "registerVersions");
|
|
186
|
-
if (entry.siteId === void 0) throw new Error("R2 manifest store requires entries to carry siteId");
|
|
187
|
-
const key = `${entry.siteId}\0${entry.table}`;
|
|
188
|
-
let bag = byShard.get(key);
|
|
189
|
-
if (!bag) {
|
|
190
|
-
bag = {
|
|
191
|
-
newEntries: [],
|
|
192
|
-
superseding: []
|
|
193
|
-
};
|
|
194
|
-
byShard.set(key, bag);
|
|
195
|
-
}
|
|
196
|
-
if (kind === "new") bag.newEntries.push(entry);
|
|
197
|
-
else bag.superseding.push(entry);
|
|
198
|
-
}
|
|
199
|
-
for (const e of newEntries) bucket(e, "new");
|
|
200
|
-
if (superseding) for (const e of superseding) bucket(e, "super");
|
|
201
|
-
await mapWithConcurrency([...byShard], SHARD_IO_CONCURRENCY, async ([shardKey, { newEntries: news, superseding: supers }]) => {
|
|
202
|
-
const [siteId, table] = shardKey.split("\0");
|
|
203
|
-
await mutateShard(siteId, table, (snap) => {
|
|
204
|
-
const byObjectKey = new Map(snap.entries.map((e) => [e.objectKey, e]));
|
|
205
|
-
for (const s of supers) {
|
|
206
|
-
const existing = byObjectKey.get(s.objectKey);
|
|
207
|
-
if (existing && existing.retiredAt === void 0) byObjectKey.set(s.objectKey, {
|
|
208
|
-
...existing,
|
|
209
|
-
retiredAt: supersededAt
|
|
210
|
-
});
|
|
211
|
-
}
|
|
212
|
-
for (const n of news) byObjectKey.set(n.objectKey, n);
|
|
213
|
-
snap.entries = Array.from(byObjectKey.values());
|
|
214
|
-
});
|
|
215
|
-
});
|
|
216
|
-
}
|
|
217
|
-
return {
|
|
218
|
-
async listLive(filter) {
|
|
219
|
-
return readEntriesAcrossShards(filter, false);
|
|
220
|
-
},
|
|
221
|
-
async listAll(filter) {
|
|
222
|
-
return readEntriesAcrossShards(filter, true);
|
|
223
|
-
},
|
|
224
|
-
async registerVersion(entry, superseding) {
|
|
225
|
-
return registerVersionsImpl([entry], superseding);
|
|
226
|
-
},
|
|
227
|
-
async registerVersions(entries, superseding) {
|
|
228
|
-
shardScopesFromEntries(entries);
|
|
229
|
-
return registerVersionsImpl(entries, superseding);
|
|
230
|
-
},
|
|
231
|
-
async listRetired(olderThan) {
|
|
232
|
-
return (await mapWithConcurrency(await listShards(), SHARD_IO_CONCURRENCY, async ({ siteId, table }) => {
|
|
233
|
-
const { snapshot } = await readShard(siteId, table);
|
|
234
|
-
const retired = [];
|
|
235
|
-
for (const e of snapshot.entries) if (e.retiredAt !== void 0 && e.retiredAt <= olderThan) retired.push(e);
|
|
236
|
-
return retired;
|
|
237
|
-
})).flat();
|
|
238
|
-
},
|
|
239
|
-
async delete(toDelete) {
|
|
240
|
-
await mapWithConcurrency([...groupBySiteTable(toDelete)], SHARD_IO_CONCURRENCY, async ([shardKey, entries]) => {
|
|
241
|
-
const [siteId, table] = shardKey.split("\0");
|
|
242
|
-
await mutateShard(siteId, table, (snap) => {
|
|
243
|
-
const drop = new Set(entries.map((e) => e.objectKey));
|
|
244
|
-
snap.entries = snap.entries.filter((e) => !drop.has(e.objectKey));
|
|
245
|
-
});
|
|
246
|
-
});
|
|
247
|
-
},
|
|
248
|
-
async getWatermarks(filter) {
|
|
249
|
-
assertScopedUser(filter.userId, "getWatermarks");
|
|
250
|
-
return (await mapWithConcurrency(await shardsForFilter(filter), SHARD_IO_CONCURRENCY, async ({ siteId, table }) => {
|
|
251
|
-
const { snapshot } = await readShard(siteId, table);
|
|
252
|
-
const watermarks = [];
|
|
253
|
-
for (const w of snapshot.watermarks) if (matchesWatermarkFilter(w, filter, { ignoreUserId: true })) watermarks.push(w);
|
|
254
|
-
return watermarks;
|
|
255
|
-
})).flat();
|
|
256
|
-
},
|
|
257
|
-
async bumpWatermark(scope, date, at) {
|
|
258
|
-
assertScopedUser(scope.userId, "bumpWatermark");
|
|
259
|
-
if (scope.siteId === void 0) throw new Error("R2 manifest store requires watermarks to carry siteId");
|
|
260
|
-
const ts = at ?? now();
|
|
261
|
-
const scopeSearchType = inferSearchType(scope);
|
|
262
|
-
await mutateShard(scope.siteId, scope.table, (snap) => {
|
|
263
|
-
const idx = snap.watermarks.findIndex((w) => w.userId === userId && w.siteId === scope.siteId && w.table === scope.table && inferSearchType(w) === scopeSearchType);
|
|
264
|
-
if (idx === -1) {
|
|
265
|
-
snap.watermarks.push({
|
|
266
|
-
userId,
|
|
267
|
-
siteId: scope.siteId,
|
|
268
|
-
table: scope.table,
|
|
269
|
-
...scope.searchType !== void 0 ? { searchType: scope.searchType } : {},
|
|
270
|
-
newestDateSynced: date,
|
|
271
|
-
oldestDateSynced: date,
|
|
272
|
-
lastSyncAt: ts
|
|
273
|
-
});
|
|
274
|
-
return;
|
|
275
|
-
}
|
|
276
|
-
const w = snap.watermarks[idx];
|
|
277
|
-
const newest = date > w.newestDateSynced ? date : w.newestDateSynced;
|
|
278
|
-
const oldest = date < w.oldestDateSynced ? date : w.oldestDateSynced;
|
|
279
|
-
const lastSyncAt = ts > w.lastSyncAt ? ts : w.lastSyncAt;
|
|
280
|
-
snap.watermarks[idx] = {
|
|
281
|
-
...w,
|
|
282
|
-
newestDateSynced: newest,
|
|
283
|
-
oldestDateSynced: oldest,
|
|
284
|
-
lastSyncAt
|
|
285
|
-
};
|
|
286
|
-
});
|
|
287
|
-
},
|
|
288
|
-
async getSyncStates(filter) {
|
|
289
|
-
assertScopedUser(filter.userId, "getSyncStates");
|
|
290
|
-
return (await mapWithConcurrency(await shardsForFilter(filter), SHARD_IO_CONCURRENCY, async ({ siteId, table }) => {
|
|
291
|
-
const { snapshot } = await readShard(siteId, table);
|
|
292
|
-
const states = [];
|
|
293
|
-
for (const s of snapshot.syncStates) if (matchesSyncStateFilter(s, filter, { ignoreUserId: true })) states.push(s);
|
|
294
|
-
return states;
|
|
295
|
-
})).flat();
|
|
296
|
-
},
|
|
297
|
-
async setSyncState(scope, state, detail) {
|
|
298
|
-
assertScopedUser(scope.userId, "setSyncState");
|
|
299
|
-
if (scope.siteId === void 0) throw new Error("R2 manifest store requires sync states to carry siteId");
|
|
300
|
-
const at = detail?.at ?? now();
|
|
301
|
-
const scopeSearchType = inferSearchType(scope);
|
|
302
|
-
await mutateShard(scope.siteId, scope.table, (snap) => {
|
|
303
|
-
const idx = snap.syncStates.findIndex((s) => s.userId === userId && s.siteId === scope.siteId && s.table === scope.table && s.date === scope.date && inferSearchType(s) === scopeSearchType);
|
|
304
|
-
if (idx === -1) {
|
|
305
|
-
snap.syncStates.push({
|
|
306
|
-
userId,
|
|
307
|
-
siteId: scope.siteId,
|
|
308
|
-
table: scope.table,
|
|
309
|
-
date: scope.date,
|
|
310
|
-
state,
|
|
311
|
-
updatedAt: at,
|
|
312
|
-
attempts: 1,
|
|
313
|
-
error: detail?.error,
|
|
314
|
-
...scope.searchType !== void 0 ? { searchType: scope.searchType } : {}
|
|
315
|
-
});
|
|
316
|
-
return;
|
|
317
|
-
}
|
|
318
|
-
const prev = snap.syncStates[idx];
|
|
319
|
-
const attempts = state === "inflight" && prev.state !== "inflight" ? prev.attempts + 1 : prev.attempts;
|
|
320
|
-
const error = state === "done" ? void 0 : detail?.error ?? prev.error;
|
|
321
|
-
snap.syncStates[idx] = {
|
|
322
|
-
...prev,
|
|
323
|
-
state,
|
|
324
|
-
updatedAt: at,
|
|
325
|
-
attempts,
|
|
326
|
-
error
|
|
327
|
-
};
|
|
328
|
-
});
|
|
329
|
-
},
|
|
330
|
-
async withLock(_scope, fn) {
|
|
331
|
-
return fn();
|
|
332
|
-
},
|
|
333
|
-
async purgeTenant(filter) {
|
|
334
|
-
if (filter.userId !== userId) throw new Error(`purgeTenant: store is scoped to userId=${userId}, got ${filter.userId}`);
|
|
335
|
-
const purged = await mapWithConcurrency(await shardsForFilter({ siteId: filter.siteId }), SHARD_IO_CONCURRENCY, async ({ siteId, table }) => {
|
|
336
|
-
const { snapshot } = await readShard(siteId, table);
|
|
337
|
-
const prefix = shardPrefix(userId, siteId, table);
|
|
338
|
-
const keys = [];
|
|
339
|
-
let cursor;
|
|
340
|
-
do {
|
|
341
|
-
const res = await bucket.list({
|
|
342
|
-
prefix,
|
|
343
|
-
cursor,
|
|
344
|
-
limit: 1e3
|
|
345
|
-
});
|
|
346
|
-
for (const obj of res.objects) keys.push(obj.key);
|
|
347
|
-
cursor = res.truncated ? res.cursor : void 0;
|
|
348
|
-
} while (cursor);
|
|
349
|
-
for (let offset = 0; offset < keys.length; offset += R2_DELETE_BATCH_SIZE) await bucket.delete(keys.slice(offset, offset + R2_DELETE_BATCH_SIZE));
|
|
350
|
-
return {
|
|
351
|
-
entriesRemoved: snapshot.entries.length,
|
|
352
|
-
watermarksRemoved: snapshot.watermarks.length,
|
|
353
|
-
syncStatesRemoved: snapshot.syncStates.length
|
|
354
|
-
};
|
|
355
|
-
});
|
|
356
|
-
return {
|
|
357
|
-
entriesRemoved: purged.reduce((sum, result) => sum + result.entriesRemoved, 0),
|
|
358
|
-
watermarksRemoved: purged.reduce((sum, result) => sum + result.watermarksRemoved, 0),
|
|
359
|
-
syncStatesRemoved: purged.reduce((sum, result) => sum + result.syncStatesRemoved, 0)
|
|
360
|
-
};
|
|
361
|
-
}
|
|
362
|
-
};
|
|
363
|
-
}
|
|
364
|
-
export { createR2ManifestStore };
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { dedupeOverlappingTiers, splitOverlappingTiers } from "./_chunks/storage.mjs";
|
|
2
|
-
/**
|
|
3
|
-
* Host-policy predicate: true once a table's live raw-daily count crosses the
|
|
4
|
-
* engine's daily→weekly compaction gate. Wraps the internal threshold so hosts
|
|
5
|
-
* decide "is compaction due?" without importing the constant or the counter.
|
|
6
|
-
*
|
|
7
|
-
* Pure — pass the entries the host already fetched (typically via its own cached
|
|
8
|
-
* manifest store, so the hot-path check stays on the host's cache rather than
|
|
9
|
-
* forcing an uncached read through the engine).
|
|
10
|
-
*/
|
|
11
|
-
declare function isRawDailyCompactionDue(entries: ReadonlyArray<{
|
|
12
|
-
tier?: string | null;
|
|
13
|
-
partition: string;
|
|
14
|
-
}>): boolean;
|
|
15
|
-
export { dedupeOverlappingTiers, isRawDailyCompactionDue, splitOverlappingTiers };
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
import { countRawDailies, dedupeOverlappingTiers, splitOverlappingTiers } from "./_chunks/compaction.mjs";
|
|
2
|
-
function isRawDailyCompactionDue(entries) {
|
|
3
|
-
return countRawDailies(entries) > 7;
|
|
4
|
-
}
|
|
5
|
-
export { dedupeOverlappingTiers, isRawDailyCompactionDue, splitOverlappingTiers };
|
package/dist/snapshot.d.mts
DELETED
package/dist/snapshot.mjs
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|