@typeberry/lib 0.9.0 → 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.
Files changed (121) hide show
  1. package/package.json +1 -1
  2. package/packages/core/collections/sorted-array.d.ts +1 -1
  3. package/packages/core/collections/sorted-array.d.ts.map +1 -1
  4. package/packages/core/collections/sorted-array.js +4 -2
  5. package/packages/core/collections/sorted-array.test.js +10 -0
  6. package/packages/core/collections/sorted-set.d.ts +1 -1
  7. package/packages/core/collections/sorted-set.d.ts.map +1 -1
  8. package/packages/core/collections/sorted-set.js +6 -2
  9. package/packages/core/collections/sorted-set.test.js +24 -0
  10. package/packages/core/utils/index.d.ts +1 -0
  11. package/packages/core/utils/index.d.ts.map +1 -1
  12. package/packages/core/utils/index.js +1 -0
  13. package/packages/core/utils/shutdown.d.ts +18 -0
  14. package/packages/core/utils/shutdown.d.ts.map +1 -0
  15. package/packages/core/utils/shutdown.js +3 -0
  16. package/packages/core/utils/shutdown.node.d.ts +5 -0
  17. package/packages/core/utils/shutdown.node.d.ts.map +1 -0
  18. package/packages/core/utils/shutdown.node.js +76 -0
  19. package/packages/core/utils/shutdown.test.d.ts +2 -0
  20. package/packages/core/utils/shutdown.test.d.ts.map +1 -0
  21. package/packages/core/utils/shutdown.test.js +164 -0
  22. package/packages/extensions/ipc/server.d.ts.map +1 -1
  23. package/packages/extensions/ipc/server.js +7 -0
  24. package/packages/jam/config-node/node-config.d.ts +20 -2
  25. package/packages/jam/config-node/node-config.d.ts.map +1 -1
  26. package/packages/jam/config-node/node-config.js +25 -3
  27. package/packages/jam/config-node/node-config.test.js +8 -1
  28. package/packages/jam/database/index.d.ts +1 -0
  29. package/packages/jam/database/index.d.ts.map +1 -1
  30. package/packages/jam/database/index.js +1 -0
  31. package/packages/jam/database/leaf-db-update.d.ts +1 -0
  32. package/packages/jam/database/leaf-db-update.d.ts.map +1 -1
  33. package/packages/jam/database/leaf-db-update.js +22 -5
  34. package/packages/jam/database/leaf-db-update.test.d.ts +2 -0
  35. package/packages/jam/database/leaf-db-update.test.d.ts.map +1 -0
  36. package/packages/jam/database/leaf-db-update.test.js +81 -0
  37. package/packages/jam/database/serialized-states-db.d.ts +4 -0
  38. package/packages/jam/database/serialized-states-db.d.ts.map +1 -1
  39. package/packages/jam/database/serialized-states-db.js +18 -2
  40. package/packages/jam/database/serialized-states-db.test.d.ts +2 -0
  41. package/packages/jam/database/serialized-states-db.test.d.ts.map +1 -0
  42. package/packages/jam/database/serialized-states-db.test.js +109 -0
  43. package/packages/jam/database/states.d.ts +11 -0
  44. package/packages/jam/database/states.d.ts.map +1 -1
  45. package/packages/jam/database/states.js +3 -0
  46. package/packages/jam/database/value-refs.d.ts +117 -0
  47. package/packages/jam/database/value-refs.d.ts.map +1 -0
  48. package/packages/jam/database/value-refs.js +206 -0
  49. package/packages/jam/database/value-refs.test.d.ts +2 -0
  50. package/packages/jam/database/value-refs.test.d.ts.map +1 -0
  51. package/packages/jam/database/value-refs.test.js +165 -0
  52. package/packages/jam/database-fjall/blocks.d.ts +25 -0
  53. package/packages/jam/database-fjall/blocks.d.ts.map +1 -0
  54. package/packages/jam/database-fjall/blocks.js +86 -0
  55. package/packages/jam/database-fjall/blocks.test.d.ts +2 -0
  56. package/packages/jam/database-fjall/blocks.test.d.ts.map +1 -0
  57. package/packages/jam/database-fjall/blocks.test.js +62 -0
  58. package/packages/jam/database-fjall/hybrid-states.d.ts +61 -10
  59. package/packages/jam/database-fjall/hybrid-states.d.ts.map +1 -1
  60. package/packages/jam/database-fjall/hybrid-states.js +131 -26
  61. package/packages/jam/database-fjall/hybrid-states.test.js +125 -3
  62. package/packages/jam/database-fjall/index.d.ts +2 -0
  63. package/packages/jam/database-fjall/index.d.ts.map +1 -1
  64. package/packages/jam/database-fjall/index.js +2 -0
  65. package/packages/jam/database-fjall/root.d.ts +29 -17
  66. package/packages/jam/database-fjall/root.d.ts.map +1 -1
  67. package/packages/jam/database-fjall/root.js +33 -13
  68. package/packages/jam/database-fjall/states.d.ts +31 -0
  69. package/packages/jam/database-fjall/states.d.ts.map +1 -0
  70. package/packages/jam/database-fjall/states.js +99 -0
  71. package/packages/jam/database-fjall/states.test.d.ts +2 -0
  72. package/packages/jam/database-fjall/states.test.d.ts.map +1 -0
  73. package/packages/jam/database-fjall/states.test.js +150 -0
  74. package/packages/jam/database-lmdb/hybrid-states.d.ts +12 -0
  75. package/packages/jam/database-lmdb/hybrid-states.d.ts.map +1 -1
  76. package/packages/jam/database-lmdb/hybrid-states.js +45 -4
  77. package/packages/jam/database-lmdb/hybrid-states.test.js +94 -2
  78. package/packages/jam/database-lmdb/states.d.ts +1 -0
  79. package/packages/jam/database-lmdb/states.d.ts.map +1 -1
  80. package/packages/jam/database-lmdb/states.js +5 -0
  81. package/packages/jam/node/export.d.ts.map +1 -1
  82. package/packages/jam/node/export.js +18 -9
  83. package/packages/jam/node/main-fuzz.d.ts +4 -1
  84. package/packages/jam/node/main-fuzz.d.ts.map +1 -1
  85. package/packages/jam/node/main-fuzz.js +127 -55
  86. package/packages/jam/node/main-importer.d.ts +11 -2
  87. package/packages/jam/node/main-importer.d.ts.map +1 -1
  88. package/packages/jam/node/main-importer.js +27 -12
  89. package/packages/jam/node/main.d.ts.map +1 -1
  90. package/packages/jam/node/main.js +42 -15
  91. package/packages/jam/node/workers.d.ts +4 -4
  92. package/packages/jam/node/workers.d.ts.map +1 -1
  93. package/packages/workers/api/config.d.ts +2 -2
  94. package/packages/workers/api/config.d.ts.map +1 -1
  95. package/packages/workers/api/config.js +1 -1
  96. package/packages/workers/api/port.d.ts +5 -1
  97. package/packages/workers/api/port.d.ts.map +1 -1
  98. package/packages/workers/api/port.js +56 -13
  99. package/packages/workers/api/port.test.js +35 -0
  100. package/packages/workers/api-node/config.d.ts +58 -9
  101. package/packages/workers/api-node/config.d.ts.map +1 -1
  102. package/packages/workers/api-node/config.js +140 -18
  103. package/packages/workers/api-node/config.test.js +52 -3
  104. package/packages/workers/api-node/port.d.ts +3 -0
  105. package/packages/workers/api-node/port.d.ts.map +1 -1
  106. package/packages/workers/api-node/port.js +31 -2
  107. package/packages/workers/api-node/port.test.js +17 -0
  108. package/packages/workers/api-node/protocol.d.ts +3 -3
  109. package/packages/workers/api-node/protocol.d.ts.map +1 -1
  110. package/packages/workers/api-node/protocol.js +18 -12
  111. package/packages/workers/block-authorship/main.js +1 -1
  112. package/packages/workers/importer/finality.d.ts +4 -0
  113. package/packages/workers/importer/finality.d.ts.map +1 -1
  114. package/packages/workers/importer/finality.js +10 -1
  115. package/packages/workers/importer/finality.test.js +6 -0
  116. package/packages/workers/importer/importer.d.ts.map +1 -1
  117. package/packages/workers/importer/importer.js +3 -0
  118. package/packages/workers/importer/main.d.ts +1 -1
  119. package/packages/workers/importer/main.d.ts.map +1 -1
  120. package/packages/workers/importer/main.js +1 -1
  121. package/packages/workers/jam-network/main.js +1 -1
