@bjornpagen/bumbledb 1.0.1 → 1.1.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 (78) hide show
  1. package/COOKBOOK.md +64 -27
  2. package/README.md +21 -20
  3. package/dist/changes.d.ts +2 -3
  4. package/dist/changes.d.ts.map +1 -1
  5. package/dist/changes.js +35 -32
  6. package/dist/changes.js.map +1 -1
  7. package/dist/codec.d.ts +4 -5
  8. package/dist/codec.d.ts.map +1 -1
  9. package/dist/codec.js +6 -6
  10. package/dist/codec.js.map +1 -1
  11. package/dist/compile.d.ts +1 -2
  12. package/dist/compile.d.ts.map +1 -1
  13. package/dist/compile.js +5 -5
  14. package/dist/compile.js.map +1 -1
  15. package/dist/db-native.d.ts +37 -41
  16. package/dist/db-native.d.ts.map +1 -1
  17. package/dist/db-native.js.map +1 -1
  18. package/dist/db.d.ts +37 -22
  19. package/dist/db.d.ts.map +1 -1
  20. package/dist/db.js +71 -57
  21. package/dist/db.js.map +1 -1
  22. package/dist/index.d.ts +3 -3
  23. package/dist/index.d.ts.map +1 -1
  24. package/dist/index.js +1 -1
  25. package/dist/index.js.map +1 -1
  26. package/dist/internal/log.d.ts +4 -4
  27. package/dist/internal/log.d.ts.map +1 -1
  28. package/dist/internal/log.js +1 -1
  29. package/dist/internal/log.js.map +1 -1
  30. package/dist/law.d.ts +1 -1
  31. package/dist/migration.d.ts +2 -3
  32. package/dist/migration.d.ts.map +1 -1
  33. package/dist/migration.js +5 -5
  34. package/dist/migration.js.map +1 -1
  35. package/dist/native.d.ts +1 -1
  36. package/dist/native.d.ts.map +1 -1
  37. package/dist/native.js.map +1 -1
  38. package/dist/result.d.ts +10 -25
  39. package/dist/result.d.ts.map +1 -1
  40. package/dist/result.js +7 -12
  41. package/dist/result.js.map +1 -1
  42. package/dist/rows.d.ts +5 -11
  43. package/dist/rows.d.ts.map +1 -1
  44. package/dist/rows.js +6 -40
  45. package/dist/rows.js.map +1 -1
  46. package/dist/runtime-codes.d.ts +1 -1
  47. package/dist/runtime-codes.d.ts.map +1 -1
  48. package/dist/runtime-codes.js +1 -2
  49. package/dist/runtime-codes.js.map +1 -1
  50. package/dist/runtime-errors.d.ts +3 -15
  51. package/dist/runtime-errors.d.ts.map +1 -1
  52. package/dist/runtime-errors.js +1 -5
  53. package/dist/runtime-errors.js.map +1 -1
  54. package/dist/runtime-native.d.ts +16 -34
  55. package/dist/runtime-native.d.ts.map +1 -1
  56. package/dist/runtime-native.js.map +1 -1
  57. package/dist/runtime.d.ts +11 -28
  58. package/dist/runtime.d.ts.map +1 -1
  59. package/dist/runtime.js +14 -54
  60. package/dist/runtime.js.map +1 -1
  61. package/pack-provenance.json +3 -3
  62. package/package.json +4 -4
  63. package/src/changes.ts +46 -44
  64. package/src/codec.ts +7 -23
  65. package/src/compile.ts +5 -6
  66. package/src/db-native.ts +31 -68
  67. package/src/db.ts +148 -127
  68. package/src/index.ts +5 -4
  69. package/src/internal/log.ts +2 -5
  70. package/src/law.ts +1 -1
  71. package/src/migration.ts +5 -12
  72. package/src/native.ts +0 -1
  73. package/src/result.ts +16 -45
  74. package/src/rows.ts +6 -56
  75. package/src/runtime-codes.ts +1 -2
  76. package/src/runtime-errors.ts +1 -5
  77. package/src/runtime-native.ts +13 -46
  78. package/src/runtime.ts +51 -119
package/src/result.ts CHANGED
@@ -5,31 +5,22 @@ import { dbNative } from "#db-native.ts"
5
5
  import type { FindColumn } from "#query/atom.ts"
6
6
  import { decodeAnswers } from "#query/run.ts"
7
7
  import type { CellValue } from "#rows.ts"
8
- import type { ExecutionPolicy } from "#runtime.ts"
9
- import { deliveryResultBytes, nativeOperationWith, policyWire } from "#runtime.ts"
8
+ import { nativeOperationWith } from "#runtime.ts"
10
9
  import type { CloseReport, DbError } from "#runtime-errors.ts"
