@tungthedev/streams-server 0.2.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.
Files changed (183) hide show
  1. package/CODE_OF_CONDUCT.md +45 -0
  2. package/CONTRIBUTING.md +76 -0
  3. package/LICENSE +201 -0
  4. package/README.md +58 -0
  5. package/SECURITY.md +42 -0
  6. package/bin/prisma-streams-server +2 -0
  7. package/package.json +46 -0
  8. package/src/app.ts +583 -0
  9. package/src/app_core.ts +3144 -0
  10. package/src/app_local.ts +206 -0
  11. package/src/auth.ts +124 -0
  12. package/src/auto_tune.ts +69 -0
  13. package/src/backpressure.ts +66 -0
  14. package/src/bootstrap.ts +613 -0
  15. package/src/compute/demo_entry.ts +415 -0
  16. package/src/compute/demo_site.ts +1242 -0
  17. package/src/compute/entry.ts +19 -0
  18. package/src/compute/package_entry.ts +4 -0
  19. package/src/compute/virtual-modules.d.ts +15 -0
  20. package/src/compute/worker_module_url.ts +9 -0
  21. package/src/concurrency_gate.ts +108 -0
  22. package/src/config.ts +402 -0
  23. package/src/db/bootstrap_store.ts +9 -0
  24. package/src/db/db.ts +2424 -0
  25. package/src/db/schema.ts +925 -0
  26. package/src/db/sqlite_manifest_snapshot.ts +81 -0
  27. package/src/db/sqlite_touch_store.ts +491 -0
  28. package/src/db/sqlite_wal_store.ts +472 -0
  29. package/src/details/full_mode_details.ts +568 -0
  30. package/src/expiry_sweeper.ts +47 -0
  31. package/src/foreground_activity.ts +55 -0
  32. package/src/hist.ts +169 -0
  33. package/src/index/binary_fuse.ts +379 -0
  34. package/src/index/indexer.ts +947 -0
  35. package/src/index/lexicon_file_cache.ts +261 -0
  36. package/src/index/lexicon_format.ts +93 -0
  37. package/src/index/lexicon_indexer.ts +863 -0
  38. package/src/index/run_cache.ts +84 -0
  39. package/src/index/run_format.ts +213 -0
  40. package/src/index/schedule.ts +28 -0
  41. package/src/index/secondary_indexer.ts +901 -0
  42. package/src/index/secondary_schema.ts +105 -0
  43. package/src/ingest.ts +309 -0
  44. package/src/lens/lens.ts +501 -0
  45. package/src/manifest.ts +249 -0
  46. package/src/memory.ts +334 -0
  47. package/src/metrics.ts +147 -0
  48. package/src/metrics_emitter.ts +83 -0
  49. package/src/notifier.ts +180 -0
  50. package/src/objectstore/accounting.ts +151 -0
  51. package/src/objectstore/interface.ts +13 -0
  52. package/src/objectstore/mock_r2.ts +269 -0
  53. package/src/objectstore/null.ts +32 -0
  54. package/src/objectstore/r2.ts +318 -0
  55. package/src/observe/pairing.ts +61 -0
  56. package/src/observe/request.ts +772 -0
  57. package/src/offset.ts +70 -0
  58. package/src/postgres/bootstrap.ts +269 -0
  59. package/src/postgres/companions.ts +197 -0
  60. package/src/postgres/control_restore.ts +109 -0
  61. package/src/postgres/details.ts +189 -0
  62. package/src/postgres/lexicon_index.ts +260 -0
  63. package/src/postgres/routing_index.ts +189 -0
  64. package/src/postgres/rows.ts +132 -0
  65. package/src/postgres/schema.ts +355 -0
  66. package/src/postgres/secondary_index.ts +238 -0
  67. package/src/postgres/segments.ts +900 -0
  68. package/src/postgres/stats.ts +103 -0
  69. package/src/postgres/store.ts +947 -0
  70. package/src/postgres/touch.ts +591 -0
  71. package/src/postgres/types.ts +32 -0
  72. package/src/profiles/evlog/schema.ts +234 -0
  73. package/src/profiles/evlog.ts +473 -0
  74. package/src/profiles/generic.ts +51 -0
  75. package/src/profiles/index.ts +237 -0
  76. package/src/profiles/metrics/block_format.ts +109 -0
  77. package/src/profiles/metrics/normalize.ts +366 -0
  78. package/src/profiles/metrics/schema.ts +319 -0
  79. package/src/profiles/metrics.ts +83 -0
  80. package/src/profiles/otelTraces/normalize.ts +955 -0
  81. package/src/profiles/otelTraces/otlp.ts +1002 -0
  82. package/src/profiles/otelTraces/schema.ts +408 -0
  83. package/src/profiles/otelTraces.ts +390 -0
  84. package/src/profiles/profile.ts +284 -0
  85. package/src/profiles/stateProtocol/change_event_conformance.typecheck.ts +35 -0
  86. package/src/profiles/stateProtocol/changes.ts +24 -0
  87. package/src/profiles/stateProtocol/ingest.ts +115 -0
  88. package/src/profiles/stateProtocol/routes.ts +511 -0
  89. package/src/profiles/stateProtocol/types.ts +6 -0
  90. package/src/profiles/stateProtocol/validation.ts +51 -0
  91. package/src/profiles/stateProtocol.ts +107 -0
  92. package/src/read_filter.ts +468 -0
  93. package/src/reader.ts +2986 -0
  94. package/src/runtime/hash.ts +156 -0
  95. package/src/runtime/hash_vendor/LICENSE.hash-wasm +38 -0
  96. package/src/runtime/hash_vendor/NOTICE.md +8 -0
  97. package/src/runtime/hash_vendor/xxhash3.umd.min.cjs +7 -0
  98. package/src/runtime/hash_vendor/xxhash32.umd.min.cjs +7 -0
  99. package/src/runtime/hash_vendor/xxhash64.umd.min.cjs +7 -0
  100. package/src/runtime/host_runtime.ts +5 -0
  101. package/src/runtime_memory.ts +200 -0
  102. package/src/runtime_memory_sampler.ts +237 -0
  103. package/src/schema/lens_schema.ts +290 -0
  104. package/src/schema/proof.ts +547 -0
  105. package/src/schema/read_json.ts +51 -0
  106. package/src/schema/registry.ts +966 -0
  107. package/src/search/agg_format.ts +638 -0
  108. package/src/search/aggregate.ts +409 -0
  109. package/src/search/binary/codec.ts +162 -0
  110. package/src/search/binary/docset.ts +67 -0
  111. package/src/search/binary/restart_strings.ts +181 -0
  112. package/src/search/binary/varint.ts +34 -0
  113. package/src/search/bitset.ts +19 -0
  114. package/src/search/col_format.ts +382 -0
  115. package/src/search/col_runtime.ts +59 -0
  116. package/src/search/column_encoding.ts +43 -0
  117. package/src/search/companion_file_cache.ts +319 -0
  118. package/src/search/companion_format.ts +327 -0
  119. package/src/search/companion_manager.ts +1305 -0
  120. package/src/search/companion_plan.ts +229 -0
  121. package/src/search/exact_format.ts +281 -0
  122. package/src/search/exact_runtime.ts +55 -0
  123. package/src/search/fts_format.ts +423 -0
  124. package/src/search/fts_runtime.ts +333 -0
  125. package/src/search/query.ts +875 -0
  126. package/src/search/schema.ts +245 -0
  127. package/src/segment/cache.ts +270 -0
  128. package/src/segment/cached_segment.ts +89 -0
  129. package/src/segment/format.ts +403 -0
  130. package/src/segment/segmenter.ts +412 -0
  131. package/src/segment/segmenter_worker.ts +72 -0
  132. package/src/segment/segmenter_workers.ts +130 -0
  133. package/src/server.ts +264 -0
  134. package/src/server_auto_tune.ts +158 -0
  135. package/src/sqlite/adapter.ts +335 -0
  136. package/src/sqlite/runtime_stats.ts +163 -0
  137. package/src/stats.ts +205 -0
  138. package/src/store/append.ts +50 -0
  139. package/src/store/bootstrap_restore_store.ts +71 -0
  140. package/src/store/capabilities.ts +86 -0
  141. package/src/store/full_mode_details_store.ts +71 -0
  142. package/src/store/index_store.ts +104 -0
  143. package/src/store/profile_touch_store.ts +1 -0
  144. package/src/store/rows.ts +144 -0
  145. package/src/store/schema_profile_store.ts +73 -0
  146. package/src/store/schema_publication.ts +6 -0
  147. package/src/store/segment_manifest_store.ts +129 -0
  148. package/src/store/segment_read_store.ts +22 -0
  149. package/src/store/stats_accounting_store.ts +83 -0
  150. package/src/store/touch_store.ts +98 -0
  151. package/src/store/wal_store.ts +21 -0
  152. package/src/stream_size_reconciler.ts +100 -0
  153. package/src/touch/canonical_change.ts +7 -0
  154. package/src/touch/live_keys.ts +158 -0
  155. package/src/touch/live_metrics.ts +841 -0
  156. package/src/touch/live_templates.ts +449 -0
  157. package/src/touch/manager.ts +1292 -0
  158. package/src/touch/process_batch.ts +576 -0
  159. package/src/touch/processor_worker.ts +85 -0
  160. package/src/touch/spec.ts +459 -0
  161. package/src/touch/touch_journal.ts +771 -0
  162. package/src/touch/touch_key_id.ts +20 -0
  163. package/src/touch/worker_pool.ts +191 -0
  164. package/src/touch/worker_protocol.ts +57 -0
  165. package/src/types/proper-lockfile.d.ts +1 -0
  166. package/src/uploader.ts +358 -0
  167. package/src/util/base32_crockford.ts +81 -0
  168. package/src/util/bloom256.ts +67 -0
  169. package/src/util/byte_lru.ts +73 -0
  170. package/src/util/cleanup.ts +22 -0
  171. package/src/util/crc32c.ts +29 -0
  172. package/src/util/ds_error.ts +15 -0
  173. package/src/util/duration.ts +17 -0
  174. package/src/util/endian.ts +53 -0
  175. package/src/util/json_pointer.ts +148 -0
  176. package/src/util/log.ts +25 -0
  177. package/src/util/lru.ts +53 -0
  178. package/src/util/retry.ts +35 -0
  179. package/src/util/siphash.ts +71 -0
  180. package/src/util/stream_paths.ts +50 -0
  181. package/src/util/time.ts +14 -0
  182. package/src/util/yield.ts +3 -0
  183. package/src/util/zstd.ts +24 -0