@@ -8,7 +8,7 @@ import { v1 as fuzzV1 } from "#@typeberry/fuzz-proto";
8
8
  import { HASH_SIZE } from "#@typeberry/hash";
9
9
  import { Logger } from "#@typeberry/logger";
10
10
  import { CURRENT_VERSION, Result, version } from "#@typeberry/utils";
11
- import { logHostEnvironment } from "#@typeberry/workers-api-node";
11
+ import { FjallValuesSession, logHostEnvironment } from "#@typeberry/workers-api-node";
12
12
  import { getChainSpec } from "./common.js";
13
13
  import { mainImporter } from "./main-importer.js";
14
14
  const logger = Logger.new(import.meta.filename, "fuzztarget");
@@ -17,6 +17,14 @@ const FUZZ_DB_SUBDIR = "typeberry-fuzz-db";
17
17
  const FUZZ_DB_FJALL = "fjall-hybrid";
18
18
  const FUZZ_DB_LMDB = "lmdb-hybrid";
19
19
  const FUZZ_DB_OPTIONS = [FUZZ_DB_FJALL, FUZZ_DB_LMDB];
20
+ /** Subdirectory (under the fuzzer's db dir) holding the reused fjall values keyspace. */
21
+ const FUZZ_FJALL_VALUES_SUBDIR = "values-session";
22
+ /**
23
+ * Size of the fjall block-cache for the fuzz session. Values pile up across
24
+ * resets (for fjall we do not wipe between them), so this cache is what keeps
25
+ * the resident memory bounded.
26
+ */
27
+ const FUZZ_FJALL_CACHE_BYTES = 128 * 1024 * 1024;
20
28
  /**
21
29
  * Resolve the directory the fuzzer should use for its on-disk database, or
22
30
  * `undefined` for an in-memory database. The dedicated `FUZZ_DB_SUBDIR` is
@@ -63,6 +71,14 @@ export async function mainFuzz(fuzzConfig, withRelPath) {
63
71
  logger.info `🗄️ Fuzz persistent backend: ${hybridStateBackend}.`;
64
72
  }
65
73
  let runningNode = null;
74
+ // The fjall values keyspace is opened once per fuzz session and reused on
75
+ // every reset, because opening it is the slow part. Only the in-memory blocks
76
+ // and leaf sets are rebuilt for each vector. fjall-hybrid only.
77
+ let fjallSession = null;
78
+ // Set when close() starts. Guards resetState so a fuzz command arriving
79
+ // mid-shutdown can't build a fresh node that close() then orphans.
80
+ let isClosing = false;
81
+ let activeReset = null;
66
82
  const chainSpec = getChainSpec(config.node.flavor);
67
83
  const closeFuzzTarget = startFuzzTarget(fuzzConfig.version, fuzzConfig.socket, {
68
84
  ...getFuzzDetails(),
@@ -86,66 +102,122 @@ export async function mainFuzz(fuzzConfig, withRelPath) {
86
102
  }
87
103
  return runningNode.getStateEntries(hash);
88
104
  },
89
- resetState: async (header, state, ancestry) => {
105
+ resetState: (header, state, ancestry) => {
106
+ const reset = (async () => {
107
+ if (isClosing) {
108
+ return Bytes.zero(HASH_SIZE).asOpaque();
109
+ }
110
+ if (runningNode !== null) {
111
+ const finish = runningNode.close();
112
+ runningNode = null;
113
+ await finish;
114
+ }
115
+ const buildNode = (databaseBasePath) => {
116
+ const isPersistent = databaseBasePath !== undefined;
117
+ return mainImporter({
118
+ ...config,
119
+ node: {
120
+ ...config.node,
121
+ databaseBasePath,
122
+ chainSpec: {
123
+ ...config.node.chainSpec,
124
+ genesisHeader: Encoder.encodeObject(Header.Codec, header, chainSpec),
125
+ genesisState: new Map(state),
126
+ },
127
+ },
128
+ ancestry,
129
+ network: null,
130
+ }, withRelPath, {
131
+ initGenesisFromAncestry: fuzzConfig.initGenesisFromAncestry,
132
+ // Hybrid keeps leaf sets in RAM, so they must be windowed exactly
133
+ // like the in-memory backend; only the large values live on disk.
134
+ dummyFinalityDepth: 20,
135
+ pruneBlocks: true,
136
+ // The on-disk fuzz db is throwaway (we wipe it), so open it ephemeral and
137
+ // skip the fsync, we do not need durability here. On full spec ephemeral
138
+ // also turns on compression further down, so the big values do not grow the
139
+ // db too much. Tiny stays uncompressed, its db is small and speed matters more.
140
+ ephemeral: isPersistent,
141
+ stateBackend: isPersistent ? hybridStateBackend : "lmdb",
142
+ // Reuse the session keyspace (fjall-hybrid only, other backends
143
+ // ignore it). Nothing to pass for the in-memory fallback.
144
+ sharedFjallSession: isPersistent ? (fjallSession ?? undefined) : undefined,
145
+ });
146
+ };
147
+ if (fuzzDbBase !== undefined) {
148
+ try {
149
+ if (hybridStateBackend === FUZZ_DB_FJALL) {
150
+ // fjall-hybrid: open the values keyspace once and reuse it on every
151
+ // reset. The values partition is content-addressed and immutable, so
152
+ // it is fine that values pile up across resets, the unreferenced ones
153
+ // just sit there. `initializeDatabase` decides whether the db is
154
+ // already initialized from the in-memory blocks, which we rebuild on
155
+ // every reset, not from the values store, so reusing it does not
156
+ // resume the previous run.
157
+ if (fjallSession === null) {
158
+ // Start from a clean slate once, then keep the keyspace open.
159
+ await wipeFuzzDb(fuzzDbBase);
160
+ fjallSession = await FjallValuesSession.open(`${withRelPath(fuzzDbBase)}/${FUZZ_FJALL_VALUES_SUBDIR}`, {
161
+ ephemeral: true,
162
+ cacheSizeBytes: FUZZ_FJALL_CACHE_BYTES,
163
+ });
164
+ logger.info `🗄️ Opened reusable fjall values session at ${withRelPath(fuzzDbBase)}/${FUZZ_FJALL_VALUES_SUBDIR}`;
165
+ }
166
+ }
167
+ else {
168
+ // lmdb-hybrid: keep the old behaviour, wipe and reopen on every
169
+ // reset. A fresh db each reset makes `initializeDatabase` set up
170
+ // genesis again instead of resuming the previous run.
171
+ await wipeFuzzDb(fuzzDbBase);
172
+ }
173
+ runningNode = await buildNode(fuzzDbBase);
174
+ return await runningNode.getBestStateRootHash();
175
+ }
176
+ catch (e) {
177
+ // A partially-opened db may leak on failure; acceptable for this degraded fallback (proper cleanup belongs in mainImporter).
178
+ logger.warn `Failed to open persistent fuzz db at ${fuzzDbBase}, falling back to in-memory: ${e}`;
179
+ runningNode = null;
180
+ }
181
+ }
182
+ runningNode = await buildNode(undefined);
183
+ return await runningNode.getBestStateRootHash();
184
+ })();
185
+ activeReset = reset;
186
+ const clearActiveReset = () => {
187
+ if (activeReset === reset) {
188
+ activeReset = null;
189
+ }
190
+ };
191
+ reset.then(clearActiveReset, clearActiveReset);
192
+ return reset;
193
+ },
194
+ });
195
+ return {
196
+ close: async () => {
197
+ isClosing = true;
198
+ // Stop accepting connections + unlink the socket.
199
+ closeFuzzTarget();
200
+ // Drain the active session (flush + close DB). Swallow errors so a
201
+ // failing close still lets the process exit 0; the db is wiped next.
202
+ // The node references the shared fjall session, so it must close first.
203
+ if (activeReset !== null) {
204
+ await activeReset.catch((e) => logger.error `Error waiting for fuzz reset: ${e}`);
205
+ }
90
206
  if (runningNode !== null) {
91
- const finish = runningNode.close();
207
+ const node = runningNode;
92
208
  runningNode = null;
93
- await finish;
209
+ await node.close().catch((e) => logger.error `Error closing fuzz node: ${e}`);
210
+ }
211
+ // Release the reused fjall values keyspace before wiping its files.
212
+ if (fjallSession !== null) {
213
+ const session = fjallSession;
214
+ fjallSession = null;
215
+ await session.close().catch((e) => logger.error `Error closing fjall session: ${e}`);
94
216
  }
95
- const buildNode = (databaseBasePath) => {
96
- const isPersistent = databaseBasePath !== undefined;
97
- return mainImporter({
98
- ...config,
99
- node: {
100
- ...config.node,
101
- databaseBasePath,
102
- chainSpec: {
103
- ...config.node.chainSpec,
104
- genesisHeader: Encoder.encodeObject(Header.Codec, header, chainSpec),
105
- genesisState: new Map(state),
106
- },
107
- },
108
- ancestry,
109
- network: null,
110
- }, withRelPath, {
111
- initGenesisFromAncestry: fuzzConfig.initGenesisFromAncestry,
112
- // Hybrid keeps leaf sets in RAM, so they must be windowed exactly
113
- // like the in-memory backend; only the large values live on disk.
114
- dummyFinalityDepth: 20,
115
- pruneBlocks: true,
116
- // Long full-spec sessions accumulate a large, never-pruned values db.
117
- // Syncing lets the OS reclaim dirty mmap pages, and compression (full
118
- // spec only, where values are big) bounds its on-disk/page-cache size.
119
- // Tiny stays uncompressed since its db is small and speed matters more.
120
- ephemeral: isPersistent,
121
- stateBackend: isPersistent ? hybridStateBackend : "lmdb",
122
- });
123
- };
124
217
  if (fuzzDbBase !== undefined) {
125
- // Each reset starts a fresh session from the genesis the fuzzer just sent,
126
- // so the on-disk db must be empty: otherwise initializeDatabase sees an
127
- // already-initialized db and silently resumes the previous run's state.
128
- await wipeFuzzDb(fuzzDbBase);
129
- try {
130
- runningNode = await buildNode(fuzzDbBase);
131
- return await runningNode.getBestStateRootHash();
132
- }
133
- catch (e) {
134
- // A partially-opened db may leak on failure; acceptable for this degraded fallback (proper cleanup belongs in mainImporter).
135
- logger.warn `Failed to open persistent fuzz db at ${fuzzDbBase}, falling back to in-memory: ${e}`;
136
- runningNode = null;
137
- }
218
+ await wipeFuzzDb(fuzzDbBase).catch(() => { });
138
219
  }
139
- runningNode = await buildNode(undefined);
140
- return await runningNode.getBestStateRootHash();
141
220
  },
142
- });
143
- return () => {
144
- closeFuzzTarget();
145
- if (fuzzDbBase !== undefined) {
146
- // best-effort cleanup on shutdown; ignore failures (dir may already be gone).
147
- wipeFuzzDb(fuzzDbBase).catch(() => { });
148
- }
149
221
  };
150
222
  }
151
223
  function isValidStateBackend(val) {
@@ -1,6 +1,7 @@
1
+ import { type FjallValuesSession } from "#@typeberry/workers-api-node";
1
2
  import type { JamConfig } from "./jam-config.js";
2
3
  import type { NodeApi } from "./main.js";
3
- export type StateBackend = "lmdb" | "lmdb-hybrid" | "fjall-hybrid";
4
+ export type StateBackend = "lmdb" | "fjall" | "lmdb-hybrid" | "fjall-hybrid";
4
5
  export type ImporterOptions = {
5
6
  initGenesisFromAncestry?: boolean;
6
7
  dummyFinalityDepth?: number;
@@ -8,9 +9,17 @@ export type ImporterOptions = {
8
9
  /** Open the database without fsync/compression. Only safe for throwaway dbs (e.g. fuzzing). */