11
10
 
12
11
  /**
13
- * `CompleteResult<A>` — the sealed owner of one completed query answer:
14
- * published only after all evaluation/finalization succeeded,
15
- * possibly backed by temporary LMDB scratch. Owned and independent of its
16
- * source snapshot/session.
12
+ * One complete answer set, sealed after evaluation and independent of its
13
+ * source snapshot. collect() explicitly materializes all rows into JS and
14
+ * leaves the result available. pages() consumes it once through bounded
15
+ * delivery batches; it does not stream query execution.
17
16
  *
18
- * `collect` materializes a bounded owned array and leaves the result
19
- * available; it refuses (`ResourceLimit`) before allocating past
20
- * `maxBytes`, and a cap failure leaves the sealed backing available for
21
- * `pages`. `pages` is a one-shot consuming stream over the
22
- * completed result: its first execution atomically spends the result and
23
- * moves the backing storage into a private cursor owned by the stream's
24
- * scope — construction alone spends nothing, a second run fails
25
- * `SpentHandle`, and a run after the result's scope closed fails
26
- * `ClosedHandle`. Early take, downstream failure and interruption all
27
- * close/drain the private cursor; EOF cleanup is identical. There is no
28
- * public cursor, `next`, AsyncIterable, clone or second streaming API.
17
+ * The stream owns its cursor through Effect scope. Early termination,
18
+ * failure, interruption and EOF close/drain it. Creating the stream does
19
+ * not spend the result; running it twice fails with SpentHandle.
29
20
  */
30
21
  interface CompleteResult<A> {
31
- collect(options: { readonly maxBytes: bigint }, work: ExecutionPolicy): Effect.Effect<ReadonlyArray<A>, DbError>
32
- pages(options: { readonly pageBytes: bigint }, work: ExecutionPolicy): Stream.Stream<ReadonlyArray<A>, DbError>
22
+ collect(): Effect.Effect<ReadonlyArray<A>, DbError>
23
+ pages(): Stream.Stream<ReadonlyArray<A>, DbError>
33
24
  close(): Effect.Effect<CloseReport>
34
25
  }
35
26
 
