@smoothbricks/lmao 0.2.1 → 0.2.3
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/dist/allocator.wasm +0 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/lib/JsBufferStrategy.d.ts +4 -3
- package/dist/lib/JsBufferStrategy.d.ts.map +1 -1
- package/dist/lib/JsBufferStrategy.js +18 -11
- package/dist/lib/arrow/lease.d.ts +10 -0
- package/dist/lib/arrow/lease.d.ts.map +1 -0
- package/dist/lib/arrow/lease.js +33 -0
- package/dist/lib/arrow/utils.d.ts +3 -4
- package/dist/lib/arrow/utils.d.ts.map +1 -1
- package/dist/lib/arrow/utils.js +12 -13
- package/dist/lib/arrow/vocabularyDictionary.d.ts +21 -0
- package/dist/lib/arrow/vocabularyDictionary.d.ts.map +1 -0
- package/dist/lib/arrow/vocabularyDictionary.js +95 -0
- package/dist/lib/bufferStrategy.d.ts +3 -2
- package/dist/lib/bufferStrategy.d.ts.map +1 -1
- package/dist/lib/cloudflare/traceRows.d.ts.map +1 -1
- package/dist/lib/cloudflare/traceRows.js +3 -2
- package/dist/lib/codegen/evaluatorGenerator.d.ts.map +1 -1
- package/dist/lib/codegen/evaluatorGenerator.js +12 -11
- package/dist/lib/codegen/fixedPositionWriterGenerator.d.ts +44 -82
- package/dist/lib/codegen/fixedPositionWriterGenerator.d.ts.map +1 -1
- package/dist/lib/codegen/fixedPositionWriterGenerator.js +223 -162
- package/dist/lib/codegen/spanLoggerClosureMaterializer.d.ts +63 -0
- package/dist/lib/codegen/spanLoggerClosureMaterializer.d.ts.map +1 -0
- package/dist/lib/codegen/spanLoggerClosureMaterializer.js +447 -0
- package/dist/lib/codegen/spanLoggerGenerator.d.ts +36 -19
- package/dist/lib/codegen/spanLoggerGenerator.d.ts.map +1 -1
- package/dist/lib/codegen/spanLoggerGenerator.js +164 -158
- package/dist/lib/convertToArrow.d.ts +7 -2
- package/dist/lib/convertToArrow.d.ts.map +1 -1
- package/dist/lib/convertToArrow.js +499 -285
- package/dist/lib/defineOpContext.js +1 -1
- package/dist/lib/enumMetadata.d.ts +19 -0
- package/dist/lib/enumMetadata.d.ts.map +1 -0
- package/dist/lib/enumMetadata.js +86 -0
- package/dist/lib/flushScheduler.d.ts.map +1 -1
- package/dist/lib/flushScheduler.js +13 -4
- package/dist/lib/library.d.ts +16 -98
- package/dist/lib/library.d.ts.map +1 -1
- package/dist/lib/library.js +32 -525
- package/dist/lib/logBinding.d.ts +21 -27
- package/dist/lib/logBinding.d.ts.map +1 -1
- package/dist/lib/op.d.ts +30 -30
- package/dist/lib/op.d.ts.map +1 -1
- package/dist/lib/op.js +15 -22
- package/dist/lib/opContext/createOpGroup.d.ts +1 -1
- package/dist/lib/opContext/createOpGroup.d.ts.map +1 -1
- package/dist/lib/opContext/createOpGroup.js +22 -29
- package/dist/lib/opContext/defineOp.d.ts +4 -4
- package/dist/lib/opContext/defineOp.d.ts.map +1 -1
- package/dist/lib/opContext/defineOp.js +53 -10
- package/dist/lib/opContext/opGroupTypes.d.ts +2 -2
- package/dist/lib/opContext/opTypes.d.ts +1 -1
- package/dist/lib/opContext/opTypes.d.ts.map +1 -1
- package/dist/lib/opContext/spanContextTypes.d.ts +29 -14
- package/dist/lib/opContext/spanContextTypes.d.ts.map +1 -1
- package/dist/lib/opContext/types.d.ts +4 -4
- package/dist/lib/opContext/types.d.ts.map +1 -1
- package/dist/lib/physicalLayoutPlan.d.ts +89 -0
- package/dist/lib/physicalLayoutPlan.d.ts.map +1 -0
- package/dist/lib/physicalLayoutPlan.js +442 -0
- package/dist/lib/resolveMessage.d.ts +9 -0
- package/dist/lib/resolveMessage.d.ts.map +1 -0
- package/dist/lib/resolveMessage.js +63 -0
- package/dist/lib/result.d.ts +5 -7
- package/dist/lib/result.d.ts.map +1 -1
- package/dist/lib/result.js +19 -26
- package/dist/lib/runtimeHint.d.ts +35 -0
- package/dist/lib/runtimeHint.d.ts.map +1 -0
- package/dist/lib/runtimeHint.js +79 -0
- package/dist/lib/schema/types.d.ts +1 -1
- package/dist/lib/schema/types.d.ts.map +1 -1
- package/dist/lib/span-buffer/aot/v1.d.ts +2 -0
- package/dist/lib/span-buffer/aot/v1.d.ts.map +1 -0
- package/dist/lib/span-buffer/aot/v1.js +24 -0
- package/dist/lib/spanBuffer.d.ts +33 -4
- package/dist/lib/spanBuffer.d.ts.map +1 -1
- package/dist/lib/spanBuffer.js +583 -91
- package/dist/lib/spanBufferStats.d.ts +1 -1
- package/dist/lib/spanBufferStats.d.ts.map +1 -1
- package/dist/lib/spanContext.d.ts +27 -51
- package/dist/lib/spanContext.d.ts.map +1 -1
- package/dist/lib/spanContext.js +822 -344
- package/dist/lib/sqlite/sqlite-common.d.ts.map +1 -1
- package/dist/lib/sqlite/sqlite-common.js +20 -21
- package/dist/lib/testing/bun-harness.d.ts +8 -3
- package/dist/lib/testing/bun-harness.d.ts.map +1 -1
- package/dist/lib/testing/bun-harness.js +30 -18
- package/dist/lib/testing/extractFacts.d.ts +1 -1
- package/dist/lib/testing/extractFacts.d.ts.map +1 -1
- package/dist/lib/testing/extractFacts.js +55 -63
- package/dist/lib/testing/facts.d.ts +1 -1
- package/dist/lib/testing/facts.d.ts.map +1 -1
- package/dist/lib/testing/queryable-span.d.ts +1 -1
- package/dist/lib/testing/queryable-span.d.ts.map +1 -1
- package/dist/lib/testing/queryable-span.js +26 -28
- package/dist/lib/testing/span-query.d.ts.map +1 -1
- package/dist/lib/testing/span-query.js +19 -22
- package/dist/lib/testing/stdio-replay.d.ts.map +1 -1
- package/dist/lib/testing/stdio-replay.js +19 -8
- package/dist/lib/threadId.d.ts.map +1 -1
- package/dist/lib/threadId.js +6 -3
- package/dist/lib/traceRoot.d.ts +30 -8
- package/dist/lib/traceRoot.d.ts.map +1 -1
- package/dist/lib/traceRoot.es.d.ts +17 -15
- package/dist/lib/traceRoot.es.d.ts.map +1 -1
- package/dist/lib/traceRoot.es.js +68 -34
- package/dist/lib/traceRoot.js +11 -0
- package/dist/lib/traceRoot.node.d.ts +17 -19
- package/dist/lib/traceRoot.node.d.ts.map +1 -1
- package/dist/lib/traceRoot.node.js +66 -38
- package/dist/lib/traceTopology.d.ts +42 -0
- package/dist/lib/traceTopology.d.ts.map +1 -0
- package/dist/lib/traceTopology.js +260 -0
- package/dist/lib/tracer.d.ts +9 -5
- package/dist/lib/tracer.d.ts.map +1 -1
- package/dist/lib/tracer.js +65 -71
- package/dist/lib/tracers/ArrayQueueTracer.d.ts +1 -1
- package/dist/lib/tracers/ArrayQueueTracer.js +1 -1
- package/dist/lib/tracers/StdioTracer.d.ts.map +1 -1
- package/dist/lib/tracers/StdioTracer.js +15 -13
- package/dist/lib/tracers/TestTracer.d.ts +4 -6
- package/dist/lib/tracers/TestTracer.d.ts.map +1 -1
- package/dist/lib/tracers/TestTracer.js +6 -8
- package/dist/lib/types.d.ts +49 -32
- package/dist/lib/types.d.ts.map +1 -1
- package/dist/lib/vocabularyRegistry.d.ts +25 -0
- package/dist/lib/vocabularyRegistry.d.ts.map +1 -0
- package/dist/lib/vocabularyRegistry.js +372 -0
- package/dist/lib/wasm/WasmBufferStrategy.d.ts +6 -10
- package/dist/lib/wasm/WasmBufferStrategy.d.ts.map +1 -1
- package/dist/lib/wasm/WasmBufferStrategy.js +44 -37
- package/dist/lib/wasm/wasmAllocator.d.ts +27 -22
- package/dist/lib/wasm/wasmAllocator.d.ts.map +1 -1
- package/dist/lib/wasm/wasmAllocator.js +66 -44
- package/dist/lib/wasm/wasmPhysicalLayout.d.ts +67 -0
- package/dist/lib/wasm/wasmPhysicalLayout.d.ts.map +1 -0
- package/dist/lib/wasm/wasmPhysicalLayout.js +179 -0
- package/dist/lib/wasm/wasmSpanBuffer.d.ts +79 -31
- package/dist/lib/wasm/wasmSpanBuffer.d.ts.map +1 -1
- package/dist/lib/wasm/wasmSpanBuffer.js +442 -272
- package/dist/lib/wasm/wasmTraceRoot.d.ts +24 -22
- package/dist/lib/wasm/wasmTraceRoot.d.ts.map +1 -1
- package/dist/lib/wasm/wasmTraceRoot.js +110 -71
- package/dist/vocabulary/register/v1.d.ts +2 -0
- package/dist/vocabulary/register/v1.d.ts.map +1 -0
- package/dist/vocabulary/register/v1.js +1 -0
- package/dist/wasm.d.ts +5 -0
- package/dist/wasm.d.ts.map +1 -0
- package/dist/wasm.js +4 -0
- package/package.json +54 -6
- package/src/index.ts +1 -0
- package/src/lib/JsBufferStrategy.ts +27 -9
- package/src/lib/__tests__/arrow-builder-integration/arrow-conversion.test.ts +335 -37
- package/src/lib/__tests__/arrow-builder-integration/binary-arrow-conversion.test.ts +97 -26
- package/src/lib/__tests__/arrow-builder-integration/binary-comparison.test.ts +75 -15
- package/src/lib/__tests__/arrow-builder-integration/binary-format-compliance.test.ts +30 -6
- package/src/lib/__tests__/arrow-builder-integration/buffer-chaining.test.ts +18 -21
- package/src/lib/__tests__/arrow-builder-integration/foundation.test.ts +5 -2
- package/src/lib/__tests__/arrow-builder-integration/integration.test.ts +25 -7
- package/src/lib/__tests__/arrow-builder-integration/lazy-columns.test.ts +3 -2
- package/src/lib/__tests__/buffer-overflow.test.ts +24 -18
- package/src/lib/__tests__/capability-span-context.test.ts +505 -0
- package/src/lib/__tests__/capacity-tuning.test.ts +5 -3
- package/src/lib/__tests__/eager-columns.test.ts +345 -0
- package/src/lib/__tests__/enum-metadata-aot.test.ts +153 -0
- package/src/lib/__tests__/enum-metadata.test.ts +177 -0
- package/src/lib/__tests__/fixtures/empty-vocabulary-runtime.fixture.ts +15 -0
- package/src/lib/__tests__/flushScheduler.test.ts +5 -1
- package/src/lib/__tests__/identity-view.property.test.ts +179 -0
- package/src/lib/__tests__/library.test.ts +19 -235
- package/src/lib/__tests__/message-buffer-families.test.ts +878 -0
- package/src/lib/__tests__/nested-library-tasks.test.ts +14 -15
- package/src/lib/__tests__/op-metadata.test.ts +1 -1
- package/src/lib/__tests__/op-type-safety.test.ts +5 -16
- package/src/lib/__tests__/physical-layout-plan.test.ts +333 -0
- package/src/lib/__tests__/remap-descriptor-integration.test.ts +381 -0
- package/src/lib/__tests__/root-context-construction.test.ts +414 -0
- package/src/lib/__tests__/span-auto-runtime.test.ts +386 -0
- package/src/lib/__tests__/span-buffer-segment-stats.test.ts +221 -0
- package/src/lib/__tests__/span-lifecycle.test.ts +53 -25
- package/src/lib/__tests__/spanbuffer-materializer-parity.test.ts +266 -0
- package/src/lib/__tests__/sync-async-trace.test.ts +24 -23
- package/src/lib/__tests__/tag-writer-aot.test.ts +214 -0
- package/src/lib/__tests__/test-helpers.ts +67 -12
- package/src/lib/__tests__/threadId.test.ts +62 -0
- package/src/lib/__tests__/timestamp.test.ts +221 -93
- package/src/lib/__tests__/traceTopology.property.test.ts +383 -0
- package/src/lib/__tests__/type-narrowing.test.ts +63 -0
- package/src/lib/__tests__/vocabulary-dense-decoding.test.ts +405 -0
- package/src/lib/__tests__/vocabularyRegistry.test.ts +313 -0
- package/src/lib/arrow/lease.ts +43 -0
- package/src/lib/arrow/utils.ts +10 -14
- package/src/lib/arrow/vocabularyDictionary.ts +123 -0
- package/src/lib/bufferStrategy.ts +9 -1
- package/src/lib/cloudflare/traceRows.ts +3 -2
- package/src/lib/codegen/__tests__/evaluatorGenerator.test.ts +21 -141
- package/src/lib/codegen/__tests__/fixedPositionWriter-parity.test.ts +273 -0
- package/src/lib/codegen/__tests__/fixedPositionWriter-uint64.test.ts +61 -34
- package/src/lib/codegen/__tests__/nullBitmap.test.ts +33 -37
- package/src/lib/codegen/__tests__/spanLoggerGenerator.test.ts +34 -18
- package/src/lib/codegen/__tests__/spanLoggerMaterializerParity.test.ts +503 -0
- package/src/lib/codegen/evaluatorGenerator.ts +18 -13
- package/src/lib/codegen/fixedPositionWriterGenerator.ts +329 -245
- package/src/lib/codegen/spanLoggerClosureMaterializer.ts +598 -0
- package/src/lib/codegen/spanLoggerGenerator.ts +241 -177
- package/src/lib/convertToArrow.ts +598 -311
- package/src/lib/defineOpContext.ts +1 -1
- package/src/lib/enumMetadata.ts +121 -0
- package/src/lib/flushScheduler.ts +11 -5
- package/src/lib/library.ts +37 -595
- package/src/lib/logBinding.ts +21 -27
- package/src/lib/op.ts +75 -18
- package/src/lib/opContext/__tests__/retry.test.ts +27 -21
- package/src/lib/opContext/createOpGroup.ts +33 -31
- package/src/lib/opContext/defineOp.ts +88 -11
- package/src/lib/opContext/opGroupTypes.ts +2 -2
- package/src/lib/opContext/opTypes.ts +1 -1
- package/src/lib/opContext/spanContextTypes.ts +98 -17
- package/src/lib/opContext/types.ts +7 -3
- package/src/lib/physicalLayoutPlan.ts +598 -0
- package/src/lib/resolveMessage.ts +67 -0
- package/src/lib/result.ts +20 -33
- package/src/lib/runtimeHint.ts +98 -0
- package/src/lib/schema/__tests__/featureFlags.test.ts +2 -1
- package/src/lib/schema/builder.ts +1 -1
- package/src/lib/schema/types.ts +1 -1
- package/src/lib/span-buffer/aot/v1.ts +26 -0
- package/src/lib/spanBuffer.ts +658 -92
- package/src/lib/spanBufferStats.ts +1 -1
- package/src/lib/spanContext.ts +1350 -861
- package/src/lib/sqlite/sqlite-common.ts +20 -31
- package/src/lib/testing/__tests__/topology-traversal.test.ts +174 -0
- package/src/lib/testing/__tests__/vitest-harness.test.ts +2 -1
- package/src/lib/testing/bun-harness.ts +94 -43
- package/src/lib/testing/extractFacts.ts +64 -78
- package/src/lib/testing/facts.ts +1 -1
- package/src/lib/testing/queryable-span.ts +23 -30
- package/src/lib/testing/span-query.ts +16 -20
- package/src/lib/testing/stdio-replay.ts +25 -8
- package/src/lib/testing/vitest-harness.ts +1 -1
- package/src/lib/threadId.ts +6 -3
- package/src/lib/traceRoot.es.ts +77 -42
- package/src/lib/traceRoot.node.ts +75 -46
- package/src/lib/traceRoot.ts +41 -14
- package/src/lib/traceTopology.ts +279 -0
- package/src/lib/tracer.ts +109 -98
- package/src/lib/tracers/ArrayQueueTracer.ts +1 -1
- package/src/lib/tracers/StdioTracer.ts +15 -13
- package/src/lib/tracers/TestTracer.ts +6 -8
- package/src/lib/tracers/__tests__/ArrayQueueTracer.test.ts +15 -10
- package/src/lib/tracers/__tests__/TestTracer.test.ts +23 -13
- package/src/lib/types.ts +64 -33
- package/src/lib/vocabularyRegistry.ts +439 -0
- package/src/lib/wasm/WasmBufferStrategy.ts +56 -48
- package/src/lib/wasm/__tests__/WasmBufferStrategy.test.ts +215 -11
- package/src/lib/wasm/__tests__/allocatorFreeBlockClamp.test.ts +86 -0
- package/src/lib/wasm/__tests__/wasm-identity-view.test.ts +311 -0
- package/src/lib/wasm/__tests__/wasm-integration.test.ts +417 -44
- package/src/lib/wasm/__tests__/wasm-message-buffer-families.test.ts +588 -0
- package/src/lib/wasm/__tests__/wasmAllocator.test.ts +100 -668
- package/src/lib/wasm/__tests__/wasmSpanBuffer.test.ts +419 -63
- package/src/lib/wasm/__tests__/wasmTraceRoot.test.ts +24 -29
- package/src/lib/wasm/__tests__/wasmTracer.test.ts.disabled +2 -2
- package/src/lib/wasm/wasmAllocator.ts +131 -96
- package/src/lib/wasm/wasmPhysicalLayout.ts +309 -0
- package/src/lib/wasm/wasmSpanBuffer.ts +597 -341
- package/src/lib/wasm/wasmTraceRoot.ts +140 -78
- package/src/vocabulary/register/v1.ts +1 -0
- package/src/wasm.ts +19 -0
- package/src/lib/__tests__/remapped-buffer-view-integration.test.ts +0 -319
- package/src/lib/__tests__/remapped-buffer-view.test.ts +0 -635
- package/src/lib/wasm/allocator.zig +0 -948
|
@@ -3,12 +3,17 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import { afterEach, beforeAll, describe, expect, it } from 'bun:test';
|
|
6
|
+
import { getColumnValue, getRawTimestamp } from '../../__tests__/arrow-test-helpers.js';
|
|
7
|
+
import { convertToLeasedArrowTable } from '../../convertToArrow.js';
|
|
6
8
|
import { createOpMetadata } from '../../opContext/defineOp.js';
|
|
9
|
+
import { resolveMessage } from '../../resolveMessage.js';
|
|
7
10
|
import { S } from '../../schema/builder.js';
|
|
8
11
|
import { defineLogSchema } from '../../schema/defineLogSchema.js';
|
|
9
12
|
import type { TracerLifecycleHooks } from '../../traceRoot.js';
|
|
13
|
+
import { iterateSpanChildren, iterateSpanTree, NO_NODE } from '../../traceTopology.js';
|
|
10
14
|
import { WasmBufferStrategy } from '../WasmBufferStrategy.js';
|
|
11
15
|
import { createWasmAllocator } from '../wasmAllocator.js';
|
|
16
|
+
import { isWasmSpanBufferInstance, type WasmSpanBufferInstance } from '../wasmSpanBuffer.js';
|
|
12
17
|
import { createWasmTraceRoot } from '../wasmTraceRoot.js';
|
|
13
18
|
|
|
14
19
|
describe('WasmBufferStrategy', () => {
|
|
@@ -23,9 +28,16 @@ describe('WasmBufferStrategy', () => {
|
|
|
23
28
|
// Test metadata for buffer creation
|
|
24
29
|
const testMetadata = createOpMetadata('test-op', 'test-package', 'test.ts', 'abc123', 1);
|
|
25
30
|
|
|
31
|
+
function requireWasmSpanBuffer<T extends typeof testSchema>(value: unknown): WasmSpanBufferInstance<T> {
|
|
32
|
+
if (!isWasmSpanBufferInstance<T>(value)) {
|
|
33
|
+
throw new Error('expected WasmSpanBufferInstance');
|
|
34
|
+
}
|
|
35
|
+
return value;
|
|
36
|
+
}
|
|
37
|
+
|
|
26
38
|
// Mock tracer lifecycle hooks for WasmTraceRoot
|
|
27
39
|
let strategy: WasmBufferStrategy<typeof testSchema>;
|
|
28
|
-
let mockTracer: TracerLifecycleHooks
|
|
40
|
+
let mockTracer: TracerLifecycleHooks<typeof testSchema>;
|
|
29
41
|
|
|
30
42
|
beforeAll(async () => {
|
|
31
43
|
strategy = await WasmBufferStrategy.create<typeof testSchema>({
|
|
@@ -42,6 +54,7 @@ describe('WasmBufferStrategy', () => {
|
|
|
42
54
|
onSpanStart: () => {},
|
|
43
55
|
onSpanEnd: () => {},
|
|
44
56
|
onStatsWillResetFor: () => {},
|
|
57
|
+
getFlagEvaluatorForContext: () => undefined,
|
|
45
58
|
bufferStrategy: strategy,
|
|
46
59
|
};
|
|
47
60
|
});
|
|
@@ -81,10 +94,11 @@ describe('WasmBufferStrategy', () => {
|
|
|
81
94
|
const buffer = strategy.createSpanBuffer(testSchema, traceRoot, testMetadata);
|
|
82
95
|
// Caller must set span name via message() - simulating writeSpanStart behavior
|
|
83
96
|
buffer.message(0, 'test-span');
|
|
97
|
+
expect('message_nulls' in buffer).toBe(false);
|
|
84
98
|
|
|
85
99
|
expect(buffer).toBeDefined();
|
|
86
100
|
expect(buffer._capacity).toBe(64);
|
|
87
|
-
expect(buffer
|
|
101
|
+
expect(resolveMessage(buffer, 0)).toBe('test-span');
|
|
88
102
|
expect(String(buffer.trace_id)).toBe('test-trace-id');
|
|
89
103
|
});
|
|
90
104
|
|
|
@@ -121,14 +135,19 @@ describe('WasmBufferStrategy', () => {
|
|
|
121
135
|
const child = strategy.createChildSpanBuffer(parent, testMetadata, testMetadata);
|
|
122
136
|
// Caller must set span name via message() - simulating writeSpanStart behavior
|
|
123
137
|
child.message(0, 'child-span');
|
|
138
|
+
expect('message_nulls' in child).toBe(false);
|
|
124
139
|
|
|
125
140
|
expect(child).toBeDefined();
|
|
126
|
-
expect(child
|
|
141
|
+
expect(resolveMessage(child, 0)).toBe('child-span');
|
|
127
142
|
expect(child.trace_id).toBe(parent.trace_id);
|
|
128
143
|
expect(child.parent_span_id).toBe(parent.span_id);
|
|
129
|
-
// Note: parent._children is NOT populated by the strategy - SpanContext handles that.
|
|
130
|
-
// The strategy only sets up the parent-child relationship via child._parent.
|
|
131
144
|
expect(child._parent).toBe(parent);
|
|
145
|
+
|
|
146
|
+
const children = iterateSpanChildren(parent);
|
|
147
|
+
const registered = children.next();
|
|
148
|
+
if (registered.done) throw new Error('topology did not register the child span');
|
|
149
|
+
expect(registered.value).toBe(child);
|
|
150
|
+
expect(children.next().done).toBe(true);
|
|
132
151
|
});
|
|
133
152
|
|
|
134
153
|
it('inherits capacity from parent by default', async () => {
|
|
@@ -167,10 +186,50 @@ describe('WasmBufferStrategy', () => {
|
|
|
167
186
|
|
|
168
187
|
expect(overflow).toBeDefined();
|
|
169
188
|
expect(overflow._capacity).toBe(buffer._capacity);
|
|
170
|
-
// Note: Currently overflow allocates its own identity block with new span_id
|
|
171
|
-
// TODO: Overflow should share identity with parent buffer
|
|
172
189
|
expect(overflow.trace_id).toBe(buffer.trace_id);
|
|
190
|
+
expect(overflow.span_id).toBe(buffer.span_id);
|
|
191
|
+
expect(overflow.parent_span_id).toBe(buffer.parent_span_id);
|
|
192
|
+
expect(overflow._nodeIndex).toBe(buffer._nodeIndex);
|
|
193
|
+
expect(overflow._topologyGeneration).toBe(buffer._topologyGeneration);
|
|
194
|
+
expect(traceRoot._topology.count).toBe(1);
|
|
173
195
|
expect(buffer._overflow).toBe(overflow);
|
|
196
|
+
expect(Array.from(iterateSpanTree(buffer))).toEqual([buffer, overflow]);
|
|
197
|
+
});
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
describe('trace topology', () => {
|
|
201
|
+
it('registers many siblings in insertion order while growing every topology lane', async () => {
|
|
202
|
+
const traceRoot = createWasmTraceRoot(strategy.allocator, 'many-siblings-trace', mockTracer);
|
|
203
|
+
const root = strategy.createSpanBuffer(testSchema, traceRoot, testMetadata);
|
|
204
|
+
const siblingCount = 257;
|
|
205
|
+
const legacyChildLane = ['_', 'children'].join('');
|
|
206
|
+
expect(Reflect.has(root, legacyChildLane)).toBe(false);
|
|
207
|
+
|
|
208
|
+
for (let index = 0; index < siblingCount; index++) {
|
|
209
|
+
const child = strategy.createChildSpanBuffer(root, testMetadata, testMetadata);
|
|
210
|
+
child.message(0, `child-${index}`);
|
|
211
|
+
expect('message_nulls' in child).toBe(false);
|
|
212
|
+
expect(child._nodeIndex).toBe(index + 1);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
const topology = traceRoot._topology;
|
|
216
|
+
expect(topology.count).toBe(siblingCount + 1);
|
|
217
|
+
expect(topology.buffers.length).toBeGreaterThanOrEqual(siblingCount + 1);
|
|
218
|
+
expect(topology.firstChild.length).toBe(topology.buffers.length);
|
|
219
|
+
expect(topology.lastChild.length).toBe(topology.buffers.length);
|
|
220
|
+
expect(topology.nextSibling.length).toBe(topology.buffers.length);
|
|
221
|
+
expect(topology.firstChild[root._nodeIndex]).toBe(1);
|
|
222
|
+
expect(topology.lastChild[root._nodeIndex]).toBe(siblingCount);
|
|
223
|
+
expect(topology.nextSibling[siblingCount]).toBe(NO_NODE);
|
|
224
|
+
|
|
225
|
+
let observed = 0;
|
|
226
|
+
for (const child of iterateSpanChildren(root)) {
|
|
227
|
+
expect(child._nodeIndex).toBe(observed + 1);
|
|
228
|
+
expect(resolveMessage(child, 0)).toBe(`child-${observed}`);
|
|
229
|
+
expect(Reflect.has(child, legacyChildLane)).toBe(false);
|
|
230
|
+
observed++;
|
|
231
|
+
}
|
|
232
|
+
expect(observed).toBe(siblingCount);
|
|
174
233
|
});
|
|
175
234
|
});
|
|
176
235
|
|
|
@@ -218,6 +277,54 @@ describe('WasmBufferStrategy', () => {
|
|
|
218
277
|
// Should have freed both buffers
|
|
219
278
|
expect(statsAfter.freeCount).toBeGreaterThan(statsBefore.freeCount);
|
|
220
279
|
});
|
|
280
|
+
|
|
281
|
+
it('releases and resets chains deeper than recursive walkers can traverse', async () => {
|
|
282
|
+
const deepSchema = defineLogSchema({});
|
|
283
|
+
const deepStrategy = await WasmBufferStrategy.create<typeof deepSchema>({
|
|
284
|
+
capacity: 8,
|
|
285
|
+
initialPages: 16,
|
|
286
|
+
maxPages: 256,
|
|
287
|
+
});
|
|
288
|
+
const deepTracer: TracerLifecycleHooks<typeof deepSchema> = {
|
|
289
|
+
onTraceStart: () => {},
|
|
290
|
+
onTraceEnd: () => {},
|
|
291
|
+
onSpanStart: () => {},
|
|
292
|
+
onSpanEnd: () => {},
|
|
293
|
+
onStatsWillResetFor: () => {},
|
|
294
|
+
getFlagEvaluatorForContext: () => undefined,
|
|
295
|
+
bufferStrategy: deepStrategy,
|
|
296
|
+
};
|
|
297
|
+
const depth = 20_000;
|
|
298
|
+
const buildChain = (traceId: string) => {
|
|
299
|
+
const traceRoot = createWasmTraceRoot(deepStrategy.allocator, traceId, deepTracer);
|
|
300
|
+
const root = deepStrategy.createSpanBuffer(deepSchema, traceRoot, testMetadata);
|
|
301
|
+
let leaf = root;
|
|
302
|
+
for (let level = 0; level < depth; level++) {
|
|
303
|
+
leaf = deepStrategy.createChildSpanBuffer(leaf, testMetadata, testMetadata);
|
|
304
|
+
}
|
|
305
|
+
return { leaf, root, topology: traceRoot._topology };
|
|
306
|
+
};
|
|
307
|
+
|
|
308
|
+
const released = buildChain('deep-release-trace');
|
|
309
|
+
const releaseGeneration = released.topology.generation;
|
|
310
|
+
expect(released.topology.count).toBe(depth + 1);
|
|
311
|
+
deepStrategy.releaseBuffer(released.root);
|
|
312
|
+
expect(released.topology.count).toBe(0);
|
|
313
|
+
expect(released.topology.root).toBe(NO_NODE);
|
|
314
|
+
expect(released.topology.generation).toBe(releaseGeneration + 1);
|
|
315
|
+
expect(() => released.topology.assertLive(released.leaf)).toThrow(/stale/);
|
|
316
|
+
expect(() => deepStrategy.releaseBuffer(released.root)).toThrow(/stale/);
|
|
317
|
+
|
|
318
|
+
const reset = buildChain('deep-reset-trace');
|
|
319
|
+
const resetGeneration = reset.topology.generation;
|
|
320
|
+
expect(reset.topology.count).toBe(depth + 1);
|
|
321
|
+
deepStrategy.reset();
|
|
322
|
+
expect(reset.topology.count).toBe(0);
|
|
323
|
+
expect(reset.topology.root).toBe(NO_NODE);
|
|
324
|
+
expect(reset.topology.generation).toBe(resetGeneration + 1);
|
|
325
|
+
expect(() => reset.topology.assertLive(reset.leaf)).toThrow(/stale/);
|
|
326
|
+
expect(() => iterateSpanChildren(reset.root).next()).toThrow(/stale/);
|
|
327
|
+
});
|
|
221
328
|
});
|
|
222
329
|
|
|
223
330
|
describe('getStats()', () => {
|
|
@@ -237,11 +344,11 @@ describe('WasmBufferStrategy', () => {
|
|
|
237
344
|
|
|
238
345
|
describe('reset()', () => {
|
|
239
346
|
it('resets allocator state', async () => {
|
|
240
|
-
const
|
|
347
|
+
const firstTraceRoot = createWasmTraceRoot(strategy.allocator, 'first-test-trace-id', mockTracer);
|
|
348
|
+
const secondTraceRoot = createWasmTraceRoot(strategy.allocator, 'second-test-trace-id', mockTracer);
|
|
241
349
|
|
|
242
|
-
|
|
243
|
-
strategy.createSpanBuffer(testSchema,
|
|
244
|
-
strategy.createSpanBuffer(testSchema, traceRoot, testMetadata);
|
|
350
|
+
strategy.createSpanBuffer(testSchema, firstTraceRoot, testMetadata);
|
|
351
|
+
strategy.createSpanBuffer(testSchema, secondTraceRoot, testMetadata);
|
|
245
352
|
|
|
246
353
|
const statsBeforeReset = strategy.getStats();
|
|
247
354
|
expect(statsBeforeReset.allocCount).toBeGreaterThan(0);
|
|
@@ -252,5 +359,102 @@ describe('WasmBufferStrategy', () => {
|
|
|
252
359
|
expect(statsAfterReset.allocCount).toBe(0);
|
|
253
360
|
expect(statsAfterReset.freeCount).toBe(0);
|
|
254
361
|
});
|
|
362
|
+
|
|
363
|
+
it('invalidates root, child, and overflow generations before offsets are reused', async () => {
|
|
364
|
+
const traceRoot = createWasmTraceRoot(strategy.allocator, 'test-trace-id', mockTracer);
|
|
365
|
+
const root = strategy.createSpanBuffer(testSchema, traceRoot, testMetadata);
|
|
366
|
+
const child = strategy.createChildSpanBuffer(root, testMetadata, testMetadata);
|
|
367
|
+
const overflow = strategy.createOverflowBuffer(root);
|
|
368
|
+
root.timestamp[0] = 11n;
|
|
369
|
+
child.timestamp[0] = 22n;
|
|
370
|
+
overflow.timestamp[0] = 33n;
|
|
371
|
+
const topologyGeneration = traceRoot._topology.generation;
|
|
372
|
+
|
|
373
|
+
strategy.reset();
|
|
374
|
+
|
|
375
|
+
expect(() => root.timestamp).toThrow(/generation .* released/);
|
|
376
|
+
expect(() => child.timestamp).toThrow(/generation .* released/);
|
|
377
|
+
expect(() => overflow.timestamp).toThrow(/generation .* released/);
|
|
378
|
+
expect(() => traceRoot._topology.assertLive(root)).toThrow(/stale/);
|
|
379
|
+
expect(() => traceRoot._topology.assertLive(child)).toThrow(/stale/);
|
|
380
|
+
expect(() => traceRoot._topology.assertLive(overflow)).toThrow(/stale/);
|
|
381
|
+
expect(() => iterateSpanChildren(root).next()).toThrow(/stale/);
|
|
382
|
+
expect(traceRoot._topology.generation).toBe(topologyGeneration + 1);
|
|
383
|
+
expect(traceRoot._topology.count).toBe(0);
|
|
384
|
+
expect(traceRoot._topology.root).toBe(NO_NODE);
|
|
385
|
+
expect(strategy.getStats()).toEqual({ allocCount: 0, freeCount: 0, bumpPtr: 192, capacity: 64 });
|
|
386
|
+
|
|
387
|
+
expect(() => strategy.releaseBuffer(root)).toThrow(/stale/);
|
|
388
|
+
expect(strategy.getStats()).toEqual({ allocCount: 0, freeCount: 0, bumpPtr: 192, capacity: 64 });
|
|
389
|
+
});
|
|
390
|
+
});
|
|
391
|
+
|
|
392
|
+
describe('leased Arrow conversion', () => {
|
|
393
|
+
it('survives a WASM memory epoch change, releases safely, and reuses freed slabs', async () => {
|
|
394
|
+
const leasedStrategy = await WasmBufferStrategy.create<typeof testSchema>({
|
|
395
|
+
capacity: 8,
|
|
396
|
+
initialPages: 1,
|
|
397
|
+
maxPages: 18,
|
|
398
|
+
});
|
|
399
|
+
const leasedTracer: TracerLifecycleHooks<typeof testSchema> = {
|
|
400
|
+
onTraceStart: () => {},
|
|
401
|
+
onTraceEnd: () => {},
|
|
402
|
+
onSpanStart: () => {},
|
|
403
|
+
onSpanEnd: () => {},
|
|
404
|
+
onStatsWillResetFor: () => {},
|
|
405
|
+
getFlagEvaluatorForContext: () => undefined,
|
|
406
|
+
bufferStrategy: leasedStrategy,
|
|
407
|
+
};
|
|
408
|
+
const traceRoot = createWasmTraceRoot(leasedStrategy.allocator, 'leased-wasm', leasedTracer);
|
|
409
|
+
const root = requireWasmSpanBuffer(leasedStrategy.createSpanBuffer(testSchema, traceRoot, testMetadata, 8));
|
|
410
|
+
root.timestamp[0] = 9_001n;
|
|
411
|
+
{
|
|
412
|
+
const entryTypes = root.entry_type;
|
|
413
|
+
if (entryTypes === undefined) throw new Error('Expected split entry-type lane');
|
|
414
|
+
entryTypes[0] = 8;
|
|
415
|
+
}
|
|
416
|
+
root.message(0, 'leased-wasm-row');
|
|
417
|
+
expect('message_nulls' in root).toBe(false);
|
|
418
|
+
root.latency(0, 17.5);
|
|
419
|
+
root.success(0, true);
|
|
420
|
+
root.operation(0, 1);
|
|
421
|
+
root._writeIndex = 1;
|
|
422
|
+
|
|
423
|
+
const f64Pointer = root._familyPtrs.f64;
|
|
424
|
+
const topologyGeneration = traceRoot._topology.generation;
|
|
425
|
+
const memoryVersion = leasedStrategy.allocator.memoryVersion;
|
|
426
|
+
const memoryBuffer = leasedStrategy.allocator.memory.buffer;
|
|
427
|
+
const lease = convertToLeasedArrowTable(root);
|
|
428
|
+
expect(lease.released).toBe(false);
|
|
429
|
+
expect(getColumnValue(lease.table, 'latency', 0)).toBe(17.5);
|
|
430
|
+
expect(getColumnValue(lease.table, 'success', 0)).toBe(true);
|
|
431
|
+
expect(getColumnValue(lease.table, 'operation', 0)).toBe('READ');
|
|
432
|
+
|
|
433
|
+
const bytesToGrow = memoryBuffer.byteLength - leasedStrategy.getStats().bumpPtr + 8;
|
|
434
|
+
const growth = leasedStrategy.allocator.allocExact(bytesToGrow, 8);
|
|
435
|
+
expect(growth).toBeGreaterThan(0);
|
|
436
|
+
expect(leasedStrategy.allocator.memory.buffer).not.toBe(memoryBuffer);
|
|
437
|
+
expect(leasedStrategy.allocator.memoryVersion).toBeGreaterThan(memoryVersion);
|
|
438
|
+
expect(getRawTimestamp(lease.table, 0)).toBe(9_001n);
|
|
439
|
+
expect(getColumnValue(lease.table, 'latency', 0)).toBe(17.5);
|
|
440
|
+
expect(getColumnValue(lease.table, 'message', 0)).toBe('leased-wasm-row');
|
|
441
|
+
expect(traceRoot._topology.generation).toBe(topologyGeneration);
|
|
442
|
+
|
|
443
|
+
leasedStrategy.releaseBuffer(root);
|
|
444
|
+
expect(traceRoot._topology.generation).toBe(topologyGeneration);
|
|
445
|
+
expect(() => traceRoot._topology.assertLive(root)).toThrow(/stale/);
|
|
446
|
+
expect(root.timestamp[0]).toBe(9_001n);
|
|
447
|
+
expect(getColumnValue(lease.table, 'latency', 0)).toBe(17.5);
|
|
448
|
+
lease.release();
|
|
449
|
+
expect(lease.released).toBe(true);
|
|
450
|
+
expect(traceRoot._topology.generation).toBe(topologyGeneration + 1);
|
|
451
|
+
expect(() => root.timestamp).toThrow(/generation .* released/);
|
|
452
|
+
expect(() => lease.release()).not.toThrow();
|
|
453
|
+
|
|
454
|
+
const nextTraceRoot = createWasmTraceRoot(leasedStrategy.allocator, 'leased-wasm-next', leasedTracer);
|
|
455
|
+
const next = requireWasmSpanBuffer(leasedStrategy.createSpanBuffer(testSchema, nextTraceRoot, testMetadata, 8));
|
|
456
|
+
expect(next._familyPtrs.f64).toBe(f64Pointer);
|
|
457
|
+
leasedStrategy.releaseBuffer(next);
|
|
458
|
+
});
|
|
255
459
|
});
|
|
256
460
|
});
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { beforeEach, describe, expect, it } from 'bun:test';
|
|
2
|
+
import { createWasmAllocator, type WasmAllocator } from '../wasmAllocator.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Exact slabs may be smaller than the allocator's intrusive free-list metadata.
|
|
6
|
+
* Releasing such a slab must reserve bookkeeping storage internally rather than
|
|
7
|
+
* overwrite an adjacent live slab.
|
|
8
|
+
*/
|
|
9
|
+
describe('sub-metadata exact slab safety', () => {
|
|
10
|
+
let allocator: WasmAllocator;
|
|
11
|
+
|
|
12
|
+
beforeEach(async () => {
|
|
13
|
+
allocator = await createWasmAllocator({ capacity: 64 });
|
|
14
|
+
allocator.reset();
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
function churnAndAssertNoCorruption(byteLength: 9 | 18) {
|
|
18
|
+
const batch = 8;
|
|
19
|
+
const rounds = 25;
|
|
20
|
+
let nextMarker = 1;
|
|
21
|
+
const live = new Map<number, number>();
|
|
22
|
+
|
|
23
|
+
function allocAndMark(): number {
|
|
24
|
+
const offset = allocator.allocExact(byteLength, 1);
|
|
25
|
+
expect(offset).toBeGreaterThan(0);
|
|
26
|
+
const marker = nextMarker++ & 0xff;
|
|
27
|
+
allocator.u8[offset + byteLength - 1] = marker;
|
|
28
|
+
live.set(offset, marker);
|
|
29
|
+
return offset;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function assertAllLiveIntact(context: string) {
|
|
33
|
+
for (const [offset, marker] of live) {
|
|
34
|
+
expect(allocator.u8[offset + byteLength - 1], `exact slab at ${offset} corrupted (${context})`).toBe(marker);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
for (let i = 0; i < batch; i++) allocAndMark();
|
|
39
|
+
assertAllLiveIntact('after initial batch');
|
|
40
|
+
|
|
41
|
+
for (let round = 0; round < rounds; round++) {
|
|
42
|
+
const offsets = [...live.keys()];
|
|
43
|
+
for (let i = 0; i < offsets.length; i += 2) {
|
|
44
|
+
allocator.freeExact(offsets[i], byteLength, 1);
|
|
45
|
+
live.delete(offsets[i]);
|
|
46
|
+
}
|
|
47
|
+
assertAllLiveIntact(`round ${round} after frees`);
|
|
48
|
+
while (live.size < batch) allocAndMark();
|
|
49
|
+
assertAllLiveIntact(`round ${round} after refill`);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
it('9-byte exact alloc/free/realloc churn never corrupts a live neighbor', () => {
|
|
54
|
+
churnAndAssertNoCorruption(9);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it('18-byte exact alloc/free/realloc churn never corrupts a live neighbor', () => {
|
|
58
|
+
churnAndAssertNoCorruption(18);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it('never returns an address that still has a live exact owner', () => {
|
|
62
|
+
const byteLength = 9;
|
|
63
|
+
const live = new Set<number>();
|
|
64
|
+
let allocs = 0;
|
|
65
|
+
let frees = 0;
|
|
66
|
+
|
|
67
|
+
for (let i = 0; i < 300; i++) {
|
|
68
|
+
const shouldFree = live.size > 0 && (i % 3 === 0 || live.size > 40);
|
|
69
|
+
if (shouldFree) {
|
|
70
|
+
const victim = [...live][i % live.size];
|
|
71
|
+
allocator.freeExact(victim, byteLength, 1);
|
|
72
|
+
live.delete(victim);
|
|
73
|
+
frees++;
|
|
74
|
+
} else {
|
|
75
|
+
const offset = allocator.allocExact(byteLength, 1);
|
|
76
|
+
expect(offset).toBeGreaterThan(0);
|
|
77
|
+
expect(live.has(offset), `allocator returned live exact offset ${offset}`).toBe(false);
|
|
78
|
+
live.add(offset);
|
|
79
|
+
allocs++;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
expect(allocs).toBeGreaterThan(0);
|
|
84
|
+
expect(frees).toBeGreaterThan(0);
|
|
85
|
+
});
|
|
86
|
+
});
|