9
10
  ephemeral?: boolean;
10
11
  /**
11
- * Persistent backend to use when `databaseBasePath` is set. Defaults to full LMDB.
12
+ * Persistent backend used when `databaseBasePath` is set. Defaults to config's backend (fjall unless overridden).
13
+ *
14
+ * lmdb and lmdb-hybrid are deprecated and retained as explicit fallbacks.
12
15
  */
13
16
  stateBackend?: StateBackend;
17
+ /**
18
+ * Reuse an already-open fjall values session instead of opening a fresh
19
+ * keyspace. Only used when `stateBackend === "fjall-hybrid"`. The fuzz target
20
+ * opens one per run and reuses it across resets.
21
+ */
22
+ sharedFjallSession?: FjallValuesSession;
14
23
  };
15
24
  export declare function mainImporter(config: JamConfig, withRelPath: (v: string) => string, options?: ImporterOptions): Promise<NodeApi>;
16
25
  //# sourceMappingURL=main-importer.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"main-importer.d.ts","sourceRoot":"","sources":["../../../../../packages/jam/node/main-importer.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIzC,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,aAAa,GAAG,cAAc,CAAC;AAEnE,MAAM,MAAM,eAAe,GAAG;IAC5B,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAClC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,+FAA+F;IAC/F,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;OAEG;IACH,YAAY,CAAC,EAAE,YAAY,CAAC;CAC7B,CAAC;AAEF,wBAAsB,YAAY,CAChC,MAAM,EAAE,SAAS,EACjB,WAAW,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,EAClC,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,OAAO,CAAC,CAqGlB"}
