@artblocks/abx-indexer 0.1.0-alpha.9 → 0.1.1
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/CHANGELOG.md +167 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/indexer.d.ts +81 -10
- package/dist/indexer.d.ts.map +1 -1
- package/dist/indexer.js +120 -8
- package/dist/indexer.js.map +1 -1
- package/dist/store.d.ts +100 -10
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +291 -26
- package/dist/store.js.map +1 -1
- package/package.json +7 -6
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
# @artblocks/abx-indexer
|
|
2
|
+
|
|
3
|
+
## 0.1.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies [7947ba9]
|
|
8
|
+
- @artblocks/abx-sdk@0.2.0
|
|
9
|
+
|
|
10
|
+
## 0.1.0
|
|
11
|
+
|
|
12
|
+
### Patch Changes
|
|
13
|
+
|
|
14
|
+
- 8f35dae: Prepare package metadata, release notes, and public-facing source comments for the initial public
|
|
15
|
+
source release.
|
|
16
|
+
- 719b9fe: Make the bundled skill read network and sponsorship support from CLI capabilities and the live
|
|
17
|
+
service descriptor instead of a hardcoded network list. Refresh public documentation references in
|
|
18
|
+
the published packages.
|
|
19
|
+
- Updated dependencies [21e3d6c]
|
|
20
|
+
- Updated dependencies [22abce8]
|
|
21
|
+
- Updated dependencies [4d5e2b1]
|
|
22
|
+
- Updated dependencies [56973c4]
|
|
23
|
+
- Updated dependencies [2290b0a]
|
|
24
|
+
- Updated dependencies [b9197bc]
|
|
25
|
+
- Updated dependencies [8ccbede]
|
|
26
|
+
- Updated dependencies [d925eb1]
|
|
27
|
+
- Updated dependencies [ea57f7a]
|
|
28
|
+
- Updated dependencies [3ddba71]
|
|
29
|
+
- Updated dependencies [8f35dae]
|
|
30
|
+
- Updated dependencies [719b9fe]
|
|
31
|
+
- Updated dependencies [9065128]
|
|
32
|
+
- Updated dependencies [c2400a7]
|
|
33
|
+
- Updated dependencies [3d7fe3c]
|
|
34
|
+
- Updated dependencies [7b462e2]
|
|
35
|
+
- Updated dependencies [ddb2e0b]
|
|
36
|
+
- Updated dependencies [4512962]
|
|
37
|
+
- Updated dependencies [76cfc6a]
|
|
38
|
+
- Updated dependencies [5522192]
|
|
39
|
+
- @artblocks/abx-sdk@0.1.0
|
|
40
|
+
|
|
41
|
+
## 0.1.0-alpha.50
|
|
42
|
+
|
|
43
|
+
### Patch Changes
|
|
44
|
+
|
|
45
|
+
- 719b9fe: Make the bundled skill read network and sponsorship support from CLI capabilities and the live
|
|
46
|
+
service descriptor instead of a hardcoded network list. Refresh public documentation references in
|
|
47
|
+
the published packages.
|
|
48
|
+
- Updated dependencies [719b9fe]
|
|
49
|
+
- @artblocks/abx-sdk@0.1.0-alpha.49
|
|
50
|
+
|
|
51
|
+
## 0.1.0-alpha.49
|
|
52
|
+
|
|
53
|
+
### Patch Changes
|
|
54
|
+
|
|
55
|
+
- Updated dependencies [4d5e2b1]
|
|
56
|
+
- @artblocks/abx-sdk@0.1.0-alpha.48
|
|
57
|
+
|
|
58
|
+
## 0.1.0-alpha.48
|
|
59
|
+
|
|
60
|
+
### Patch Changes
|
|
61
|
+
|
|
62
|
+
- Updated dependencies [56973c4]
|
|
63
|
+
- @artblocks/abx-sdk@0.1.0-alpha.47
|
|
64
|
+
|
|
65
|
+
## 0.1.0-alpha.47
|
|
66
|
+
|
|
67
|
+
### Patch Changes
|
|
68
|
+
|
|
69
|
+
- Updated dependencies [ddb2e0b]
|
|
70
|
+
- Updated dependencies [76cfc6a]
|
|
71
|
+
- @artblocks/abx-sdk@0.1.0-alpha.46
|
|
72
|
+
|
|
73
|
+
## 0.1.0-alpha.46
|
|
74
|
+
|
|
75
|
+
### Patch Changes
|
|
76
|
+
|
|
77
|
+
- Updated dependencies [d925eb1]
|
|
78
|
+
- @artblocks/abx-sdk@0.1.0-alpha.45
|
|
79
|
+
|
|
80
|
+
## 0.1.0-alpha.45
|
|
81
|
+
|
|
82
|
+
### Patch Changes
|
|
83
|
+
|
|
84
|
+
- Updated dependencies [22abce8]
|
|
85
|
+
- @artblocks/abx-sdk@0.1.0-alpha.44
|
|
86
|
+
|
|
87
|
+
## 0.1.0-alpha.44
|
|
88
|
+
|
|
89
|
+
### Patch Changes
|
|
90
|
+
|
|
91
|
+
- Updated dependencies [2290b0a]
|
|
92
|
+
- @artblocks/abx-sdk@0.1.0-alpha.43
|
|
93
|
+
|
|
94
|
+
## 0.1.0-alpha.43
|
|
95
|
+
|
|
96
|
+
### Patch Changes
|
|
97
|
+
|
|
98
|
+
- Updated dependencies [ea57f7a]
|
|
99
|
+
- @artblocks/abx-sdk@0.1.0-alpha.42
|
|
100
|
+
|
|
101
|
+
## 0.1.0-alpha.42
|
|
102
|
+
|
|
103
|
+
### Patch Changes
|
|
104
|
+
|
|
105
|
+
- Updated dependencies [8ccbede]
|
|
106
|
+
- @artblocks/abx-sdk@0.1.0-alpha.41
|
|
107
|
+
|
|
108
|
+
## 0.1.0-alpha.41
|
|
109
|
+
|
|
110
|
+
### Patch Changes
|
|
111
|
+
|
|
112
|
+
- Updated dependencies [b9197bc]
|
|
113
|
+
- @artblocks/abx-sdk@0.1.0-alpha.40
|
|
114
|
+
|
|
115
|
+
## 0.1.0-alpha.40
|
|
116
|
+
|
|
117
|
+
### Patch Changes
|
|
118
|
+
|
|
119
|
+
- Updated dependencies [3d7fe3c]
|
|
120
|
+
- Updated dependencies [7b462e2]
|
|
121
|
+
- @artblocks/abx-sdk@0.1.0-alpha.39
|
|
122
|
+
|
|
123
|
+
## 0.1.0-alpha.39
|
|
124
|
+
|
|
125
|
+
### Patch Changes
|
|
126
|
+
|
|
127
|
+
- Updated dependencies [c2400a7]
|
|
128
|
+
- @artblocks/abx-sdk@0.1.0-alpha.38
|
|
129
|
+
|
|
130
|
+
## 0.1.0-alpha.38
|
|
131
|
+
|
|
132
|
+
### Patch Changes
|
|
133
|
+
|
|
134
|
+
- Updated dependencies [4512962]
|
|
135
|
+
- @artblocks/abx-sdk@0.1.0-alpha.37
|
|
136
|
+
|
|
137
|
+
## 0.1.0-alpha.37
|
|
138
|
+
|
|
139
|
+
### Patch Changes
|
|
140
|
+
|
|
141
|
+
- Updated dependencies [5522192]
|
|
142
|
+
- @artblocks/abx-sdk@0.1.0-alpha.36
|
|
143
|
+
|
|
144
|
+
## 0.1.0-alpha.36
|
|
145
|
+
|
|
146
|
+
### Patch Changes
|
|
147
|
+
|
|
148
|
+
- Updated dependencies [21e3d6c]
|
|
149
|
+
- Updated dependencies [a73922c]
|
|
150
|
+
- @artblocks/abx-sdk@0.1.0-alpha.35
|
|
151
|
+
|
|
152
|
+
## 0.1.0-alpha.35
|
|
153
|
+
|
|
154
|
+
### Patch Changes
|
|
155
|
+
|
|
156
|
+
- Updated dependencies [3ddba71]
|
|
157
|
+
- Updated dependencies [9065128]
|
|
158
|
+
- @artblocks/abx-sdk@0.1.0-alpha.34
|
|
159
|
+
|
|
160
|
+
## 0.1.0-alpha.34
|
|
161
|
+
|
|
162
|
+
### Patch Changes
|
|
163
|
+
|
|
164
|
+
- 9242a05: Prepare package metadata, release notes, and public-facing source comments for the initial public
|
|
165
|
+
source release.
|
|
166
|
+
- Updated dependencies [9242a05]
|
|
167
|
+
- @artblocks/abx-sdk@0.1.0-alpha.33
|
package/dist/index.d.ts
CHANGED
|
@@ -4,6 +4,6 @@
|
|
|
4
4
|
* Replays the event spine from chain into a disposable, rebuildable projection.
|
|
5
5
|
* The canonical re-index: how every service onboards or exits a project.
|
|
6
6
|
*/
|
|
7
|
-
export { SelfHostIndexer, type IndexResult } from './indexer.js';
|
|
7
|
+
export { SelfHostIndexer, DEFAULT_INCREMENTAL_VACUUM_PAGES, DEFAULT_VACUUM_INTERVAL_MS, type IndexResult, type ReindexOptions, } from './indexer.js';
|
|
8
8
|
export { SqliteStore, type Store, type ProjectRegistration, type EffectStatusRow, type EffectArtifactRow, } from './store.js';
|
|
9
9
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EACL,eAAe,EACf,gCAAgC,EAChC,0BAA0B,EAC1B,KAAK,WAAW,EAChB,KAAK,cAAc,GACpB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,WAAW,EACX,KAAK,KAAK,EACV,KAAK,mBAAmB,EACxB,KAAK,eAAe,EACpB,KAAK,iBAAiB,GACvB,MAAM,YAAY,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -4,6 +4,6 @@
|
|
|
4
4
|
* Replays the event spine from chain into a disposable, rebuildable projection.
|
|
5
5
|
* The canonical re-index: how every service onboards or exits a project.
|
|
6
6
|
*/
|
|
7
|
-
export { SelfHostIndexer } from './indexer.js';
|
|
7
|
+
export { SelfHostIndexer, DEFAULT_INCREMENTAL_VACUUM_PAGES, DEFAULT_VACUUM_INTERVAL_MS, } from './indexer.js';
|
|
8
8
|
export { SqliteStore, } from './store.js';
|
|
9
9
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EACL,eAAe,EACf,gCAAgC,EAChC,0BAA0B,GAG3B,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,WAAW,GAKZ,MAAM,YAAY,CAAC"}
|
package/dist/indexer.d.ts
CHANGED
|
@@ -1,10 +1,45 @@
|
|
|
1
|
-
import { type Address, type ProjectState, type PublicClient } from '@artblocks/abx-sdk';
|
|
1
|
+
import { type Address, type GetLogsAdaptiveOptions, type ProjectState, type PublicClient, type ReconstructBlockTag } from '@artblocks/abx-sdk';
|
|
2
|
+
import type { Log } from 'viem';
|
|
2
3
|
import { type IndexStatusRow, type Store, type ProjectRegistration } from './store.js';
|
|
4
|
+
export interface ReindexOptions {
|
|
5
|
+
full?: boolean;
|
|
6
|
+
readUriDocuments?: boolean;
|
|
7
|
+
rpcUrl?: string;
|
|
8
|
+
/** Already-fetched logs for this project covering {@link toBlock}. Skips the
|
|
9
|
+
* per-project `eth_getLogs` — the watch loop that scanned the registered set
|
|
10
|
+
* holds the delta and should be the only getLogs. */
|
|
11
|
+
logs?: readonly Log[];
|
|
12
|
+
/** Inclusive scan head `logs` cover. Required with `logs`. */
|
|
13
|
+
toBlock?: bigint;
|
|
14
|
+
/**
|
|
15
|
+
* Stop the scan boundary at this block tag instead of chain head (the default, unchanged
|
|
16
|
+
* behavior). Resolved to a concrete block number BEFORE scanning (`resolveBlockTag` in the SDK),
|
|
17
|
+
* so the stored watermark (`ProjectState.toBlock`) is always a literal number, never the tag —
|
|
18
|
+
* see {@link ReconstructBlockTag}. Ignored when `logs` is supplied: that path's own `toBlock` is
|
|
19
|
+
* the caller's already-resolved scan head, from a watch loop that has nothing to do with a
|
|
20
|
+
* per-project tag choice.
|
|
21
|
+
*/
|
|
22
|
+
blockTag?: ReconstructBlockTag;
|
|
23
|
+
/** See {@link GetLogsAdaptiveOptions.onChunk} — the only progress signal during a large scan. */
|
|
24
|
+
onChunk?: GetLogsAdaptiveOptions['onChunk'];
|
|
25
|
+
}
|
|
3
26
|
export interface IndexResult {
|
|
4
27
|
state: ProjectState;
|
|
5
28
|
elapsedMs: number;
|
|
6
29
|
mode: 'full' | 'incremental';
|
|
7
30
|
}
|
|
31
|
+
/** Bounded per-pass reclaim for {@link SelfHostIndexer.runIncrementalVacuum} — ~100 pages is ~400KB
|
|
32
|
+
* at SQLite's default 4096-byte page size, cheap enough to run synchronously without a request or a
|
|
33
|
+
* watch tick noticing, while a long-running node with a large freelist still drains it over several
|
|
34
|
+
* passes instead of never. */
|
|
35
|
+
export declare const DEFAULT_INCREMENTAL_VACUUM_PAGES = 100;
|
|
36
|
+
/** Default cadence for automatic SQLite maintenance (see
|
|
37
|
+
* {@link SelfHostIndexer.startVacuumMaintenance}). Deliberately far coarser than the chain watcher's
|
|
38
|
+
* poll (`ABX_WATCH_INTERVAL_MS`, 12s by default): freed pages accumulate slowly (a reclaim, a
|
|
39
|
+
* dropped projection, a pruned bound artifact), so there is nothing to gain from touching the file
|
|
40
|
+
* every tick — and this is process-internal scheduling, not an operator-facing knob, so it isn't
|
|
41
|
+
* read from the environment the way the watcher's interval is. */
|
|
42
|
+
export declare const DEFAULT_VACUUM_INTERVAL_MS: number;
|
|
8
43
|
/**
|
|
9
44
|
* The reference indexer (Layer 3). It does one thing well: replay the event
|
|
10
45
|
* spine from chain into the store. Because every state change rides a standard,
|
|
@@ -19,6 +54,16 @@ export declare class SelfHostIndexer {
|
|
|
19
54
|
/** Catch-up runs in flight, per lowercased address — see {@link reindexShared}. */
|
|
20
55
|
private inFlight;
|
|
21
56
|
constructor(store?: Store);
|
|
57
|
+
/**
|
|
58
|
+
* The pooled read client for a chain, or — with `rpcUrl` — one pinned to a SINGLE endpoint.
|
|
59
|
+
*
|
|
60
|
+
* The default (no `rpcUrl`) is a viem `fallback` across every configured endpoint, which fails
|
|
61
|
+
* over on an *error*. It does not fail over on a successful empty answer, which is exactly what an
|
|
62
|
+
* endpoint that has pruned its log history returns for an old block: `[]`, HTTP 200. Pinning one
|
|
63
|
+
* endpoint is how a caller can re-run the same scan against each in turn and find one that holds
|
|
64
|
+
* the history (see the CLI's empty-scan recovery). Pooled per (chain, endpoint) so the pinned
|
|
65
|
+
* clients don't evict the shared one.
|
|
66
|
+
*/
|
|
22
67
|
private client;
|
|
23
68
|
/** The RPC client for a chain — exposed for reads that aren't a reindex (e.g. deploy-block
|
|
24
69
|
* discovery in the admin control plane). Reuses the same pooled client as `reindex`. */
|
|
@@ -34,9 +79,7 @@ export declare class SelfHostIndexer {
|
|
|
34
79
|
* replay. `{full: true}` forces a replay from the deploy block (the durability
|
|
35
80
|
* proof, and what runs automatically when there's no prior state). Idempotent.
|
|
36
81
|
*/
|
|
37
|
-
reindex(address: Address, opts?:
|
|
38
|
-
full?: boolean;
|
|
39
|
-
}): Promise<IndexResult>;
|
|
82
|
+
reindex(address: Address, opts?: ReindexOptions): Promise<IndexResult>;
|
|
40
83
|
/**
|
|
41
84
|
* {@link reindex}, but concurrent calls for the same project COALESCE into one run.
|
|
42
85
|
*
|
|
@@ -46,9 +89,7 @@ export declare class SelfHostIndexer {
|
|
|
46
89
|
* the bottleneck — so the second caller joins the first run instead. A caller that needs a *full*
|
|
47
90
|
* replay while an incremental is in flight gets its replay queued after it, never dropped.
|
|
48
91
|
*/
|
|
49
|
-
reindexShared(address: Address, opts?:
|
|
50
|
-
full?: boolean;
|
|
51
|
-
}): Promise<IndexResult>;
|
|
92
|
+
reindexShared(address: Address, opts?: ReindexOptions): Promise<IndexResult>;
|
|
52
93
|
/** Is a catch-up for this project running right now? (Lets a caller answer "still backfilling"
|
|
53
94
|
* without starting more work.) */
|
|
54
95
|
isCatchingUp(address: Address): boolean;
|
|
@@ -61,14 +102,44 @@ export declare class SelfHostIndexer {
|
|
|
61
102
|
indexStatus(address: Address): IndexStatusRow;
|
|
62
103
|
private track;
|
|
63
104
|
/** Re-index every registered project. */
|
|
64
|
-
reindexAll(opts?:
|
|
65
|
-
full?: boolean;
|
|
66
|
-
}): Promise<IndexResult[]>;
|
|
105
|
+
reindexAll(opts?: ReindexOptions): Promise<IndexResult[]>;
|
|
67
106
|
getProject(address: Address): ProjectState | null;
|
|
68
107
|
/** Throw away a project's reconstructed projection, keeping its registration — the next
|
|
69
108
|
* {@link reindex} then rebuilds it from the deploy block. The projection is a disposable cache of
|
|
70
109
|
* chain state; this is how you prove it (`abx demo` deletes and replays to show identical state). */
|
|
71
110
|
dropProjection(address: Address): void;
|
|
72
111
|
listProjects(): ProjectState[];
|
|
112
|
+
/**
|
|
113
|
+
* Run one bounded `PRAGMA incremental_vacuum` pass, delegating to {@link SqliteStore.runIncrementalVacuum}.
|
|
114
|
+
* A no-op (returns 0) for any `Store` implementation that isn't a `SqliteStore` — vacuuming is a
|
|
115
|
+
* SQLite-specific concern, so a Postgres-backed deploy (which owns its own manual VACUUM story)
|
|
116
|
+
* simply has nothing to do here. Exposed on its own (not just via {@link startVacuumMaintenance})
|
|
117
|
+
* so a caller can also run one pass on demand — e.g. right after `abx vacuum convert`, to reclaim
|
|
118
|
+
* whatever the full VACUUM already didn't (it shouldn't leave anything, but this makes "did it
|
|
119
|
+
* work" independently checkable).
|
|
120
|
+
*/
|
|
121
|
+
runIncrementalVacuum(maxPages?: number): number;
|
|
122
|
+
/**
|
|
123
|
+
* Start automatic SQLite maintenance: {@link runIncrementalVacuum} on its own
|
|
124
|
+
* timer, decoupled from the chain watcher's poll loop (`packages/token-api/src/watcher.ts`) so a
|
|
125
|
+
* reclaim pass can never sit inline with a request or a watch tick — it runs BETWEEN them, on
|
|
126
|
+
* whatever cadence the caller (or the default) picks, and a slow pass only ever delays the next
|
|
127
|
+
* pass, never a request being served concurrently (`node:sqlite`'s `DatabaseSync` is synchronous,
|
|
128
|
+
* but each pass is bounded — see `SqliteStore.runIncrementalVacuum` — precisely so that's cheap).
|
|
129
|
+
*
|
|
130
|
+
* `abx serve` is the intended caller, started once alongside `startChainWatcher`. Safe to call
|
|
131
|
+
* unconditionally: for a non-`SqliteStore` backend this still returns a working `stop()`, it just
|
|
132
|
+
* schedules calls that are themselves no-ops (see {@link runIncrementalVacuum}).
|
|
133
|
+
*
|
|
134
|
+
* A failed pass is logged and swallowed — maintenance must never be the thing that takes a node
|
|
135
|
+
* down; the freelist simply waits for the next pass.
|
|
136
|
+
*/
|
|
137
|
+
startVacuumMaintenance(opts?: {
|
|
138
|
+
intervalMs?: number;
|
|
139
|
+
maxPages?: number;
|
|
140
|
+
log?: (line: string) => void;
|
|
141
|
+
}): {
|
|
142
|
+
stop(): void;
|
|
143
|
+
};
|
|
73
144
|
}
|
|
74
145
|
//# sourceMappingURL=indexer.d.ts.map
|
package/dist/indexer.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"indexer.d.ts","sourceRoot":"","sources":["../src/indexer.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"indexer.d.ts","sourceRoot":"","sources":["../src/indexer.ts"],"names":[],"mappings":"AAAA,OAAO,EAML,KAAK,OAAO,EACZ,KAAK,sBAAsB,EAC3B,KAAK,YAAY,EACjB,KAAK,YAAY,EACjB,KAAK,mBAAmB,EACzB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAC,GAAG,EAAC,MAAM,MAAM,CAAC;AAC9B,OAAO,EAAc,KAAK,cAAc,EAAE,KAAK,KAAK,EAAE,KAAK,mBAAmB,EAAC,MAAM,YAAY,CAAC;AAElG,MAAM,WAAW,cAAc;IAC7B,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;0DAEsD;IACtD,IAAI,CAAC,EAAE,SAAS,GAAG,EAAE,CAAC;IACtB,8DAA8D;IAC9D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;;;;OAOG;IACH,QAAQ,CAAC,EAAE,mBAAmB,CAAC;IAC/B,iGAAiG;IACjG,OAAO,CAAC,EAAE,sBAAsB,CAAC,SAAS,CAAC,CAAC;CAC7C;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,YAAY,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,GAAG,aAAa,CAAC;CAC9B;AAED;;;+BAG+B;AAC/B,eAAO,MAAM,gCAAgC,MAAM,CAAC;AAEpD;;;;;mEAKmE;AACnE,eAAO,MAAM,0BAA0B,QAAa,CAAC;AAErD;;;;;;;GAOG;AACH,qBAAa,eAAe;IAC1B,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,OAAO,CAAC,OAAO,CAAmC;IAClD,mFAAmF;IACnF,OAAO,CAAC,QAAQ,CAAqE;gBAEzE,KAAK,CAAC,EAAE,KAAK;IAIzB;;;;;;;;;OASG;IACH,OAAO,CAAC,MAAM;IAOd;6FACyF;IACzF,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,YAAY;IAI5C;;6DAEyD;IACzD,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAC,mBAAmB,EAAE,cAAc,CAAC,GAAG,mBAAmB;IAO7E;;;;;;OAMG;IACG,OAAO,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,GAAE,cAAmB,GAAG,OAAO,CAAC,WAAW,CAAC;IA2FhF;;;;;;;;OAQG;IACH,aAAa,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,GAAE,cAAmB,GAAG,OAAO,CAAC,WAAW,CAAC;IAYhF;uCACmC;IACnC,YAAY,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO;IAIvC;;;;;OAKG;IACH,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,cAAc;IAU7C,OAAO,CAAC,KAAK;IAoBb,yCAAyC;IACnC,UAAU,CAAC,IAAI,GAAE,cAAmB,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAQnE,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,YAAY,GAAG,IAAI;IAIjD;;0GAEsG;IACtG,cAAc,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAItC,YAAY,IAAI,YAAY,EAAE;IAO9B;;;;;;;;OAQG;IACH,oBAAoB,CAAC,QAAQ,GAAE,MAAyC,GAAG,MAAM;IAIjF;;;;;;;;;;;;;;OAcG;IACH,sBAAsB,CAAC,IAAI,GAAE;QAAC,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;KAAM,GAAG;QAAC,IAAI,IAAI,IAAI,CAAA;KAAC;CAiB1H"}
|
package/dist/indexer.js
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
|
-
import { classifyIndexError, makePublicClient, reconstructIncremental, reconstructProject, } from '@artblocks/abx-sdk';
|
|
1
|
+
import { classifyIndexError, makePublicClient, reconstructFromLogs, reconstructIncremental, reconstructProject, } from '@artblocks/abx-sdk';
|
|
2
2
|
import { SqliteStore } from './store.js';
|
|
3
|
+
/** Bounded per-pass reclaim for {@link SelfHostIndexer.runIncrementalVacuum} — ~100 pages is ~400KB
|
|
4
|
+
* at SQLite's default 4096-byte page size, cheap enough to run synchronously without a request or a
|
|
5
|
+
* watch tick noticing, while a long-running node with a large freelist still drains it over several
|
|
6
|
+
* passes instead of never. */
|
|
7
|
+
export const DEFAULT_INCREMENTAL_VACUUM_PAGES = 100;
|
|
8
|
+
/** Default cadence for automatic SQLite maintenance (see
|
|
9
|
+
* {@link SelfHostIndexer.startVacuumMaintenance}). Deliberately far coarser than the chain watcher's
|
|
10
|
+
* poll (`ABX_WATCH_INTERVAL_MS`, 12s by default): freed pages accumulate slowly (a reclaim, a
|
|
11
|
+
* dropped projection, a pruned bound artifact), so there is nothing to gain from touching the file
|
|
12
|
+
* every tick — and this is process-internal scheduling, not an operator-facing knob, so it isn't
|
|
13
|
+
* read from the environment the way the watcher's interval is. */
|
|
14
|
+
export const DEFAULT_VACUUM_INTERVAL_MS = 5 * 60_000;
|
|
3
15
|
/**
|
|
4
16
|
* The reference indexer (Layer 3). It does one thing well: replay the event
|
|
5
17
|
* spine from chain into the store. Because every state change rides a standard,
|
|
@@ -16,10 +28,21 @@ export class SelfHostIndexer {
|
|
|
16
28
|
constructor(store) {
|
|
17
29
|
this.store = store ?? new SqliteStore();
|
|
18
30
|
}
|
|
19
|
-
|
|
20
|
-
|
|
31
|
+
/**
|
|
32
|
+
* The pooled read client for a chain, or — with `rpcUrl` — one pinned to a SINGLE endpoint.
|
|
33
|
+
*
|
|
34
|
+
* The default (no `rpcUrl`) is a viem `fallback` across every configured endpoint, which fails
|
|
35
|
+
* over on an *error*. It does not fail over on a successful empty answer, which is exactly what an
|
|
36
|
+
* endpoint that has pruned its log history returns for an old block: `[]`, HTTP 200. Pinning one
|
|
37
|
+
* endpoint is how a caller can re-run the same scan against each in turn and find one that holds
|
|
38
|
+
* the history (see the CLI's empty-scan recovery). Pooled per (chain, endpoint) so the pinned
|
|
39
|
+
* clients don't evict the shared one.
|
|
40
|
+
*/
|
|
41
|
+
client(chainKey, rpcUrl) {
|
|
42
|
+
const key = rpcUrl ? `${chainKey}|${rpcUrl}` : chainKey;
|
|
43
|
+
let c = this.clients.get(key);
|
|
21
44
|
if (!c)
|
|
22
|
-
this.clients.set(
|
|
45
|
+
this.clients.set(key, (c = makePublicClient({ chainKey, rpcUrl })));
|
|
23
46
|
return c;
|
|
24
47
|
}
|
|
25
48
|
/** The RPC client for a chain — exposed for reads that aren't a reindex (e.g. deploy-block
|
|
@@ -64,15 +87,54 @@ export class SelfHostIndexer {
|
|
|
64
87
|
let state;
|
|
65
88
|
let mode;
|
|
66
89
|
try {
|
|
67
|
-
if (incremental) {
|
|
68
|
-
|
|
90
|
+
if (incremental && opts.logs !== undefined) {
|
|
91
|
+
if (opts.toBlock === undefined) {
|
|
92
|
+
throw new Error('reindex({logs}) requires toBlock — the inclusive scan head those logs cover');
|
|
93
|
+
}
|
|
94
|
+
state = await reconstructFromLogs(this.client(reg.chainKey, opts.rpcUrl), prior, opts.logs, {
|
|
95
|
+
factory,
|
|
96
|
+
readUriDocuments: opts.readUriDocuments,
|
|
97
|
+
toBlock: opts.toBlock,
|
|
98
|
+
});
|
|
99
|
+
mode = 'incremental';
|
|
100
|
+
}
|
|
101
|
+
else if (incremental) {
|
|
102
|
+
state = await reconstructIncremental(this.client(reg.chainKey, opts.rpcUrl), prior, {
|
|
103
|
+
factory,
|
|
104
|
+
readUriDocuments: opts.readUriDocuments,
|
|
105
|
+
onChunk: opts.onChunk,
|
|
106
|
+
toBlock: opts.blockTag,
|
|
107
|
+
});
|
|
69
108
|
mode = 'incremental';
|
|
70
109
|
}
|
|
71
110
|
else {
|
|
72
|
-
state = await reconstructProject(this.client(reg.chainKey), {
|
|
111
|
+
state = await reconstructProject(this.client(reg.chainKey, opts.rpcUrl), {
|
|
73
112
|
address,
|
|
74
113
|
fromBlock: BigInt(reg.fromBlock),
|
|
75
114
|
factory,
|
|
115
|
+
readUriDocuments: opts.readUriDocuments,
|
|
116
|
+
onChunk: opts.onChunk,
|
|
117
|
+
toBlock: opts.blockTag,
|
|
118
|
+
});
|
|
119
|
+
mode = 'full';
|
|
120
|
+
}
|
|
121
|
+
// Self-heal, never loop: an incremental fold that yields FEWER events than what's already
|
|
122
|
+
// stored signals a damaged projection. `eventCount` can only grow with append-only chain
|
|
123
|
+
// history, so a decrease is
|
|
124
|
+
// never legitimate — discard the bad fold before it's written, and repair with exactly ONE
|
|
125
|
+
// full replay from the deploy block. That result is written unconditionally, even in the
|
|
126
|
+
// (pathological) case where it too looks smaller: a full reconstruct from chain is
|
|
127
|
+
// definitionally correct, so there is nothing left to fall back to and no second attempt.
|
|
128
|
+
if (mode === 'incremental' && prior && state.eventCount < prior.eventCount) {
|
|
129
|
+
console.error(`[indexer] ${address}: an incremental fold produced ${state.eventCount} events, fewer than the ` +
|
|
130
|
+
`${prior.eventCount} already stored — discarding it and falling back to one full reconstruct.`);
|
|
131
|
+
state = await reconstructProject(this.client(reg.chainKey, opts.rpcUrl), {
|
|
132
|
+
address,
|
|
133
|
+
fromBlock: BigInt(reg.fromBlock),
|
|
134
|
+
factory,
|
|
135
|
+
readUriDocuments: opts.readUriDocuments,
|
|
136
|
+
onChunk: opts.onChunk,
|
|
137
|
+
toBlock: opts.blockTag,
|
|
76
138
|
});
|
|
77
139
|
mode = 'full';
|
|
78
140
|
}
|
|
@@ -88,7 +150,9 @@ export class SelfHostIndexer {
|
|
|
88
150
|
});
|
|
89
151
|
throw err;
|
|
90
152
|
}
|
|
91
|
-
|
|
153
|
+
// A full replay is the repair path — it purges + rebuilds the append-only event log so a
|
|
154
|
+
// reorg-replaced event can't survive as a stale row (incremental writes never delete).
|
|
155
|
+
this.store.putProject(state, { fullReplay: mode === 'full' });
|
|
92
156
|
const now = new Date().toISOString();
|
|
93
157
|
this.store.setIndexStatus(address, { status: 'live', error: null, attempts: 0, lastAttemptAt: now, lastIndexedAt: now });
|
|
94
158
|
return { state, elapsedMs: Date.now() - started, mode };
|
|
@@ -172,5 +236,53 @@ export class SelfHostIndexer {
|
|
|
172
236
|
listProjects() {
|
|
173
237
|
return this.store.listProjects();
|
|
174
238
|
}
|
|
239
|
+
// ── SQLite maintenance — the bounded-automatic half; the explicit one-time
|
|
240
|
+
// conversion for a pre-existing store lives on `SqliteStore.vacuumConvert` / `abx vacuum convert`.
|
|
241
|
+
/**
|
|
242
|
+
* Run one bounded `PRAGMA incremental_vacuum` pass, delegating to {@link SqliteStore.runIncrementalVacuum}.
|
|
243
|
+
* A no-op (returns 0) for any `Store` implementation that isn't a `SqliteStore` — vacuuming is a
|
|
244
|
+
* SQLite-specific concern, so a Postgres-backed deploy (which owns its own manual VACUUM story)
|
|
245
|
+
* simply has nothing to do here. Exposed on its own (not just via {@link startVacuumMaintenance})
|
|
246
|
+
* so a caller can also run one pass on demand — e.g. right after `abx vacuum convert`, to reclaim
|
|
247
|
+
* whatever the full VACUUM already didn't (it shouldn't leave anything, but this makes "did it
|
|
248
|
+
* work" independently checkable).
|
|
249
|
+
*/
|
|
250
|
+
runIncrementalVacuum(maxPages = DEFAULT_INCREMENTAL_VACUUM_PAGES) {
|
|
251
|
+
return this.store instanceof SqliteStore ? this.store.runIncrementalVacuum(maxPages) : 0;
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Start automatic SQLite maintenance: {@link runIncrementalVacuum} on its own
|
|
255
|
+
* timer, decoupled from the chain watcher's poll loop (`packages/token-api/src/watcher.ts`) so a
|
|
256
|
+
* reclaim pass can never sit inline with a request or a watch tick — it runs BETWEEN them, on
|
|
257
|
+
* whatever cadence the caller (or the default) picks, and a slow pass only ever delays the next
|
|
258
|
+
* pass, never a request being served concurrently (`node:sqlite`'s `DatabaseSync` is synchronous,
|
|
259
|
+
* but each pass is bounded — see `SqliteStore.runIncrementalVacuum` — precisely so that's cheap).
|
|
260
|
+
*
|
|
261
|
+
* `abx serve` is the intended caller, started once alongside `startChainWatcher`. Safe to call
|
|
262
|
+
* unconditionally: for a non-`SqliteStore` backend this still returns a working `stop()`, it just
|
|
263
|
+
* schedules calls that are themselves no-ops (see {@link runIncrementalVacuum}).
|
|
264
|
+
*
|
|
265
|
+
* A failed pass is logged and swallowed — maintenance must never be the thing that takes a node
|
|
266
|
+
* down; the freelist simply waits for the next pass.
|
|
267
|
+
*/
|
|
268
|
+
startVacuumMaintenance(opts = {}) {
|
|
269
|
+
const intervalMs = opts.intervalMs ?? DEFAULT_VACUUM_INTERVAL_MS;
|
|
270
|
+
const maxPages = opts.maxPages ?? DEFAULT_INCREMENTAL_VACUUM_PAGES;
|
|
271
|
+
const log = opts.log ?? ((line) => console.error(`[maintenance] ${line}`));
|
|
272
|
+
const timer = setInterval(() => {
|
|
273
|
+
try {
|
|
274
|
+
const reclaimed = this.runIncrementalVacuum(maxPages);
|
|
275
|
+
if (reclaimed > 0)
|
|
276
|
+
log(`incremental_vacuum reclaimed ${reclaimed} page(s)`);
|
|
277
|
+
}
|
|
278
|
+
catch (err) {
|
|
279
|
+
log(`incremental_vacuum failed (will retry next pass): ${err.message}`);
|
|
280
|
+
}
|
|
281
|
+
}, intervalMs);
|
|
282
|
+
// Never keeps the process alive on its own — a plain background convenience, not a reason `abx
|
|
283
|
+
// serve` (or a test) would hang waiting for it.
|
|
284
|
+
timer.unref?.();
|
|
285
|
+
return { stop: () => clearInterval(timer) };
|
|
286
|
+
}
|
|
175
287
|
}
|
|
176
288
|
//# sourceMappingURL=indexer.js.map
|
package/dist/indexer.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"indexer.js","sourceRoot":"","sources":["../src/indexer.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,gBAAgB,EAChB,sBAAsB,EACtB,kBAAkB,
|
|
1
|
+
{"version":3,"file":"indexer.js","sourceRoot":"","sources":["../src/indexer.ts"],"names":[],"mappings":"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"}
|