@@ -0,0 +1,50 @@
1
+ import type { Result } from "better-result";
2
+
3
+ export type AppendRow = {
4
+ routingKey: Uint8Array | null;
5
+ contentType: string | null;
6
+ payload: Uint8Array;
7
+ };
8
+
9
+ export type ProducerInfo = {
10
+ id: string;
11
+ epoch: number;
12
+ seq: number;
13
+ };
14
+
15
+ export type AppendSuccess = {
16
+ lastOffset: bigint;
17
+ appendedRows: number;
18
+ closed: boolean;
19
+ duplicate: boolean;
20
+ producer?: { epoch: number; seq: number };
21
+ };
22
+
23
+ export type StoreAppendError =
24
+ | { kind: "not_found" | "gone" | "content_type_mismatch" }
25
+ | { kind: "stream_seq"; expected: string; received: string }
26
+ | { kind: "closed"; lastOffset: bigint }
27
+ | { kind: "producer_stale_epoch"; producerEpoch: number }
28
+ | { kind: "producer_gap"; expected: number; received: number }
29
+ | { kind: "producer_epoch_seq" };
30
+
31
+ export type StoreAppendResult = Result<AppendSuccess, StoreAppendError>;
32
+
33
+ export type StoreAppendTask = {
34
+ stream: string;
35
+ baseAppendMs: bigint;
36
+ rows: AppendRow[];
37
+ contentType: string | null;
38
+ streamSeq: string | null;
39
+ producer: ProducerInfo | null;
40
+ close: boolean;
41
+ };
42
+
43
+ export type StoreAppendBatchResult = {
44
+ results: StoreAppendResult[];
45
+ walBytesCommitted: number;
46
+ };
47
+
48
+ export type StoreAppendBatchError = { kind: "retryable" };
49
+
50
+ export type StoreAppendBatch = Result<StoreAppendBatchResult, StoreAppendBatchError>;
@@ -0,0 +1,71 @@
1
+ import type {
2
+ IndexRunRow,
3
+ LexiconIndexRunRow,
4
+ SecondaryIndexRunRow,
5
+ } from "./rows";
6
+ import type { StreamReadRow } from "./segment_read_store";
7
+ import type { ProfileTouchControlStore } from "./touch_store";
8
+ import type { MaybePromise } from "./capabilities";
9
+
10
+ export interface BootstrapRestoreStore {
11
+ readonly touch: ProfileTouchControlStore;
12
+ close(): MaybePromise<void>;
13
+ nowMs(): bigint;
14
+ beginRestoreStream?(stream: string): MaybePromise<void>;
15
+ commitRestoreStream?(stream: string): MaybePromise<void>;
16
+ rollbackRestoreStream?(stream: string): MaybePromise<void>;
17
+ restoreStreamRow(row: StreamReadRow): MaybePromise<void>;
18
+ upsertStreamProfile(stream: string, profileJson: string): MaybePromise<void>;
19
+ deleteStreamProfile(stream: string): MaybePromise<void>;
20
+ upsertSegmentMeta(stream: string, count: number, offsets: Uint8Array, blocks: Uint8Array, lastTs: Uint8Array): MaybePromise<void>;
21
+ upsertManifestRow(
22
+ stream: string,
23
+ generation: number,
24
+ uploadedGeneration: number,
25
+ uploadedAtMs: bigint | null,
26
+ etag: string | null,
27
+ sizeBytes: number | null
28
+ ): MaybePromise<void>;
29
+ createSegmentRow(row: {
30
+ segmentId: string;
31
+ stream: string;
32
+ segmentIndex: number;
33
+ startOffset: bigint;
34
+ endOffset: bigint;
35
+ blockCount: number;
36
+ lastAppendMs: bigint;
37
+ payloadBytes: bigint;
38
+ sizeBytes: number;
39
+ localPath: string;
40
+ }): MaybePromise<void>;
41
+ markSegmentUploaded(segmentId: string, etag: string, uploadedAtMs: bigint): MaybePromise<void>;
42
+ upsertIndexState(stream: string, indexSecret: Uint8Array, indexedThrough: number): MaybePromise<void>;
43
+ insertIndexRun(row: Omit<IndexRunRow, "retired_gen" | "retired_at_ms">): MaybePromise<void>;
44
+ retireIndexRuns(runIds: string[], retiredGen: number, retiredAtMs: bigint): MaybePromise<void>;
45
+ upsertSecondaryIndexState(
46
+ stream: string,
47
+ indexName: string,
48
+ indexSecret: Uint8Array,
49
+ configHash: string,
50
+ indexedThrough: number
51
+ ): MaybePromise<void>;
52
+ insertSecondaryIndexRun(row: Omit<SecondaryIndexRunRow, "retired_gen" | "retired_at_ms">): MaybePromise<void>;
53
+ retireSecondaryIndexRuns(runIds: string[], retiredGen: number, retiredAtMs: bigint): MaybePromise<void>;
54
+ upsertLexiconIndexState(stream: string, sourceKind: string, sourceName: string, indexedThrough: number): MaybePromise<void>;
55
+ insertLexiconIndexRun(row: Omit<LexiconIndexRunRow, "retired_gen" | "retired_at_ms">): MaybePromise<void>;
56
+ retireLexiconIndexRuns(runIds: string[], retiredGen: number, retiredAtMs: bigint): MaybePromise<void>;
57
+ upsertSearchCompanionPlan(stream: string, generation: number, planHash: string, planJson: string): MaybePromise<void>;
58
+ upsertSearchSegmentCompanion(
59
+ stream: string,
60
+ segmentIndex: number,
61
+ objectKey: string,
62
+ planGeneration: number,
63
+ sectionsJson: string,
64
+ sectionSizesJson: string,
65
+ sizeBytes: number,
66
+ primaryTimestampMinMs: bigint | null,
67
+ primaryTimestampMaxMs: bigint | null
68
+ ): MaybePromise<void>;
69
+ upsertSchemaRegistry(stream: string, registryJson: string): MaybePromise<void>;
70
+ setSchemaUploadedSizeBytes(stream: string, sizeBytes: number): MaybePromise<void>;
71
+ }
@@ -0,0 +1,86 @@
1
+ import type { WalStore } from "./wal_store";
2
+ import type { StreamReadStore } from "./segment_read_store";
3
+ import type { SchemaStore } from "./schema_profile_store";
4
+ import type { ProfileStore } from "./schema_profile_store";
5
+ import { dsError } from "../util/ds_error";
6
+
7
+ export type MaybePromise<T> = T | Promise<T>;
8
+
9
+ export type DurableStoreCapabilities = {
10
+ wal: true;
11
+ schemas: true;
12
+ profiles: true;
13
+ streamLifecycle: true;
14
+ segmentReads: boolean;
15
+ indexes: boolean;
16
+ manifests: boolean;
17
+ objectStoreAccounting: boolean;
18
+ storageStats: boolean;
19
+ schemaPublication: boolean;
20
+ builtinProfiles: boolean;
21
+ internalMetrics: boolean;
22
+ touch: boolean;
23
+ };
24
+
25
+ export interface StoreLifecycle {
26
+ readonly kind: "sqlite" | "postgres";
27
+ readonly capabilities: DurableStoreCapabilities;
28
+ close(): MaybePromise<void>;
29
+ nowMs(): bigint;
30
+ }
31
+
32
+ export interface StreamStore {
33
+ getStream(stream: string): MaybePromise<StreamReadStoreRow | null>;
34
+ ensureStream(stream: string, opts?: EnsureStreamOptions | null): MaybePromise<StreamReadStoreRow>;
35
+ listStreams(limit: number, offset: number): MaybePromise<StreamReadStoreRow[]>;
36
+ listExpiredStreams(limit: number): MaybePromise<string[]>;
37
+ deleteStream(stream: string): MaybePromise<boolean>;
38
+ hardDeleteStream(stream: string): MaybePromise<boolean>;
39
+ isDeleted(row: StreamReadStoreRow): boolean;
40
+ }
41
+
42
+ export type StreamReadStoreRow = Awaited<ReturnType<StreamReadStore["getStreamForRead"]>> extends infer Row ? NonNullable<Row> : never;
43
+
44
+ export type EnsureStreamOptions = {
45
+ contentType?: string | null;
46
+ profile?: string | null;
47
+ streamSeq?: string | null;
48
+ closed?: boolean;
49
+ ttlSeconds?: number | null;
50
+ expiresAtMs?: bigint | null;
51
+ streamFlags?: number;
52
+ };
53
+
54
+ export interface WalControlPlaneStore extends StoreLifecycle, StreamStore, StreamReadStore, WalStore, SchemaStore, ProfileStore {}
55
+
56
+ export function requireWalControlPlaneStore(store: StoreLifecycle): WalControlPlaneStore {
57
+ const candidate = store as Partial<WalControlPlaneStore>;
58
+ if (
59
+ store.capabilities.wal !== true ||
60
+ store.capabilities.streamLifecycle !== true ||
61
+ store.capabilities.schemas !== true ||
62
+ store.capabilities.profiles !== true ||
63
+ typeof candidate.getStream !== "function" ||
64
+ typeof candidate.ensureStream !== "function" ||
65
+ typeof candidate.listStreams !== "function" ||
66
+ typeof candidate.listExpiredStreams !== "function" ||
67
+ typeof candidate.deleteStream !== "function" ||
68
+ typeof candidate.hardDeleteStream !== "function" ||
69
+ typeof candidate.isDeleted !== "function" ||
70
+ typeof candidate.close !== "function" ||
71
+ typeof candidate.nowMs !== "function" ||
72
+ typeof candidate.appendBatch !== "function" ||
73
+ typeof candidate.readWalRange !== "function" ||
74
+ typeof candidate.readWalRangeDesc !== "function" ||
75
+ typeof candidate.getStreamForRead !== "function" ||
76
+ typeof candidate.nowMsForRead !== "function" ||
77
+ typeof candidate.getWalOldestTimestampMsForRead !== "function" ||
78
+ typeof candidate.getSchemaRegistryForRead !== "function" ||
79
+ typeof candidate.commitSchemaMetadataMutation !== "function" ||
80
+ typeof candidate.getStreamProfileForRead !== "function" ||
81
+ typeof candidate.commitProfileMetadataMutation !== "function"
82
+ ) {
83
+ throw dsError("store does not provide WAL/control-plane capabilities");
84
+ }
85
+ return candidate as WalControlPlaneStore;
86
+ }
@@ -0,0 +1,71 @@
1
+ import type { MaybePromise } from "./capabilities";
2
+ import type {
3
+ IndexRunRow,
4
+ IndexStateRow,
5
+ LexiconIndexRunRow,
6
+ LexiconIndexStateRow,
7
+ SearchCompanionPlanRow,
8
+ SearchSegmentCompanionRow,
9
+ SecondaryIndexRunRow,
10
+ SecondaryIndexStateRow,
11
+ } from "./rows";
12
+ import type { ManifestRow } from "./segment_manifest_store";
13
+ import type { SchemaRegistryRow } from "./schema_profile_store";
14
+
15
+ export type IndexStorageSummary = {
16
+ object_count: number;
17
+ bytes: bigint;
18
+ };
19
+
20
+ export type SecondaryIndexStorageSummary = IndexStorageSummary & {
21
+ index_name: string;
22
+ };
23
+
24
+ export type LexiconIndexStorageSummary = IndexStorageSummary & {
25
+ source_kind: string;
26
+ source_name: string;
27
+ };
28
+
29
+ export type ExactIndexDetailSnapshot = {
30
+ indexName: string;
31
+ state: SecondaryIndexStateRow | null;
32
+ activeRuns: SecondaryIndexRunRow[];
33
+ retiredRuns: SecondaryIndexRunRow[];
34
+ };
35
+
36
+ export type FullModeDetailsSnapshot = {
37
+ segmentCount: number;
38
+ uploadedSegmentCount: number;
39
+ manifest: ManifestRow;
40
+ schemaRow: SchemaRegistryRow | null;
41
+ uploadedSegmentBytes: bigint;
42
+ pendingSealedSegmentBytes: bigint;
43
+ routingIndexStorage: IndexStorageSummary;
44
+ secondaryIndexStorage: SecondaryIndexStorageSummary[];
45
+ lexiconIndexStorage: LexiconIndexStorageSummary[];
46
+ bundledCompanionStorage: IndexStorageSummary;
47
+ routingState: IndexStateRow | null;
48
+ routingRuns: IndexRunRow[];
49
+ retiredRoutingRuns: IndexRunRow[];
50
+ exactIndexes: ExactIndexDetailSnapshot[];
51
+ routingLexiconState: LexiconIndexStateRow | null;
52
+ routingLexiconRuns: LexiconIndexRunRow[];
53
+ retiredRoutingLexiconRuns: LexiconIndexRunRow[];
54
+ companionPlan: SearchCompanionPlanRow | null;
55
+ companionRows: SearchSegmentCompanionRow[];
56
+ };
57
+
58
+ export type FullModeDetailsSnapshotRequest = {
59
+ stream: string;
60
+ exactIndexNames: string[];
61
+ };
62
+
63
+ export type FullModeLagSnapshotRequest = {
64
+ stream: string;
65
+ segmentIndexes: number[];
66
+ };
67
+
68
+ export interface FullModeDetailsStore {
69
+ getFullModeDetailsSnapshot(request: FullModeDetailsSnapshotRequest): MaybePromise<FullModeDetailsSnapshot>;
70
+ getFullModeLagSnapshot(request: FullModeLagSnapshotRequest): MaybePromise<Map<number, bigint>>;
71
+ }
@@ -0,0 +1,104 @@
1
+ import type {
2
+ IndexRunRow,
3
+ IndexStateRow,
4
+ LexiconIndexRunRow,
5
+ LexiconIndexStateRow,
6
+ SearchCompanionPlanRow,
7
+ SearchSegmentCompanionRow,
8
+ SecondaryIndexRunRow,
9
+ SecondaryIndexStateRow,
10
+ SegmentRow,
11
+ StreamRow,
12
+ } from "./rows";
13
+ import type { MaybePromise } from "./capabilities";
14
+ import type { WalReadRow } from "./wal_store";
15
+
16
+ export type ManifestGenerationRow = {
17
+ generation: number;
18
+ };
19
+
20
+ export interface IndexSharedReadStore {
21
+ nowMs(): bigint;
22
+ getStream(stream: string): MaybePromise<StreamRow | null>;
23
+ getSegmentByIndex(stream: string, segmentIndex: number): MaybePromise<SegmentRow | null>;
24
+ countUploadedSegments(stream: string): MaybePromise<number>;
25
+ getManifestRow(stream: string): MaybePromise<ManifestGenerationRow>;
26
+ }
27
+
28
+ export interface RoutingIndexStore extends IndexSharedReadStore {
29
+ getIndexState(stream: string): MaybePromise<IndexStateRow | null>;
30
+ upsertIndexState(stream: string, indexSecret: Uint8Array, indexedThrough: number): MaybePromise<void>;
31
+ updateIndexedThrough(stream: string, indexedThrough: number): MaybePromise<void>;
32
+ listIndexRuns(stream: string): MaybePromise<IndexRunRow[]>;
33
+ listIndexRunsAll(stream: string): MaybePromise<IndexRunRow[]>;
34
+ listRetiredIndexRuns(stream: string): MaybePromise<IndexRunRow[]>;
35
+ insertIndexRun(row: Omit<IndexRunRow, "retired_gen" | "retired_at_ms">): MaybePromise<void>;
36
+ retireIndexRuns(runIds: string[], retiredGen: number, retiredAtMs: bigint): MaybePromise<void>;
37
+ deleteIndexRuns(runIds: string[]): MaybePromise<void>;
38
+ deleteIndex(stream: string): MaybePromise<void>;
39
+ }
40
+
41
+ export interface SecondaryIndexStore extends IndexSharedReadStore {
42
+ countSegmentsForStream(stream: string): MaybePromise<number>;
43
+ getSecondaryIndexState(stream: string, indexName: string): MaybePromise<SecondaryIndexStateRow | null>;
44
+ listSecondaryIndexStates(stream: string): MaybePromise<SecondaryIndexStateRow[]>;
45
+ upsertSecondaryIndexState(
46
+ stream: string,
47
+ indexName: string,
48
+ indexSecret: Uint8Array,
49
+ configHash: string,
50
+ indexedThrough: number
51
+ ): MaybePromise<void>;
52
+ updateSecondaryIndexedThrough(stream: string, indexName: string, indexedThrough: number): MaybePromise<void>;
53
+ listSecondaryIndexRuns(stream: string, indexName: string): MaybePromise<SecondaryIndexRunRow[]>;
54
+ listRetiredSecondaryIndexRuns(stream: string, indexName: string): MaybePromise<SecondaryIndexRunRow[]>;
55
+ insertSecondaryIndexRun(row: Omit<SecondaryIndexRunRow, "retired_gen" | "retired_at_ms">): MaybePromise<void>;
56
+ retireSecondaryIndexRuns(runIds: string[], retiredGen: number, retiredAtMs: bigint): MaybePromise<void>;
57
+ deleteSecondaryIndexRuns(runIds: string[]): MaybePromise<void>;
58
+ deleteSecondaryIndex(stream: string, indexName: string): MaybePromise<void>;
59
+ }
60
+
61
+ export interface LexiconIndexStore extends IndexSharedReadStore {
62
+ countSegmentsForStream(stream: string): MaybePromise<number>;
63
+ readWalRange(stream: string, startOffset: bigint, endOffset: bigint, routingKey?: Uint8Array): AsyncIterable<WalReadRow>;
64
+ getLexiconIndexState(stream: string, sourceKind: string, sourceName: string): MaybePromise<LexiconIndexStateRow | null>;
65
+ upsertLexiconIndexState(stream: string, sourceKind: string, sourceName: string, indexedThrough: number): MaybePromise<void>;
66
+ updateLexiconIndexedThrough(stream: string, sourceKind: string, sourceName: string, indexedThrough: number): MaybePromise<void>;
67
+ listLexiconIndexRuns(stream: string, sourceKind: string, sourceName: string): MaybePromise<LexiconIndexRunRow[]>;
68
+ listLexiconIndexRunsAll(stream: string, sourceKind: string, sourceName: string): MaybePromise<LexiconIndexRunRow[]>;
69
+ listRetiredLexiconIndexRuns(stream: string, sourceKind: string, sourceName: string): MaybePromise<LexiconIndexRunRow[]>;
70
+ insertLexiconIndexRun(row: Omit<LexiconIndexRunRow, "retired_gen" | "retired_at_ms">): MaybePromise<void>;
71
+ retireLexiconIndexRuns(runIds: string[], retiredGen: number, retiredAtMs: bigint): MaybePromise<void>;
72
+ deleteLexiconIndexRuns(runIds: string[]): MaybePromise<void>;
73
+ deleteLexiconIndexSource(stream: string, sourceKind: string, sourceName: string): MaybePromise<void>;
74
+ }
75
+
76
+ export interface CompanionProgressStore {
77
+ countUploadedSegments(stream: string): MaybePromise<number>;
78
+ getSearchCompanionPlan(stream: string): MaybePromise<SearchCompanionPlanRow | null>;
79
+ getSearchSegmentCompanion(stream: string, segmentIndex: number): MaybePromise<SearchSegmentCompanionRow | null>;
80
+ listSearchSegmentCompanions(stream: string): MaybePromise<SearchSegmentCompanionRow[]>;
81
+ }
82
+
83
+ export interface SearchCompanionIndexStore {
84
+ getSegmentByIndex(stream: string, segmentIndex: number): MaybePromise<SegmentRow | null>;
85
+ countUploadedSegments(stream: string): MaybePromise<number>;
86
+ getSearchCompanionPlan(stream: string): MaybePromise<SearchCompanionPlanRow | null>;
87
+ listSearchCompanionPlanStreams(): MaybePromise<string[]>;
88
+ upsertSearchCompanionPlan(stream: string, generation: number, planHash: string, planJson: string): MaybePromise<void>;
89
+ deleteSearchCompanionPlan(stream: string): MaybePromise<void>;
90
+ getSearchSegmentCompanion(stream: string, segmentIndex: number): MaybePromise<SearchSegmentCompanionRow | null>;
91
+ listSearchSegmentCompanions(stream: string): MaybePromise<SearchSegmentCompanionRow[]>;
92
+ upsertSearchSegmentCompanion(
93
+ stream: string,
94
+ segmentIndex: number,
95
+ objectKey: string,
96
+ planGeneration: number,
97
+ sectionsJson: string,
98
+ sectionSizesJson: string,
99
+ sizeBytes: number,
100
+ primaryTimestampMinMs: bigint | null,
101
+ primaryTimestampMaxMs: bigint | null
102
+ ): MaybePromise<void>;
103
+ deleteSearchSegmentCompanions(stream: string): MaybePromise<void>;
104
+ }
@@ -0,0 +1 @@
1
+ export type ProfileTouchStatePlan = "preserve" | "ensure" | "delete";
@@ -0,0 +1,144 @@
1
+ export const STREAM_FLAG_DELETED = 1 << 0;
2
+ export const STREAM_FLAG_TOUCH = 1 << 1;
3
+
4
+ export type StreamRow = {
5
+ stream: string;
6
+ created_at_ms: bigint;
7
+ updated_at_ms: bigint;
8
+ content_type: string;
9
+ profile: string | null;
10
+ stream_seq: string | null;
11
+ closed: number;
12
+ closed_producer_id: string | null;
13
+ closed_producer_epoch: number | null;
14
+ closed_producer_seq: number | null;
15
+ ttl_seconds: number | null;
16
+ epoch: number;
17
+ next_offset: bigint;
18
+ sealed_through: bigint;
19
+ uploaded_through: bigint;
20
+ uploaded_segment_count: number;
21
+ pending_rows: bigint;
22
+ pending_bytes: bigint;
23
+ logical_size_bytes: bigint;
24
+ wal_rows: bigint;
25
+ wal_bytes: bigint;
26
+ last_append_ms: bigint;
27
+ last_segment_cut_ms: bigint;
28
+ segment_in_progress: number;
29
+ expires_at_ms: bigint | null;
30
+ stream_flags: number;
31
+ };
32
+
33
+ export type SegmentRow = {
34
+ segment_id: string;
35
+ stream: string;
36
+ segment_index: number;
37
+ start_offset: bigint;
38
+ end_offset: bigint;
39
+ block_count: number;
40
+ last_append_ms: bigint;
41
+ payload_bytes: bigint;
42
+ size_bytes: number;
43
+ local_path: string;
44
+ created_at_ms: bigint;
45
+ uploaded_at_ms: bigint | null;
46
+ r2_etag: string | null;
47
+ };
48
+
49
+ export type SegmentMetaRow = {
50
+ stream: string;
51
+ segment_count: number;
52
+ segment_offsets: Uint8Array;
53
+ segment_blocks: Uint8Array;
54
+ segment_last_ts: Uint8Array;
55
+ };
56
+
57
+ export type IndexStateRow = {
58
+ stream: string;
59
+ index_secret: Uint8Array;
60
+ indexed_through: number;
61
+ updated_at_ms: bigint;
62
+ };
63
+
64
+ export type IndexRunRow = {
65
+ run_id: string;
66
+ stream: string;
67
+ level: number;
68
+ start_segment: number;
69
+ end_segment: number;
70
+ object_key: string;
71
+ size_bytes: number;
72
+ filter_len: number;
73
+ record_count: number;
74
+ retired_gen: number | null;
75
+ retired_at_ms: bigint | null;
76
+ };
77
+
78
+ export type SecondaryIndexStateRow = {
79
+ stream: string;
80
+ index_name: string;
81
+ index_secret: Uint8Array;
82
+ config_hash: string;
83
+ indexed_through: number;
84
+ updated_at_ms: bigint;
85
+ };
86
+
87
+ export type SecondaryIndexRunRow = {
88
+ run_id: string;
89
+ stream: string;
90
+ index_name: string;
91
+ level: number;
92
+ start_segment: number;
93
+ end_segment: number;
94
+ object_key: string;
95
+ size_bytes: number;
96
+ filter_len: number;
97
+ record_count: number;
98
+ retired_gen: number | null;
99
+ retired_at_ms: bigint | null;
100
+ };
101
+
102
+ export type LexiconIndexStateRow = {
103
+ stream: string;
104
+ source_kind: string;
105
+ source_name: string;
106
+ indexed_through: number;
107
+ updated_at_ms: bigint;
108
+ };
109
+
110
+ export type LexiconIndexRunRow = {
111
+ run_id: string;
112
+ stream: string;
113
+ source_kind: string;
114
+ source_name: string;
115
+ level: number;
116
+ start_segment: number;
117
+ end_segment: number;
118
+ object_key: string;
119
+ size_bytes: number;
120
+ record_count: number;
121
+ retired_gen: number | null;
122
+ retired_at_ms: bigint | null;
123
+ };
124
+
125
+ export type SearchCompanionPlanRow = {
126
+ stream: string;
127
+ generation: number;
128
+ plan_hash: string;
129
+ plan_json: string;
130
+ updated_at_ms: bigint;
131
+ };
132
+
133
+ export type SearchSegmentCompanionRow = {
134
+ stream: string;
135
+ segment_index: number;
136
+ object_key: string;
137
+ plan_generation: number;
138
+ sections_json: string;
139
+ section_sizes_json: string;
140
+ size_bytes: number;
141
+ primary_timestamp_min_ms: bigint | null;
142
+ primary_timestamp_max_ms: bigint | null;
143
+ updated_at_ms: bigint;
144
+ };
@@ -0,0 +1,73 @@
1
+ import type { Result } from "better-result";
2
+ import type { StreamReadRow } from "./segment_read_store";
3
+ import type { SchemaRegistry } from "../schema/registry";
4
+ import type { ProfileTouchStatePlan } from "./profile_touch_store";
5
+
6
+ export type SchemaRegistryRow = {
7
+ stream: string;
8
+ registry_json: string;
9
+ updated_at_ms: bigint;
10
+ uploaded_size_bytes: bigint;
11
+ };
12
+
13
+ export type StoredProfileRow = {
14
+ stream: string;
15
+ profile_json: string;
16
+ updated_at_ms: bigint;
17
+ };
18
+
19
+ export type SchemaMetadataMutationContext = {
20
+ streamRow: StreamReadRow | null;
21
+ registryRow: SchemaRegistryRow | null;
22
+ };
23
+
24
+ export type SchemaMetadataMutationPlan<T> = {
25
+ registry: SchemaRegistry;
26
+ registryJson: string;
27
+ value: T;
28
+ };
29
+
30
+ export type SchemaMetadataCommit<T> = {
31
+ registry: SchemaRegistry;
32
+ updatedAtMs: bigint;
33
+ value: T;
34
+ };
35
+
36
+ export interface SchemaStore {
37
+ getSchemaRegistryForRead(stream: string): Promise<SchemaRegistryRow | null>;
38
+ commitSchemaMetadataMutation<T, E>(
39
+ stream: string,
40
+ mutation: (ctx: SchemaMetadataMutationContext) => Result<SchemaMetadataMutationPlan<T>, E>
41
+ ): Promise<Result<SchemaMetadataCommit<T>, E>>;
42
+ }
43
+
44
+ export type ProfileMetadataMutationContext = {
45
+ streamRow: StreamReadRow | null;
46
+ profileRow: StoredProfileRow | null;
47
+ };
48
+
49
+ export type ProfileMetadataPlan = {
50
+ streamProfile: string | null;
51
+ profileJson: string | null;
52
+ schemaRegistry: SchemaRegistry | null;
53
+ touchState?: ProfileTouchStatePlan;
54
+ };
55
+
56
+ export type ProfileMetadataMutationPlan<T> = {
57
+ metadata: ProfileMetadataPlan;
58
+ value: T;
59
+ };
60
+
61
+ export type ProfileMetadataCommit<T> = {
62
+ schemaRegistry: SchemaRegistry | null;
63
+ profileUpdatedAtMs: bigint;
64
+ value: T;
65
+ };
66
+
67
+ export interface ProfileStore {
68
+ getStreamProfileForRead(stream: string): Promise<StoredProfileRow | null>;
69
+ commitProfileMetadataMutation<T, E>(
70
+ stream: string,
71
+ mutation: (ctx: ProfileMetadataMutationContext) => Result<ProfileMetadataMutationPlan<T>, E>
72
+ ): Promise<Result<ProfileMetadataCommit<T>, E>>;
73
+ }
@@ -0,0 +1,6 @@
1
+ import type { SchemaRegistry } from "../schema/registry";
2
+
3
+ export interface SchemaPublicationStore {
4
+ uploadSchemaRegistry(stream: string, registry: SchemaRegistry): Promise<void>;
5
+ publishProfileSchemaRegistry(stream: string, registry: SchemaRegistry): Promise<void>;
6
+ }