1
+ {"version":3,"file":"main-importer.d.ts","sourceRoot":"","sources":["../../../../../packages/jam/node/main-importer.ts"],"names":[],"mappings":"AASA,OAAO,EACL,KAAK,kBAAkB,EAKxB,MAAM,6BAA6B,CAAC;AAErC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIzC,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,OAAO,GAAG,aAAa,GAAG,cAAc,CAAC;AAE7E,MAAM,MAAM,eAAe,GAAG;IAC5B,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAClC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,+FAA+F;IAC/F,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;;;OAIG;IACH,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B;;;;OAIG;IACH,kBAAkB,CAAC,EAAE,kBAAkB,CAAC;CACzC,CAAC;AAEF,wBAAsB,YAAY,CAChC,MAAM,EAAE,SAAS,EACjB,WAAW,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,EAClC,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,OAAO,CAAC,CAqHlB"}
@@ -1,12 +1,12 @@
1
1
  import { Bytes } from "#@typeberry/bytes";
2
2
  import { PvmBackend } from "#@typeberry/config";
3
- import { KnownChainSpec } from "#@typeberry/config-node";
3
+ import { KnownChainSpec, RegularStateBackend } from "#@typeberry/config-node";
4
4
  import { bandersnatch, initWasm } from "#@typeberry/crypto";
5
5
  import { Blake2b, HASH_SIZE } from "#@typeberry/hash";
6
6
  import { createImporter, ImporterConfig } from "#@typeberry/importer";
7
7
  import { tryAsU16 } from "#@typeberry/numbers";
8
8
  import { CURRENT_SUITE, CURRENT_VERSION, Result, resultToString, version } from "#@typeberry/utils";
9
- import { HybridWorkerConfig, InMemWorkerConfig, LmdbWorkerConfig } from "#@typeberry/workers-api-node";
9
+ import { FjallWorkerConfig, HybridWorkerConfig, InMemWorkerConfig, LmdbWorkerConfig, } from "#@typeberry/workers-api-node";
10
10
  import { getChainSpec, getDatabasePath, initializeDatabase, logger } from "./common.js";
11
11
  const zeroHash = Bytes.zero(HASH_SIZE).asOpaque();