@@ -52,42 +43,27 @@ function decodePage<A>(finds: readonly FindColumn[], rows: readonly (readonly Ce
52
43
 
53
44
  /**
54
45
  * Internal constructor: `db.ts` publishes results through this after
55
- * execution completes. Delivery (`collect`/`pages`) starts a fresh bounded
56
- * operation under the caller's delivery policy — never the completed query's
57
- * expired execution deadline.
46
+ * execution completes. Each delivery has independent cooperative cancellation.
58
47
  */
59
48
  function makeCompleteResult<A>(handle: ResultHandle, finds: readonly FindColumn[]): CompleteResult<A> {
60
- function deliveryWire(operation: string, delivery: ExecutionPolicy, requested: bigint) {
61
- return policyWire({ ...delivery, resultBytes: deliveryResultBytes(requested, delivery) }, operation)
62
- }
63
49
  const value: CompleteResult<A> = {
64
- collect(options, work) {
50
+ collect() {
65
51
  return Effect.suspend(() =>
66
52
  nativeOperationWith(
67
53
  "CompleteResult.collect",
68
- (callback) =>
69
- dbNative.runtimeResultCollect(
70
- handle,
71
- deliveryWire("CompleteResult.collect", work, options.maxBytes),
72
- callback
73
- ),
54
+ (callback) => dbNative.runtimeResultCollect(handle, callback),
74
55
  dbNative.runtimeRowsTake,
75
56
  (rows) => decodePage<A>(finds, rows)
76
57
  )
77
58
  )
78
59
  },
79
- pages(options, work) {
60
+ pages() {
80
61
  return Stream.unwrap(
81
62
  Effect.gen(function* () {
82
63
  const cursor: CursorHandle = yield* Effect.acquireRelease(
83
64
  nativeOperationWith(
84
65
  "CompleteResult.pages",
85
- (callback) =>
86
- dbNative.runtimeResultCursor(
87
- handle,
88
- deliveryWire("CompleteResult.pages", work, options.pageBytes),
89
- callback
90
- ),
66
+ (callback) => dbNative.runtimeResultCursor(handle, callback),
91
67
  dbNative.runtimeCursorTake,
92
68
  (taken) => taken
93
69
  ),
@@ -97,12 +73,7 @@ function makeCompleteResult<A>(handle: ResultHandle, finds: readonly FindColumn[
97
73
  return Stream.paginate(undefined, () =>
98
74
  nativeOperationWith(
99
75
  "CompleteResult.page",
100
- (callback) =>
101
- dbNative.runtimeCursorNext(
102
- cursor,
103
- deliveryWire("CompleteResult.page", work, options.pageBytes),
104
- callback
105
- ),
76
+ (callback) => dbNative.runtimeCursorNext(cursor, callback),
106
77
  dbNative.runtimePageTake,
107
78
  (page) => page
108
79
  ).pipe(
package/src/rows.ts CHANGED
@@ -21,9 +21,6 @@ import { isFloatIntervalValue, isIntervalValue, literalShapeError, rosterOf } fr
21
21
  import type { AnyRelation, Fact, RelationData } from "#relation.ts"
22
22
  import { Uuid } from "#uuid.ts"
23
23
 
24
- /** Converter-granularity host cell wall (64 KiB). One oversize cell refuses. */
25
- const HOST_CELL_MAX = 65536n
26
-
27
24
  /**
28
25
  * One owned cell at the private bridge boundary. The declared sealed field
29
26
  * type disambiguates the union: `string` is text, an `uuid` in its
@@ -44,8 +41,6 @@ type CellValue =
44
41
  interface FlatRows {
45
42
  readonly rows: bigint
46
43
  readonly cells: readonly CellValue[]
47
- /** Conservative charged byte size of the owned cells (input accounting). */
48
- readonly bytes: bigint
49
44
  }
50
45
 
51
46
  function recordOf(fact: object): Readonly<Record<string, unknown>> {
@@ -64,9 +59,8 @@ function refuseShared(context: string, value: Uint8Array): void {
64
59
  }
65
60
 
66
61
  /**
67
- * Cheap host charge before any string scan or byte copy. Strings charge
68
- * two bytes per UTF-16 code unit, not their UTF-8 wire size. Native admission
69
- * measures and bounds UTF-8 separately; byte views charge their length.
62
+ * Approximate payload size for host batching, not a memory allowance.
63
+ * Strings use two bytes per UTF-16 code unit, not their UTF-8 wire size.
70
64
  */
71
65
  function hostCellCharge(value: unknown): bigint {
72
66
  if (typeof value === "string") {
@@ -87,16 +81,6 @@ function hostCellCharge(value: unknown): bigint {
87
81
  return 0n
88
82
  }
89
83
 
90
- function assertHostCellFits(context: string, value: unknown, limit: bigint): bigint {
91
- const charge = hostCellCharge(value)
92
- if (charge > limit) {
93
- throw new AuthoringError({
94
- message: `${context}: host cell of ${charge} bytes exceeds the ${limit}-byte converter bound — refuse before copy or scan`
95
- })
96
- }
97
- return charge
98
- }
99
-
100
84
  /**
101
85
  * The write half of the closed bijection: one handle NAME to its u64 row
102
86
  * id (declaration order = row ids). An unknown name is a pointed refusal
@@ -125,25 +109,6 @@ function handleOf(context: string, closed: AnyClosedRoster, cell: unknown): stri
125
109
  return handle
126
110
  }
127
111
 
128
- /** Conservative owned-byte charge of one cell (host accounting, not wire). */
129
- function cellBytes(cell: CellValue): bigint {
130
- if (typeof cell === "boolean") {
131
- return 1n
132
- }
133
- if (typeof cell === "bigint" || typeof cell === "number") {
134
- return 8n
135
- }
136
- if (typeof cell === "string") {
137
- // Account for the host string here; native admission separately
138
- // checks and charges its exact UTF-8 encoding.
139
- return BigInt(cell.length) * 2n
140
- }
141
- if (cell instanceof Uint8Array) {
142
- return BigInt(cell.byteLength)
143
- }
144
- return 16n
145
- }
146
-
147
112
  function cellOf(context: string, field: AnyField, value: unknown): CellValue {
148
113
  const roster = rosterOf(field)
149
114
  if (roster !== undefined) {
@@ -170,7 +135,6 @@ function cellOf(context: string, field: AnyField, value: unknown): CellValue {
170
135
  if (typeof value !== "string") {
171
136
  throw literalShapeError(context, "string", value)
172
137
  }
173
- assertHostCellFits(context, value, HOST_CELL_MAX)
174
138
  if (!value.isWellFormed()) {
175
139
  throw literalShapeError(context, "well-formed string", value)
176
140
  }
@@ -194,7 +158,6 @@ function cellOf(context: string, field: AnyField, value: unknown): CellValue {
194
158
  throw literalShapeError(context, "Uint8Array", value)
195
159
  }
196
160
  refuseShared(context, value)
197
- assertHostCellFits(context, value, HOST_CELL_MAX)
198
161
  if (value.byteLength !== field.width) {
199
162
  throw new AuthoringError({
200
163
  message: `${context}: bytes<${field.width}> takes exactly ${field.width} bytes (got ${value.byteLength})`
@@ -231,14 +194,13 @@ function cellOf(context: string, field: AnyField, value: unknown): CellValue {
231
194
 
232
195
  /**
233
196
  * The flat projector: every fact's cells land in ONE row-major cell array
234
- * (length rows × arity) with the row count and charged byte size counted
235
- * while projecting. Missing-field refusal and per-cell judgment are
197
+ * (length rows × arity), counting rows while projecting.
198
+ * Missing-field refusal and per-cell judgment are
236
199
  * {@link cellOf}'s, byte for byte.
237
200
  */
238
201
  function flatRowsOf(data: RelationData, facts: Iterable<object>): FlatRows {
239
202
  const cells: CellValue[] = []
240
203
  let rows = 0n
241
- let bytes = 0n
242
204
  for (const fact of facts) {
243
205
  rows += 1n
244
206
  const record = recordOf(fact)
@@ -248,11 +210,10 @@ function flatRowsOf(data: RelationData, facts: Iterable<object>): FlatRows {
248
210
  throw new AuthoringError({ message: `relation ${data.name}: fact is missing field ${declared.name}` })
249
211
  }
250
212
  const cell = cellOf(`relation ${data.name} field ${declared.name}`, declared.field, value)
251
- bytes += cellBytes(cell)
252
213
  cells.push(cell)
253
214
  }
254
215
  }
255
- return { rows, cells, bytes }
216
+ return { rows, cells }
256
217
  }
257
218
 
258
219
  function keyCellsOf(
@@ -387,15 +348,4 @@ function factOfCells<R extends AnyRelation>(relation: R, row: readonly unknown[]
387
348
  }
388
349
 
389
350
  export type { CellValue, FlatRows }
390
- export {
391
- assertHostCellFits,
392
- cellBytes,
393
- cellOf,
394
- decodeCell,
395
- factOfCells,
396
- flatRowsOf,
397
- handleOf,
398
- hostCellCharge,
399
- keyCellsOf,
400
- recordOf
401
- }
351
+ export { cellOf, decodeCell, factOfCells, flatRowsOf, handleOf, hostCellCharge, keyCellsOf, recordOf }
@@ -13,6 +13,5 @@ export const runtimeErrorCodes = [
13
13
  "Io",
14
14
  "ResourceLimit",
15
15
  "Engine",
16
- "Cancelled",
17
- "DeadlineExceeded"
16
+ "Cancelled"
18
17
  ] as const
@@ -49,11 +49,7 @@ const Outstanding = Schema.Struct({
49
49
  retained: Schema.BigInt,
50
50
  owners: Schema.BigInt,
51
51
  databases: Schema.BigInt,
52
- natives: Schema.BigInt,
53
- inputBytes: Schema.BigInt,
54
- workingBytes: Schema.BigInt,
55
- scratchBytes: Schema.BigInt,
56
- resultBytes: Schema.BigInt
52
+ natives: Schema.BigInt
57
53
  })
58
54
  export type OutstandingWork = typeof Outstanding.Type
59
55
  const Close = Schema.Union([
@@ -34,7 +34,7 @@ export interface RepositoryLockHandle {
34
34
  }
35
35
 
36
36
  /** Resource kinds installed in native worker tables. */
37
- export type NativeKind = "snapshot" | "result" | "cursor" | "draft" | "changes" | "repository-lock"
37
+ export type NativeKind = "snapshot" | "prepared" | "result" | "cursor" | "draft" | "changes" | "repository-lock"
38
38
 
39
39
  /**
40
40
  * Checked capability into the native registry. JS tokens validate
@@ -96,28 +96,13 @@ export type LogTakeWire =
96
96
  readonly digest: Uint8Array
97
97
  }
98
98
 
99
- export interface PolicyWire {
100
- readonly inputBytes: bigint
101
- readonly workingBytes: bigint
102
- readonly scratchBytes: bigint
103
- readonly resultBytes: bigint
104
- readonly rows: bigint
105
- readonly workUnits: bigint
106
- readonly timeoutMs: number
107
- }
108
-
109
99
  export interface OptionsWire {
110
- readonly workers: number
111
- readonly queueCapacity: number
112
- readonly cleanupCapacity: number
113
- readonly ownerCapacity: number
114
- readonly nativeHandleCapacity: number
115
- readonly inputBytes: bigint
116
- readonly workingBytes: bigint
117
- readonly scratchBytes: bigint
118
- readonly resultBytes: bigint
119
- readonly chunkBytes: bigint
120
- readonly cleanupTimeoutMs: number
100
+ readonly workers?: number | undefined
101
+ readonly queueCapacity?: number | undefined
102
+ readonly cleanupCapacity?: number | undefined
103
+ readonly ownerCapacity?: number | undefined
104
+ readonly nativeHandleCapacity?: number | undefined
105
+ readonly cleanupTimeoutMs?: number | undefined
121
106
  }
122
107
 
123
108
  export interface InspectionWire {
@@ -128,10 +113,6 @@ export interface InspectionWire {
128
113
  readonly owners: bigint
129
114
  readonly databases: bigint
130
115
  readonly natives: bigint
131
- readonly inputBytes: bigint
132
- readonly workingBytes: bigint
133
- readonly scratchBytes: bigint
134
- readonly resultBytes: bigint
135
116
  }
136
117
 
137
118
  export type CloseWire =
@@ -142,8 +123,8 @@ export type CloseWire =
142
123
  interface RuntimeNative {
143
124
  runtimeErrorCodes(): readonly string[]
144
125
  runtimeOpen(options: OptionsWire): RuntimeHandle
145
- runtimeReady(runtime: RuntimeHandle, policy: PolicyWire, callback: () => void): OperationHandle
146
- runtimeHash(runtime: RuntimeHandle, policy: PolicyWire, bytes: Uint8Array, callback: () => void): OperationHandle
126
+ runtimeReady(runtime: RuntimeHandle, callback: () => void): OperationHandle
127
+ runtimeHash(runtime: RuntimeHandle, bytes: Uint8Array, callback: () => void): OperationHandle
147
128
  runtimeTake(operation: OperationHandle): Uint8Array | null
148
129
  runtimeCancel(operation: OperationHandle, callback: (report: CloseWire) => void): void
149
130
  runtimeClose(runtime: RuntimeHandle, callback: (report: CloseWire) => void): void
@@ -156,20 +137,14 @@ interface RuntimeNative {
156
137
  * Predelivery: no JS take; cursor stays on row1 so retry does not skip.
157
138
  */
158
139
  runtimeArmPublicationCancel(runtime: RuntimeHandle): void
159
- runtimeDirectoryAcquire(
160
- runtime: RuntimeHandle,
161
- policy: PolicyWire,
162
- path: string,
163
- callback: () => void
164
- ): OperationHandle
140
+ runtimeDirectoryAcquire(runtime: RuntimeHandle, path: string, callback: () => void): OperationHandle
165
141
  runtimeDirectoryTake(operation: OperationHandle): DirectoryHandle
166
- runtimeDirectoryBegin(owner: DirectoryHandle, policy: PolicyWire): OperationHandle
142
+ runtimeDirectoryBegin(owner: DirectoryHandle): OperationHandle
167
143
  runtimeDirectoryCheck(operation: OperationHandle): void
168
144
  runtimeDirectoryEnd(operation: OperationHandle): void
169
145
  runtimeDirectoryClose(owner: DirectoryHandle, remove: boolean, callback: (report: CloseWire) => void): void
170
146
  runtimeDirectoryDbOpen(
171
147
  owner: DirectoryHandle,
172
- policy: PolicyWire,
173
148
  childName: string,
174
149
  spec: SchemaSpec,
175
150
  create: boolean,
@@ -178,12 +153,11 @@ interface RuntimeNative {
178
153
  runtimeDbTake(operation: OperationHandle): ManagedDbOutcome
179
154
  runtimeManagedDbClose(db: DbHandle, callback: (report: CloseWire) => void): void
180
155
 
181
- // --- successor log grammar on the executor (charged hashing over
156
+ // --- successor log grammar on the executor (hashing over
182
157
  // whole canonical change payloads; C06 through C09) ---
183
158
  runtimeLogCommandSeal(
184
159
  runtime: RuntimeHandle,
185
160
  schema: LogSchemaHandle,
186
- policy: PolicyWire,
187
161
  metadata: LogCommandMetadata,
188
162
  changes: Uint8Array,
189
163
  result: Uint8Array | null,
@@ -193,14 +167,12 @@ interface RuntimeNative {
193
167
  runtimeLogCommandParse(
194
168
  runtime: RuntimeHandle,
195
169
  schema: LogSchemaHandle,
196
- policy: PolicyWire,
197
170
  bytes: Uint8Array,
198
171
  limits: LogLimits,
199
172
  callback: () => void
200
173
  ): OperationHandle
201
174
  runtimeLogDecisionDecode(
202
175
  runtime: RuntimeHandle,
203
- policy: PolicyWire,
204
176
  bytes: Uint8Array,
205
177
  parent: LogDecisionStamp | null,
206
178
  limits: LogLimits,
@@ -208,12 +180,7 @@ interface RuntimeNative {
208
180
  ): OperationHandle
209
181
  runtimeLogTake(operation: OperationHandle): LogTakeWire
210
182
  /** L14 mint: `Runtime::mint_repository_lock` stamps `NativeKind::RepositoryLock` at take. */
211
- logRepositoryLockAcquire(
212
- runtime: RuntimeHandle,
213
- policy: PolicyWire,
214
- directory: string,
215
- callback: () => void
216
- ): OperationHandle
183
+ logRepositoryLockAcquire(runtime: RuntimeHandle, directory: string, callback: () => void): OperationHandle
217
184
  logRepositoryLockTake(operation: OperationHandle): RepositoryLockHandle
218
185
  logRepositoryLockRelease(owner: RepositoryLockHandle, callback: (report: CloseWire) => void): void
219
186
  }
package/src/runtime.ts CHANGED
@@ -1,43 +1,21 @@
1
1
  import { Context, Duration, Effect, Exit, Layer } from "effect"
2
2
  import type { CloseReport, OutstandingWork } from "#runtime-errors.ts"
3
3
  import { CloseFailure, DbError, dbError } from "#runtime-errors.ts"
4
- import type {
5
- CloseWire,
6
- OperationHandle,
7
- OptionsWire,
8
- PolicyWire,
9
- RepositoryLockHandle,
10
- RuntimeHandle
11
- } from "#runtime-native.ts"
4
+ import type { CloseWire, OperationHandle, OptionsWire, RepositoryLockHandle, RuntimeHandle } from "#runtime-native.ts"
12
5
  import { runtimeNative } from "#runtime-native.ts"
13
6
 
14
- export interface ExecutionPolicy {
15
- readonly inputBytes: bigint
16
- readonly workingBytes: bigint
17
- readonly scratchBytes: bigint
18
- readonly resultBytes: bigint
19
- readonly rows: bigint
20
- readonly workUnits: bigint
21
- readonly timeout: Duration.Input
22
- }
23
-
24
7
  export interface NativeRuntimeOptions {
25
- readonly workers: number
26
- readonly queueCapacity: number
27
- readonly cleanupCapacity: number
28
- readonly ownerCapacity: number
29
- readonly nativeHandleCapacity: number
30
- readonly inputBytes: bigint
31
- readonly workingBytes: bigint
32
- readonly scratchBytes: bigint
33
- readonly resultBytes: bigint
34
- readonly chunkBytes: bigint
35
- readonly cleanupTimeout: Duration.Input
8
+ readonly workers?: number
9
+ readonly queueCapacity?: number
10
+ readonly cleanupCapacity?: number
11
+ readonly ownerCapacity?: number
12
+ readonly nativeHandleCapacity?: number
13
+ readonly cleanupTimeout?: Duration.Input
36
14
  }
37
15
 
38
16
  interface RuntimeService {
39
17
  readonly close: () => Effect.Effect<CloseReport>
40
- readonly inspect: (work: ExecutionPolicy) => Effect.Effect<OutstandingWork, DbError>
18
+ readonly inspect: () => Effect.Effect<OutstandingWork, DbError>
41
19
  }
42
20
 
43
21
  const owners = new WeakMap<RuntimeService, RuntimeHandle>()
@@ -51,43 +29,23 @@ function count(value: number, operation: string): number {
51
29
  return value
52
30
  }
53
31
 
54
- function bytes(value: bigint, operation: string): bigint {
55
- if (typeof value !== "bigint" || value < 0n || value > 0xffffffffffffffffn) throw invalid(operation)
56
- return value
57
- }
58
-
59
32
  function millis(value: Duration.Input, operation: string): number {
60
33
  const duration = Duration.toMillis(value)
61
34
  if (!Number.isFinite(duration) || duration < 0 || duration > 0xffffffff) throw invalid(operation)
62
35
  return Math.ceil(duration)
63
36
  }
64
37
 
65
- export function policyWire(work: ExecutionPolicy, operation: string): PolicyWire {
66
- return {
67
- inputBytes: bytes(work.inputBytes, operation),
68
- workingBytes: bytes(work.workingBytes, operation),
69
- scratchBytes: bytes(work.scratchBytes, operation),
70
- resultBytes: bytes(work.resultBytes, operation),
71
- rows: bytes(work.rows, operation),
72
- workUnits: bytes(work.workUnits, operation),
73
- timeoutMs: millis(work.timeout, operation)
74
- }
75
- }
76
-
77
38
  function options(value: NativeRuntimeOptions): OptionsWire {
78
39
  const operation = "NativeRuntime.acquire"
79
40
  return {
80
- workers: count(value.workers, operation),
81
- queueCapacity: count(value.queueCapacity, operation),
82
- cleanupCapacity: count(value.cleanupCapacity, operation),
83
- ownerCapacity: count(value.ownerCapacity, operation),
84
- nativeHandleCapacity: count(value.nativeHandleCapacity, operation),
85
- inputBytes: bytes(value.inputBytes, operation),
86
- workingBytes: bytes(value.workingBytes, operation),
87
- scratchBytes: bytes(value.scratchBytes, operation),
88
- resultBytes: bytes(value.resultBytes, operation),
89
- chunkBytes: bytes(value.chunkBytes, operation),
90
- cleanupTimeoutMs: count(millis(value.cleanupTimeout, operation), operation)
41
+ workers: value.workers === undefined ? undefined : count(value.workers, operation),
42
+ queueCapacity: value.queueCapacity === undefined ? undefined : count(value.queueCapacity, operation),
43
+ cleanupCapacity: value.cleanupCapacity === undefined ? undefined : count(value.cleanupCapacity, operation),
44
+ ownerCapacity: value.ownerCapacity === undefined ? undefined : count(value.ownerCapacity, operation),
45
+ nativeHandleCapacity:
46
+ value.nativeHandleCapacity === undefined ? undefined : count(value.nativeHandleCapacity, operation),
47
+ cleanupTimeoutMs:
48
+ value.cleanupTimeout === undefined ? undefined : count(millis(value.cleanupTimeout, operation), operation)
91
49
  }
92
50
  }
93
51
 
@@ -169,14 +127,6 @@ function afterClose<A, E, R>(
169
127
  return effect.pipe(Effect.onExit(() => Effect.die(new CloseFailure({ operation, report }))))
170
128
  }
171
129
 
172
- /** Independent caps intersect: a delivery request cannot enlarge `work.resultBytes`. */
173
- export function deliveryResultBytes(requested: bigint, work: ExecutionPolicy): bigint {
174
- if (typeof requested !== "bigint" || requested < 0n) {
175
- throw invalid("deliveryResultBytes")
176
- }
177
- return requested < work.resultBytes ? requested : work.resultBytes
178
- }
179
-
180
130
  function close(handle: RuntimeHandle): Effect.Effect<CloseReport> {
181
131
  return drain("NativeRuntime.close", (callback) => runtimeNative.runtimeClose(handle, callback))
182
132
  }
@@ -257,54 +207,41 @@ const acquire = Effect.fn("NativeRuntime.acquire")(function* (configuration: Nat
257
207
  const wire = options(configuration)
258
208
  handle = runtimeNative.runtimeOpen(wire)
259
209
  const owner = handle
260
- const lease = runtimeNative.runtimeReady(
261
- owner,
262
- {
263
- inputBytes: 0n,
264
- workingBytes: 0n,
265
- scratchBytes: 0n,
266
- resultBytes: 0n,
267
- rows: 0n,
268
- workUnits: 1n,
269
- timeoutMs: wire.cleanupTimeoutMs
270
- },
271
- () => {
272
- if (signal.aborted) {
273
- try {
274
- runtimeNative.runtimeClose(owner, (report) => {
275
- stash.report = closeReport("NativeRuntime.acquire.cancel", report)
276
- })
277
- } catch (cause) {
278
- stash.report = { kind: "failed", error: failure("NativeRuntime.acquire.cancel", cause) }
279
- }
280
- return
281
- }
210
+ const lease = runtimeNative.runtimeReady(owner, () => {
211
+ if (signal.aborted) {
282
212
  try {
283
- runtimeNative.runtimeTake(lease)
284
- const service: RuntimeService = {
285
- close: () => close(owner),
286
- inspect: Effect.fn("NativeRuntime.inspect")(function* (work) {
287
- yield* nativeOperation(
288
- "NativeRuntime.inspect",
289
- (callback) =>
290
- runtimeNative.runtimeReady(owner, policyWire(work, "NativeRuntime.inspect"), callback),
291
- () => undefined
292
- )
293
- return runtimeNative.runtimeInspect(owner)
294
- })
295
- }
296
- owners.set(service, owner)
297
- resume(Effect.succeed(service))
213
+ runtimeNative.runtimeClose(owner, (report) => {
214
+ stash.report = closeReport("NativeRuntime.acquire.cancel", report)
215
+ })
298
216
  } catch (cause) {
299
- const error = failure("NativeRuntime.acquire", cause)
300
- resume(
301
- close(owner).pipe(
302
- Effect.flatMap((report) => afterClose("NativeRuntime.acquire", report, Effect.fail(error)))
217
+ stash.report = { kind: "failed", error: failure("NativeRuntime.acquire.cancel", cause) }
218
+ }
219
+ return
220
+ }
221
+ try {
222
+ runtimeNative.runtimeTake(lease)
223
+ const service: RuntimeService = {
224
+ close: () => close(owner),
225
+ inspect: Effect.fn("NativeRuntime.inspect")(function* () {
226
+ yield* nativeOperation(
227
+ "NativeRuntime.inspect",
228
+ (callback) => runtimeNative.runtimeReady(owner, callback),
229
+ () => undefined
303
230
  )
304
- )
231
+ return runtimeNative.runtimeInspect(owner)
232
+ })
305
233
  }
234
+ owners.set(service, owner)
235
+ resume(Effect.succeed(service))
236
+ } catch (cause) {
237
+ const error = failure("NativeRuntime.acquire", cause)
238
+ resume(
239
+ close(owner).pipe(
240
+ Effect.flatMap((report) => afterClose("NativeRuntime.acquire", report, Effect.fail(error)))
241
+ )
242
+ )
306
243
  }
307
- )
244
+ })
308
245
  } catch (cause) {
309
246
  const error = failure("NativeRuntime.acquire", cause)
310
247
  resume(
@@ -333,7 +270,7 @@ const acquire = Effect.fn("NativeRuntime.acquire")(function* (configuration: Nat
333
270
  export class NativeRuntime extends Context.Service<NativeRuntime, RuntimeService>()(
334
271
  "@bjornpagen/bumbledb/NativeRuntime"
335
272
  ) {
336
- static layer(options: NativeRuntimeOptions): Layer.Layer<NativeRuntime, DbError> {
273
+ static layer(options: NativeRuntimeOptions = {}): Layer.Layer<NativeRuntime, DbError> {
337
274
  return Layer.effect(NativeRuntime, acquire(options))
338
275
  }
339
276
  }
@@ -374,17 +311,12 @@ function joinLockRelease(operation: string, owner: RepositoryLockHandle): Effect
374
311
  */
375
312
  export const internalAcquireRepositoryLock = Effect.fn("internalAcquireRepositoryLock")(function* (
376
313
  operation: string,
377
- directory: string,
378
- work: ExecutionPolicy
314
+ directory: string
379
315
  ) {
380
316
  if (directory.length === 0) {
381
317
  return yield* Effect.fail(invalid(operation))
382
318
  }
383
319
  const runtime = yield* runtimeHandle()
384
- const wire = yield* Effect.try({
385
- try: () => policyWire(work, operation),
386
- catch: () => invalid(operation)
387
- })
388
320
  const closeOp = `${operation}.repositoryLock`
389
321
  return yield* Effect.uninterruptibleMask((restore) =>
390
322
  Effect.gen(function* () {
@@ -406,7 +338,7 @@ export const internalAcquireRepositoryLock = Effect.fn("internalAcquireRepositor
406
338
  const owner = yield* restore(
407
339
  nativeOperationWith(
408
340
  operation,
409
- (callback) => runtimeNative.logRepositoryLockAcquire(runtime, wire, directory, callback),
341
+ (callback) => runtimeNative.logRepositoryLockAcquire(runtime, directory, callback),
410
342
  runtimeNative.logRepositoryLockTake,
411
343
  (value) => value
412
344
  )
@@ -421,7 +353,7 @@ export const internalAcquireRepositoryLock = Effect.fn("internalAcquireRepositor
421
353
  })
422
354
 
423
355
  /** Internal first executor consumer; not a replacement row codec or public hash API. */
424
- export const hashChunk = Effect.fn("bumbledb.hashChunk")(function* (input: Uint8Array, work: ExecutionPolicy) {
356
+ export const hashChunk = Effect.fn("bumbledb.hashChunk")(function* (input: Uint8Array) {
425
357
  const runtime = yield* NativeRuntime
426
358
  const handle = owners.get(runtime)
427
359
  if (handle === undefined) return yield* Effect.fail(invalid("hashChunk"))
@@ -429,7 +361,7 @@ export const hashChunk = Effect.fn("bumbledb.hashChunk")(function* (input: Uint8
429
361
  "hashChunk",
430
362
  (callback) => {
431
363
  if (!(input instanceof Uint8Array) || !(input.buffer instanceof ArrayBuffer)) throw invalid("hashChunk")
432
- return runtimeNative.runtimeHash(handle, policyWire(work, "hashChunk"), input, callback)
364
+ return runtimeNative.runtimeHash(handle, input, callback)
433
365
  },
434
366
  (value) => {
435
367
  if (value === null) throw dbError("hashChunk", { _tag: "Internal" })