12
12
  export async function mainImporter(config, withRelPath, options = {}) {
@@ -18,8 +18,13 @@ export async function mainImporter(config, withRelPath, options = {}) {
18
18
  logger.info `🐇 Bandersnatch ${bandesnatchNative.isOk ? "native 🚀" : `using wasm: ${bandesnatchNative.error}`}`;
19
19
  // Single source of truth for the states db backend: drives both the log line
20
20
  // below and the worker config picked further down.
21
- const dbBackend = config.node.databaseBasePath === undefined ? "in-memory" : (options.stateBackend ?? "lmdb");
21
+ const dbBackend = config.node.databaseBasePath === undefined
22
+ ? "in-memory"
23
+ : (options.stateBackend ?? config.node.stateBackend ?? RegularStateBackend.Fjall);
22
24
  logger.info `🗄️ States DB: ${dbBackend}.`;
25
+ if (dbBackend === "lmdb" || dbBackend === "lmdb-hybrid") {
26
+ logger.warn `🗄️ The ${dbBackend} state backend is deprecated. Use fjall unless you need a temporary fallback.`;
27
+ }
23
28
  const chainSpec = getChainSpec(config.node.flavor);
24
29
  const blake2b = await Blake2b.createHasher();
25
30
  const nodeName = config.nodeName;
@@ -49,18 +54,28 @@ export async function mainImporter(config, withRelPath, options = {}) {
49
54
  ephemeral,
50
55
  compression,
51
56
  backend: dbBackend === "lmdb-hybrid" ? "lmdb" : "fjall",
57
+ sharedFjallSession: options.sharedFjallSession,
52
58
  })
53
- : LmdbWorkerConfig.new({
54
- nodeName,
55
- chainSpec,
56
- blake2b,
57
- dbPath,
58
- workerParams,
59
- ephemeral,
60
- });
59
+ : dbBackend === "fjall"
60
+ ? FjallWorkerConfig.new({
61
+ nodeName,
62
+ chainSpec,
63
+ blake2b,
64
+ dbPath,
65
+ workerParams,
66
+ ephemeral,
67
+ })
68
+ : LmdbWorkerConfig.new({
69
+ nodeName,
70
+ chainSpec,
71
+ blake2b,
72
+ dbPath,
73
+ workerParams,
74
+ ephemeral,
75
+ });
61
76
  // Initialize the database with genesis state and block if there isn't one.
62
77
  logger.info `🛢️ Opening database at ${dbPath}`;
63
- const rootDb = workerConfig.openDatabase({ readonly: false });
78
+ const rootDb = await workerConfig.openDatabase({ readonly: false });
64
79
  await initializeDatabase(chainSpec, blake2b, genesisHeaderHash, rootDb, config.node.chainSpec, config.ancestry, {
65
80
  initGenesisFromAncestry: options.initGenesisFromAncestry,
66
81
  });
@@ -1 +1 @@
1
- {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../../../../packages/jam/node/main.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAc,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEzF,OAAO,EAAE,KAAK,SAAS,EAAc,MAAM,mBAAmB,CAAC;AAe/D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AACnE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAkC,MAAM,EAAW,MAAM,kBAAkB,CAAC;AAKnF,OAAO,KAAK,EAAE,SAAS,EAAiB,MAAM,iBAAiB,CAAC;AAWhE,MAAM,MAAM,OAAO,GAAG;IACpB,SAAS,EAAE,SAAS,CAAC;IACrB,eAAe,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAAC;IAChE,WAAW,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC,CAAC;IACtE,oBAAoB,IAAI,OAAO,CAAC,aAAa,CAAC,CAAC;IAC/C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB,CAAC;AAEF,wBAAsB,IAAI,CACxB,MAAM,EAAE,SAAS,EACjB,WAAW,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,EAClC,SAAS,EAAE,SAAS,GAAG,IAAI,GAC1B,OAAO,CAAC,OAAO,CAAC,CA2KlB"}
1
+ {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../../../../packages/jam/node/main.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAc,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEzF,OAAO,EAAE,KAAK,SAAS,EAAc,MAAM,mBAAmB,CAAC;AAgB/D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AACnE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAkC,MAAM,EAAW,MAAM,kBAAkB,CAAC;AAYnF,OAAO,KAAK,EAAE,SAAS,EAAiB,MAAM,iBAAiB,CAAC;AAWhE,MAAM,MAAM,OAAO,GAAG;IACpB,SAAS,EAAE,SAAS,CAAC;IACrB,eAAe,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAAC;IAChE,WAAW,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC,CAAC;IACtE,oBAAoB,IAAI,OAAO,CAAC,aAAa,CAAC,CAAC;IAC/C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB,CAAC;AAEF,wBAAsB,IAAI,CACxB,MAAM,EAAE,SAAS,EACjB,WAAW,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,EAClC,SAAS,EAAE,SAAS,GAAG,IAAI,GAC1B,OAAO,CAAC,OAAO,CAAC,CA2LlB"}
@@ -1,6 +1,7 @@
1
1
  import { isMainThread } from "node:worker_threads";
2
2
  import { AUTHORSHIP_NETWORK_PORT } from "#@typeberry/comms-authorship-network";
3
3
  import { PvmBackend } from "#@typeberry/config";
4
+ import { RegularStateBackend } from "#@typeberry/config-node";
4
5
  import { initWasm } from "#@typeberry/crypto";
5
6
  import { deriveBandersnatchSecretKey, deriveEd25519SecretKey, trivialSeed, } from "#@typeberry/crypto/key-derivation.js";
6
7
  import { Blake2b } from "#@typeberry/hash";
@@ -10,7 +11,7 @@ import { Listener } from "#@typeberry/listener";
10
11
  import { tryAsU16, tryAsU32 } from "#@typeberry/numbers";
11
12
  import { CURRENT_SUITE, CURRENT_VERSION, Result, version } from "#@typeberry/utils";
12
13
  import { DirectPort, DirectWorkerConfig } from "#@typeberry/workers-api";
13
- import { InMemWorkerConfig, LmdbWorkerConfig, logHostEnvironment, ThreadPort } from "#@typeberry/workers-api-node";
14
+ import { FjallWorkerConfig, InMemWorkerConfig, LmdbWorkerConfig, logHostEnvironment, ThreadPort, } from "#@typeberry/workers-api-node";
14
15
  import { getChainSpec, getDatabasePath, initializeDatabase, logger } from "./common.js";
15
16
  import { initializeExtensions } from "./extensions.js";
16
17
  import * as metrics from "./metrics.js";
@@ -29,9 +30,12 @@ export async function main(config, withRelPath, telemetry) {
29
30
  const blake2b = await Blake2b.createHasher();
30
31
  const nodeName = config.nodeName;
31
32
  const isInMemory = config.node.databaseBasePath === undefined;
32
- logger.info `🗄️ States DB: ${isInMemory ? "in-memory" : "lmdb"}.`;
33
+ logger.info `🗄️ States DB: ${isInMemory ? "in-memory" : config.node.stateBackend}.`;
34
+ if (!isInMemory && config.node.stateBackend === RegularStateBackend.Lmdb) {
35
+ logger.warn `🗄️ The lmdb state backend is deprecated. Use state_backend="fjall" unless you need a temporary fallback.`;
36
+ }
33
37
  const { dbPath, genesisHeaderHash } = getDatabasePath(blake2b, nodeName, config.node.chainSpec.genesisHeader, withRelPath(config.node.databaseBasePath ?? "<in-memory>"));
34
- const baseConfig = { nodeName, chainSpec, blake2b, dbPath };
38
+ const baseConfig = { nodeName, chainSpec, blake2b, dbPath, stateBackend: config.node.stateBackend };
35
39
  const importerParams = {
36
40
  ...baseConfig,
37
41
  workerParams: ImporterConfig.create({
@@ -42,16 +46,29 @@ export async function main(config, withRelPath, telemetry) {
42
46
  };
43
47
  const importerConfig = isInMemory
44
48
  ? { isInMemory, config: InMemWorkerConfig.new(importerParams) }
45
- : { isInMemory, config: LmdbWorkerConfig.new(importerParams) };
49
+ : { isInMemory, config: createPersistentWorkerConfig(importerParams) };
46
50
  // Initialize the database with genesis state and block if there isn't one.
47
51
  logger.info `🛢️ Opening database at ${dbPath}`;
48
- const rootDb = importerConfig.config.openDatabase({ readonly: false });
49
- await initializeDatabase(chainSpec, blake2b, genesisHeaderHash, rootDb, config.node.chainSpec, config.ancestry);
50
- // NOTE [ToDr] even though, we should be closing the database here,
51
- // it seems that opening it in the main thread for writing, and later
52
- // in the importer thread, causes issues. Everything works fine though,
53
- // if we DO NOT close the database (I guess it's process-shared?)
54
- // await rootDb.close();
52
+ const rootDb = await importerConfig.config.openDatabase({ readonly: false });
53
+ try {
54
+ await initializeDatabase(chainSpec, blake2b, genesisHeaderHash, rootDb, config.node.chainSpec, config.ancestry);
55
+ }
56
+ catch (e) {
57
+ try {
58
+ await rootDb.close();
59
+ }
60
+ catch (closeError) {
61
+ logger.warn `Failed to close database after initialization error: ${closeError}`;
62
+ }
63
+ throw e;
64
+ }
65
+ // fjall-js shares the engine explicitly and requires every handle to close.
66
+ // Keep lmdb's historical main-thread handle open until shutdown.
67
+ let mainRootDb = rootDb;
68
+ if (!importerConfig.isInMemory && config.node.stateBackend === RegularStateBackend.Fjall) {
69
+ await rootDb.close();
70
+ mainRootDb = null;
71
+ }
55
72
  // Start block importer
56
73
  let importer;
57
74
  let closeImporter;
@@ -138,8 +155,10 @@ export async function main(config, withRelPath, telemetry) {
138
155
  await closeImporter();
139
156
  logger.log `[main] ☠️ Closing the extensions`;
140
157
  closeExtensions();
141
- logger.log `[main] 🛢️ Closing the database`;
142
- await rootDb.close();
158
+ if (mainRootDb !== null) {
159
+ logger.log `[main] 🛢️ Closing the database`;
160
+ await mainRootDb.close();
161
+ }
143
162
  logger.log `[main] 📳 Closing telemetry`;
144
163
  await telemetry?.close();
145
164
  logger.info `[main] ✅ Done.`;
@@ -167,7 +186,7 @@ const initAuthorship = async (importer, isAuthoring, isFastForward, params, base
167
186
  statesDb: params.rootDb.getStatesDb(),
168
187
  workerParams,
169
188
  }), params.networkingPort)
170
- : await spawnBlockGeneratorWorker(LmdbWorkerConfig.new({
189
+ : await spawnBlockGeneratorWorker(createPersistentWorkerConfig({
171
190
  ...baseConfig,
172
191
  workerParams,
173
192
  ports: new Map([[AUTHORSHIP_NETWORK_PORT, params.networkingPort]]),
@@ -205,7 +224,7 @@ const initNetwork = async (importer, params, baseConfig, genesisHeaderHash, netw
205
224
  statesDb: params.rootDb.getStatesDb(),
206
225
  workerParams: networkingConfig,
207
226
  }), params.authorshipPort)
208
- : await spawnNetworkWorker(LmdbWorkerConfig.new({
227
+ : await spawnNetworkWorker(createPersistentWorkerConfig({
209
228
  ...baseConfig,
210
229
  workerParams: networkingConfig,
211
230
  ports: new Map([[AUTHORSHIP_NETWORK_PORT, params.authorshipPort]]),
@@ -222,3 +241,11 @@ const initNetwork = async (importer, params, baseConfig, genesisHeaderHash, netw
222
241
  });
223
242
  return { closeNetwork: finish, networkApi: network, networkWorker: worker };
224
243
  };
244
+ function createPersistentWorkerConfig({ stateBackend, ...params }) {
245
+ switch (stateBackend) {
246
+ case RegularStateBackend.Fjall:
247
+ return FjallWorkerConfig.new(params);
248
+ case RegularStateBackend.Lmdb:
249
+ return LmdbWorkerConfig.new(params);
250
+ }
251
+ }
@@ -5,8 +5,8 @@ import * as importer from "#@typeberry/importer";
5
5
  import * as jamNetwork from "#@typeberry/jam-network";
6
6
  import type { SerializedState } from "#@typeberry/state-merkleization";
7
7
  import { type DirectPort, type DirectWorkerConfig } from "#@typeberry/workers-api";
8
- import { type LmdbWorkerConfig } from "#@typeberry/workers-api-node";
9
- export declare function spawnImporterWorker(config: LmdbWorkerConfig<importer.ImporterConfig>): Promise<{
8
+ import { type PersistentWorkerConfig } from "#@typeberry/workers-api-node";
9
+ export declare function spawnImporterWorker(config: PersistentWorkerConfig<importer.ImporterConfig>): Promise<{
10
10
  importer: import("@typeberry/workers-api").Tx<{
11
11
  getStateEntries: {
12
12
  request: import("@typeberry/codec").Descriptor<import("@typeberry/bytes").Bytes<32> & import("@typeberry/utils").WithOpaque<"HeaderHash">, import("@typeberry/bytes").Bytes<32>>;
@@ -376,7 +376,7 @@ export declare function spawnImporterWorker(config: LmdbWorkerConfig<importer.Im
376
376
  finish: () => Promise<void>;
377
377
  }>;
378
378
  export declare function startImporterDirect(config: DirectWorkerConfig<importer.ImporterConfig, BlocksDb, StatesDb<SerializedState<LeafDb>>>): ReturnType<typeof spawnImporterWorker>;
379
- export declare function spawnNetworkWorker(config: LmdbWorkerConfig<jamNetwork.NetworkingConfig>): Promise<{
379
+ export declare function spawnNetworkWorker(config: PersistentWorkerConfig<jamNetwork.NetworkingConfig>): Promise<{
380
380
  network: import("@typeberry/workers-api").Tx<{
381
381
  newHeader: {
382
382
  request: import("@typeberry/codec").Descriptor<import("@typeberry/hash").WithHash<import("@typeberry/hash").OpaqueHash & import("@typeberry/utils").WithOpaque<"HeaderHash">, import("@typeberry/codec").ViewOf<import("@typeberry/block").Header & import("@typeberry/codec").CodecRecord<import("@typeberry/block").Header>, {
@@ -865,7 +865,7 @@ export declare function spawnNetworkWorker(config: LmdbWorkerConfig<jamNetwork.N
865
865
  export declare function startNetwork(config: DirectWorkerConfig<jamNetwork.NetworkingConfig>, authorshipPort: DirectPort): Promise<Omit<Awaited<ReturnType<typeof spawnNetworkWorker>>, "worker"> & {
866
866
  worker: Worker | null;
867
867
  }>;
868
- export declare function spawnBlockGeneratorWorker(config: LmdbWorkerConfig<blockAuthorship.BlockAuthorshipConfig>): Promise<{
868
+ export declare function spawnBlockGeneratorWorker(config: PersistentWorkerConfig<blockAuthorship.BlockAuthorshipConfig>): Promise<{
869
869
  generator: import("@typeberry/workers-api").Tx<{
870
870
  finish: {
871
871
  request: import("@typeberry/codec").Descriptor<void, void>;
@@ -1 +1 @@
1
- {"version":3,"file":"workers.d.ts","sourceRoot":"","sources":["../../../../../packages/jam/node/workers.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"workers.d.ts","sourceRoot":"","sources":["../../../../../packages/jam/node/workers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,KAAK,eAAe,MAAM,6BAA6B,CAAC;AAE/D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACtE,OAAO,KAAK,QAAQ,MAAM,qBAAqB,CAAC;AAChD,OAAO,KAAK,UAAU,MAAM,wBAAwB,CAAC;AACrD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACtE,OAAO,EAAW,KAAK,UAAU,EAAE,KAAK,kBAAkB,EAAmB,MAAM,wBAAwB,CAAC;AAC5G,OAAO,EAAE,KAAK,sBAAsB,EAAe,MAAM,6BAA6B,CAAC;AAEvF,wBAAsB,mBAAmB,CAAC,MAAM,EAAE,sBAAsB,CAAC,QAAQ,CAAC,cAAc,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgBhG;AAED,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,kBAAkB,CAAC,QAAQ,CAAC,cAAc,EAAE,QAAQ,EAAE,QAAQ,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC,GAC/F,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAaxC;AAED,wBAAsB,kBAAkB,CAAC,MAAM,EAAE,sBAAsB,CAAC,UAAU,CAAC,gBAAgB,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiBnG;AAED,wBAAsB,YAAY,CAChC,MAAM,EAAE,kBAAkB,CAAC,UAAU,CAAC,gBAAgB,CAAC,EACvD,cAAc,EAAE,UAAU,GACzB,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,OAAO,kBAAkB,CAAC,CAAC,EAAE,QAAQ,CAAC,GAAG;IAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC,CAerG;AAED,wBAAsB,yBAAyB,CAAC,MAAM,EAAE,sBAAsB,CAAC,eAAe,CAAC,qBAAqB,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiBpH;AAED,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,kBAAkB,CAAC,eAAe,CAAC,qBAAqB,CAAC,EACjE,cAAc,EAAE,UAAU,GACzB,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,OAAO,yBAAyB,CAAC,CAAC,EAAE,QAAQ,CAAC,GAAG;IAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC,CAgB5G"}
@@ -11,7 +11,7 @@ export interface WorkerConfig<TParams = void, TBlocks = BlocksDb, TStates = Stat
11
11
  /** Open database. */
12
12
  openDatabase(options?: {
13
13
  readonly: boolean;
14
- }): RootDb<TBlocks, TStates>;
14
+ }): Promise<RootDb<TBlocks, TStates>>;
15
15
  }
16
16
  /**
17
17
  * Worker config with in-thread database.
@@ -32,6 +32,6 @@ export declare class DirectWorkerConfig<TParams = void, TBlocks = BlocksDb, TSta
32
32
  private constructor();
33
33
  openDatabase(_options?: {
34
34
  readonly: boolean;
35
- }): RootDb<TBlocks, TStates>;
35
+ }): Promise<RootDb<TBlocks, TStates>>;
36
36
  }
37
37
  //# sourceMappingURL=config.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../../../packages/workers/api/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAEtE,kCAAkC;AAClC,MAAM,WAAW,YAAY,CAAC,OAAO,GAAG,IAAI,EAAE,OAAO,GAAG,QAAQ,EAAE,OAAO,GAAG,QAAQ;IAClF,iBAAiB;IACjB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,kBAAkB;IAClB,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC;IAC9B,yBAAyB;IACzB,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;IAE/B,qBAAqB;IACrB,YAAY,CAAC,OAAO,CAAC,EAAE;QAAE,QAAQ,EAAE,OAAO,CAAA;KAAE,GAAG,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;CACzE;AAED;;GAEG;AACH,qBAAa,kBAAkB,CAAC,OAAO,GAAG,IAAI,EAAE,OAAO,GAAG,QAAQ,EAAE,OAAO,GAAG,QAAQ,CACpF,YAAW,YAAY,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;aAmBhC,QAAQ,EAAE,MAAM;aAChB,SAAS,EAAE,SAAS;aACpB,YAAY,EAAE,OAAO;IACrC,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IArB3B,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAClB,QAAQ,EACR,SAAS,EACT,QAAQ,EACR,QAAQ,EACR,YAAY,EAAE,MAAM,GACrB,EAAE;QACD,QAAQ,EAAE,MAAM,CAAC;QACjB,SAAS,EAAE,SAAS,CAAC;QACrB,QAAQ,EAAE,CAAC,CAAC;QACZ,QAAQ,EAAE,CAAC,CAAC;QACZ,YAAY,EAAE,CAAC,CAAC;KACjB,GAAG,kBAAkB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;IAI/B,OAAO;IAQP,YAAY,CAAC,QAAQ,CAAC,EAAE;QAAE,QAAQ,EAAE,OAAO,CAAA;KAAE,GAAG,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC;CAOzE"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../../../packages/workers/api/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAEtE,kCAAkC;AAClC,MAAM,WAAW,YAAY,CAAC,OAAO,GAAG,IAAI,EAAE,OAAO,GAAG,QAAQ,EAAE,OAAO,GAAG,QAAQ;IAClF,iBAAiB;IACjB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,kBAAkB;IAClB,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC;IAC9B,yBAAyB;IACzB,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;IAE/B,qBAAqB;IACrB,YAAY,CAAC,OAAO,CAAC,EAAE;QAAE,QAAQ,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;CAClF;AAED;;GAEG;AACH,qBAAa,kBAAkB,CAAC,OAAO,GAAG,IAAI,EAAE,OAAO,GAAG,QAAQ,EAAE,OAAO,GAAG,QAAQ,CACpF,YAAW,YAAY,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;aAmBhC,QAAQ,EAAE,MAAM;aAChB,SAAS,EAAE,SAAS;aACpB,YAAY,EAAE,OAAO;IACrC,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IArB3B,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAClB,QAAQ,EACR,SAAS,EACT,QAAQ,EACR,QAAQ,EACR,YAAY,EAAE,MAAM,GACrB,EAAE;QACD,QAAQ,EAAE,MAAM,CAAC;QACjB,SAAS,EAAE,SAAS,CAAC;QACrB,QAAQ,EAAE,CAAC,CAAC;QACZ,QAAQ,EAAE,CAAC,CAAC;QACZ,YAAY,EAAE,CAAC,CAAC;KACjB,GAAG,kBAAkB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;IAI/B,OAAO;IAQD,YAAY,CAAC,QAAQ,CAAC,EAAE;QAAE,QAAQ,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;CAOxF"}
@@ -17,7 +17,7 @@ export class DirectWorkerConfig {
17
17
  this.blocksDb = blocksDb;
18
18
  this.statesDb = statesDb;
19
19
  }
20
- openDatabase(_options) {
20
+ async openDatabase(_options) {
21
21
  return {
22
22
  getBlocksDb: () => this.blocksDb,
23
23
  getStatesDb: () => this.statesDb,
@@ -44,7 +44,8 @@ export interface Port {
44
44
  * so there is no need for any serialization - we simply pass the data.
45
45
  */
46
46
  export declare class DirectPort implements Port {
47
- private readonly events;
47
+ private readonly inbound;
48
+ private readonly outbound;
48
49
  readonly threadId = 0;
49
50
  /** Create a pair of symmetrical inter-connected ports. */
50
51
  static pair(): [DirectPort, DirectPort];
@@ -54,5 +55,8 @@ export declare class DirectPort implements Port {
54
55
  once<T>(event: string, _codec: Codec<T>, callback: (msg: Envelope<T>) => void): () => void;
55
56
  postMessage<T>(event: string, _codec: Codec<T>, msg: Envelope<T>): void;
56
57
  close(): void;
58
+ private queuePending;
59
+ private flushPending;
60
+ private closeState;
57
61
  }
58
62
  //# sourceMappingURL=port.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"port.d.ts","sourceRoot":"","sources":["../../../../../packages/workers/api/port.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAG9C;;;;;;GAMG;AACH,MAAM,MAAM,QAAQ,CAAC,CAAC,IAAI;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,CAAC,CAAC;CACT,CAAC;AAEF;;;;GAIG;AACH,MAAM,WAAW,IAAI;IACnB,0BAA0B;IAC1B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAE1B,0FAA0F;IAC1F,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC,EAAE,KAAK,KAAK,IAAI,GAAG,IAAI,CAAC;IAE5C;;;;OAIG;IACH,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;IAExF;;;;OAIG;IACH,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;IAE1F,2EAA2E;IAC3E,WAAW,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IAEvE,yCAAyC;IACzC,KAAK,IAAI,IAAI,CAAC;CACf;AAED;;;;;GAKG;AACH,qBAAa,UAAW,YAAW,IAAI;IASjB,OAAO,CAAC,QAAQ,CAAC,MAAM;IAR3C,QAAQ,CAAC,QAAQ,KAAK;IAEtB,0DAA0D;IAC1D,MAAM,CAAC,IAAI,IAAI,CAAC,UAAU,EAAE,UAAU,CAAC;IAKvC,OAAO;IAEP,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC,EAAE,KAAK,KAAK,IAAI,GAAG,IAAI;IAI3C,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC,KAAK,IAAI,GAAG,MAAM,IAAI;IAYxF,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC,KAAK,IAAI,GAAG,MAAM,IAAI;IAY1F,WAAW,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC,GAAG,IAAI;IAIvE,KAAK;CAIN"}
1
+ {"version":3,"file":"port.d.ts","sourceRoot":"","sources":["../../../../../packages/workers/api/port.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAG9C;;;;;;GAMG;AACH,MAAM,MAAM,QAAQ,CAAC,CAAC,IAAI;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,CAAC,CAAC;CACT,CAAC;AAEF;;;;GAIG;AACH,MAAM,WAAW,IAAI;IACnB,0BAA0B;IAC1B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAE1B,0FAA0F;IAC1F,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC,EAAE,KAAK,KAAK,IAAI,GAAG,IAAI,CAAC;IAE5C;;;;OAIG;IACH,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;IAExF;;;;OAIG;IACH,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;IAE1F,2EAA2E;IAC3E,WAAW,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IAEvE,yCAAyC;IACzC,KAAK,IAAI,IAAI,CAAC;CACf;AAOD;;;;;GAKG;AACH,qBAAa,UAAW,YAAW,IAAI;IAWnC,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAX3B,QAAQ,CAAC,QAAQ,KAAK;IAEtB,0DAA0D;IAC1D,MAAM,CAAC,IAAI,IAAI,CAAC,UAAU,EAAE,UAAU,CAAC;IAMvC,OAAO;IAKP,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC,EAAE,KAAK,KAAK,IAAI,GAAG,IAAI;IAI3C,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC,KAAK,IAAI,GAAG,MAAM,IAAI;IAaxF,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC,KAAK,IAAI,GAAG,MAAM,IAAI;IAuB1F,WAAW,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC,GAAG,IAAI;IAQvE,KAAK;IAKL,OAAO,CAAC,YAAY;IAMpB,OAAO,CAAC,YAAY;IAWpB,OAAO,CAAC,UAAU;CAKnB"}