@smoothbricks/lmao 0.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 (447) hide show
  1. package/README.md +269 -0
  2. package/dist/allocator.wasm +0 -0
  3. package/dist/bun/preload.d.ts +11 -0
  4. package/dist/bun/preload.d.ts.map +1 -0
  5. package/dist/bun/preload.js +10 -0
  6. package/dist/bun/trace-preload.d.ts +8 -0
  7. package/dist/bun/trace-preload.d.ts.map +1 -0
  8. package/dist/bun/trace-preload.js +12 -0
  9. package/dist/es.d.ts +8 -0
  10. package/dist/es.d.ts.map +1 -0
  11. package/dist/es.js +9 -0
  12. package/dist/index.d.ts +41 -0
  13. package/dist/index.d.ts.map +1 -0
  14. package/dist/index.js +84 -0
  15. package/dist/lib/JsBufferStrategy.d.ts +49 -0
  16. package/dist/lib/JsBufferStrategy.d.ts.map +1 -0
  17. package/dist/lib/JsBufferStrategy.js +60 -0
  18. package/dist/lib/archive/chunkCompaction.d.ts +15 -0
  19. package/dist/lib/archive/chunkCompaction.d.ts.map +1 -0
  20. package/dist/lib/archive/chunkCompaction.js +24 -0
  21. package/dist/lib/archive/chunkEnvelope.d.ts +21 -0
  22. package/dist/lib/archive/chunkEnvelope.d.ts.map +1 -0
  23. package/dist/lib/archive/chunkEnvelope.js +55 -0
  24. package/dist/lib/archive/chunkRouting.d.ts +10 -0
  25. package/dist/lib/archive/chunkRouting.d.ts.map +1 -0
  26. package/dist/lib/archive/chunkRouting.js +47 -0
  27. package/dist/lib/archive/chunkStats.d.ts +12 -0
  28. package/dist/lib/archive/chunkStats.d.ts.map +1 -0
  29. package/dist/lib/archive/chunkStats.js +10 -0
  30. package/dist/lib/archive/index.d.ts +5 -0
  31. package/dist/lib/archive/index.d.ts.map +1 -0
  32. package/dist/lib/archive/index.js +4 -0
  33. package/dist/lib/arrow/capacityStats.d.ts +9 -0
  34. package/dist/lib/arrow/capacityStats.d.ts.map +1 -0
  35. package/dist/lib/arrow/capacityStats.js +231 -0
  36. package/dist/lib/arrow/dictionaries.d.ts +27 -0
  37. package/dist/lib/arrow/dictionaries.d.ts.map +1 -0
  38. package/dist/lib/arrow/dictionaries.js +135 -0
  39. package/dist/lib/arrow/flechette.d.ts +40 -0
  40. package/dist/lib/arrow/flechette.d.ts.map +1 -0
  41. package/dist/lib/arrow/flechette.js +67 -0
  42. package/dist/lib/arrow/utils.d.ts +38 -0
  43. package/dist/lib/arrow/utils.d.ts.map +1 -0
  44. package/dist/lib/arrow/utils.js +112 -0
  45. package/dist/lib/buffer/Nanoseconds.d.ts +109 -0
  46. package/dist/lib/buffer/Nanoseconds.d.ts.map +1 -0
  47. package/dist/lib/buffer/Nanoseconds.js +86 -0
  48. package/dist/lib/bufferStrategy.d.ts +95 -0
  49. package/dist/lib/bufferStrategy.d.ts.map +1 -0
  50. package/dist/lib/bufferStrategy.js +1 -0
  51. package/dist/lib/capacityTuning.d.ts +50 -0
  52. package/dist/lib/capacityTuning.d.ts.map +1 -0
  53. package/dist/lib/capacityTuning.js +65 -0
  54. package/dist/lib/codegen/evaluatorGenerator.d.ts +35 -0
  55. package/dist/lib/codegen/evaluatorGenerator.d.ts.map +1 -0
  56. package/dist/lib/codegen/evaluatorGenerator.js +199 -0
  57. package/dist/lib/codegen/fixedPositionWriterGenerator.d.ts +139 -0
  58. package/dist/lib/codegen/fixedPositionWriterGenerator.d.ts.map +1 -0
  59. package/dist/lib/codegen/fixedPositionWriterGenerator.js +289 -0
  60. package/dist/lib/codegen/spanLoggerGenerator.d.ts +115 -0
  61. package/dist/lib/codegen/spanLoggerGenerator.d.ts.map +1 -0
  62. package/dist/lib/codegen/spanLoggerGenerator.js +575 -0
  63. package/dist/lib/convertToArrow.d.ts +40 -0
  64. package/dist/lib/convertToArrow.d.ts.map +1 -0
  65. package/dist/lib/convertToArrow.js +1467 -0
  66. package/dist/lib/defineOpContext.d.ts +96 -0
  67. package/dist/lib/defineOpContext.d.ts.map +1 -0
  68. package/dist/lib/defineOpContext.js +227 -0
  69. package/dist/lib/errors/Blocked.d.ts +113 -0
  70. package/dist/lib/errors/Blocked.d.ts.map +1 -0
  71. package/dist/lib/errors/Blocked.js +68 -0
  72. package/dist/lib/errors/CodeError.d.ts +101 -0
  73. package/dist/lib/errors/CodeError.d.ts.map +1 -0
  74. package/dist/lib/errors/CodeError.js +42 -0
  75. package/dist/lib/errors/RetriesExhausted.d.ts +67 -0
  76. package/dist/lib/errors/RetriesExhausted.d.ts.map +1 -0
  77. package/dist/lib/errors/RetriesExhausted.js +31 -0
  78. package/dist/lib/errors/Transient.d.ts +115 -0
  79. package/dist/lib/errors/Transient.d.ts.map +1 -0
  80. package/dist/lib/errors/Transient.js +54 -0
  81. package/dist/lib/errors/index.d.ts +14 -0
  82. package/dist/lib/errors/index.d.ts.map +1 -0
  83. package/dist/lib/errors/index.js +16 -0
  84. package/dist/lib/errors/retry-policy.d.ts +60 -0
  85. package/dist/lib/errors/retry-policy.d.ts.map +1 -0
  86. package/dist/lib/errors/retry-policy.js +54 -0
  87. package/dist/lib/flushScheduler.d.ts +162 -0
  88. package/dist/lib/flushScheduler.d.ts.map +1 -0
  89. package/dist/lib/flushScheduler.js +388 -0
  90. package/dist/lib/library.d.ts +149 -0
  91. package/dist/lib/library.d.ts.map +1 -0
  92. package/dist/lib/library.js +588 -0
  93. package/dist/lib/logApi.d.ts +61 -0
  94. package/dist/lib/logApi.d.ts.map +1 -0
  95. package/dist/lib/logApi.js +12 -0
  96. package/dist/lib/logBinding.d.ts +63 -0
  97. package/dist/lib/logBinding.d.ts.map +1 -0
  98. package/dist/lib/logBinding.js +1 -0
  99. package/dist/lib/op.d.ts +105 -0
  100. package/dist/lib/op.d.ts.map +1 -0
  101. package/dist/lib/op.js +59 -0
  102. package/dist/lib/opContext/contextTypes.d.ts +88 -0
  103. package/dist/lib/opContext/contextTypes.d.ts.map +1 -0
  104. package/dist/lib/opContext/contextTypes.js +34 -0
  105. package/dist/lib/opContext/createOpGroup.d.ts +57 -0
  106. package/dist/lib/opContext/createOpGroup.d.ts.map +1 -0
  107. package/dist/lib/opContext/createOpGroup.js +341 -0
  108. package/dist/lib/opContext/defineOp.d.ts +83 -0
  109. package/dist/lib/opContext/defineOp.d.ts.map +1 -0
  110. package/dist/lib/opContext/defineOp.js +197 -0
  111. package/dist/lib/opContext/featureFlagTypes.d.ts +58 -0
  112. package/dist/lib/opContext/featureFlagTypes.d.ts.map +1 -0
  113. package/dist/lib/opContext/featureFlagTypes.js +1 -0
  114. package/dist/lib/opContext/index.d.ts +13 -0
  115. package/dist/lib/opContext/index.d.ts.map +1 -0
  116. package/dist/lib/opContext/index.js +15 -0
  117. package/dist/lib/opContext/opGroupTypes.d.ts +250 -0
  118. package/dist/lib/opContext/opGroupTypes.d.ts.map +1 -0
  119. package/dist/lib/opContext/opGroupTypes.js +31 -0
  120. package/dist/lib/opContext/opTypes.d.ts +48 -0
  121. package/dist/lib/opContext/opTypes.d.ts.map +1 -0
  122. package/dist/lib/opContext/opTypes.js +7 -0
  123. package/dist/lib/opContext/spanContextTypes.d.ts +347 -0
  124. package/dist/lib/opContext/spanContextTypes.d.ts.map +1 -0
  125. package/dist/lib/opContext/spanContextTypes.js +1 -0
  126. package/dist/lib/opContext/types.d.ts +297 -0
  127. package/dist/lib/opContext/types.d.ts.map +1 -0
  128. package/dist/lib/opContext/types.js +16 -0
  129. package/dist/lib/result.d.ts +308 -0
  130. package/dist/lib/result.d.ts.map +1 -0
  131. package/dist/lib/result.js +359 -0
  132. package/dist/lib/schema/LogSchema.d.ts +62 -0
  133. package/dist/lib/schema/LogSchema.d.ts.map +1 -0
  134. package/dist/lib/schema/LogSchema.js +134 -0
  135. package/dist/lib/schema/builder.d.ts +12 -0
  136. package/dist/lib/schema/builder.d.ts.map +1 -0
  137. package/dist/lib/schema/builder.js +169 -0
  138. package/dist/lib/schema/defineFeatureFlags.d.ts +60 -0
  139. package/dist/lib/schema/defineFeatureFlags.d.ts.map +1 -0
  140. package/dist/lib/schema/defineFeatureFlags.js +29 -0
  141. package/dist/lib/schema/defineLogSchema.d.ts +87 -0
  142. package/dist/lib/schema/defineLogSchema.d.ts.map +1 -0
  143. package/dist/lib/schema/defineLogSchema.js +171 -0
  144. package/dist/lib/schema/evaluator.d.ts +267 -0
  145. package/dist/lib/schema/evaluator.d.ts.map +1 -0
  146. package/dist/lib/schema/evaluator.js +169 -0
  147. package/dist/lib/schema/extend.d.ts +14 -0
  148. package/dist/lib/schema/extend.d.ts.map +1 -0
  149. package/dist/lib/schema/extend.js +51 -0
  150. package/dist/lib/schema/systemSchema.d.ts +112 -0
  151. package/dist/lib/schema/systemSchema.d.ts.map +1 -0
  152. package/dist/lib/schema/systemSchema.js +260 -0
  153. package/dist/lib/schema/typeGuards.d.ts +52 -0
  154. package/dist/lib/schema/typeGuards.d.ts.map +1 -0
  155. package/dist/lib/schema/typeGuards.js +127 -0
  156. package/dist/lib/schema/types.d.ts +156 -0
  157. package/dist/lib/schema/types.d.ts.map +1 -0
  158. package/dist/lib/schema/types.js +4 -0
  159. package/dist/lib/spanBuffer.d.ts +133 -0
  160. package/dist/lib/spanBuffer.d.ts.map +1 -0
  161. package/dist/lib/spanBuffer.js +442 -0
  162. package/dist/lib/spanBufferHelpers.d.ts +53 -0
  163. package/dist/lib/spanBufferHelpers.d.ts.map +1 -0
  164. package/dist/lib/spanBufferHelpers.js +65 -0
  165. package/dist/lib/spanBufferStats.d.ts +38 -0
  166. package/dist/lib/spanBufferStats.d.ts.map +1 -0
  167. package/dist/lib/spanBufferStats.js +1 -0
  168. package/dist/lib/spanContext.d.ts +141 -0
  169. package/dist/lib/spanContext.d.ts.map +1 -0
  170. package/dist/lib/spanContext.js +763 -0
  171. package/dist/lib/sqlite/index.d.ts +14 -0
  172. package/dist/lib/sqlite/index.d.ts.map +1 -0
  173. package/dist/lib/sqlite/index.js +12 -0
  174. package/dist/lib/sqlite/sqlite-async-writer.d.ts +24 -0
  175. package/dist/lib/sqlite/sqlite-async-writer.d.ts.map +1 -0
  176. package/dist/lib/sqlite/sqlite-async-writer.js +65 -0
  177. package/dist/lib/sqlite/sqlite-common.d.ts +37 -0
  178. package/dist/lib/sqlite/sqlite-common.d.ts.map +1 -0
  179. package/dist/lib/sqlite/sqlite-common.js +207 -0
  180. package/dist/lib/sqlite/sqlite-d1.d.ts +25 -0
  181. package/dist/lib/sqlite/sqlite-d1.d.ts.map +1 -0
  182. package/dist/lib/sqlite/sqlite-d1.js +67 -0
  183. package/dist/lib/sqlite/sqlite-db.d.ts +29 -0
  184. package/dist/lib/sqlite/sqlite-db.d.ts.map +1 -0
  185. package/dist/lib/sqlite/sqlite-db.js +1 -0
  186. package/dist/lib/sqlite/sqlite-node.d.ts +16 -0
  187. package/dist/lib/sqlite/sqlite-node.d.ts.map +1 -0
  188. package/dist/lib/sqlite/sqlite-node.js +68 -0
  189. package/dist/lib/sqlite/sqlite-writer.d.ts +39 -0
  190. package/dist/lib/sqlite/sqlite-writer.d.ts.map +1 -0
  191. package/dist/lib/sqlite/sqlite-writer.js +78 -0
  192. package/dist/lib/testing/bun-harness.d.ts +150 -0
  193. package/dist/lib/testing/bun-harness.d.ts.map +1 -0
  194. package/dist/lib/testing/bun-harness.js +729 -0
  195. package/dist/lib/testing/extractFacts.d.ts +73 -0
  196. package/dist/lib/testing/extractFacts.d.ts.map +1 -0
  197. package/dist/lib/testing/extractFacts.js +237 -0
  198. package/dist/lib/testing/facts.d.ts +235 -0
  199. package/dist/lib/testing/facts.d.ts.map +1 -0
  200. package/dist/lib/testing/facts.js +209 -0
  201. package/dist/lib/testing/index.d.ts +58 -0
  202. package/dist/lib/testing/index.d.ts.map +1 -0
  203. package/dist/lib/testing/index.js +74 -0
  204. package/dist/lib/testing/queryable-span.d.ts +39 -0
  205. package/dist/lib/testing/queryable-span.d.ts.map +1 -0
  206. package/dist/lib/testing/queryable-span.js +58 -0
  207. package/dist/lib/testing/span-query.d.ts +21 -0
  208. package/dist/lib/testing/span-query.d.ts.map +1 -0
  209. package/dist/lib/testing/span-query.js +47 -0
  210. package/dist/lib/testing/stdio-replay.d.ts +4 -0
  211. package/dist/lib/testing/stdio-replay.d.ts.map +1 -0
  212. package/dist/lib/testing/stdio-replay.js +42 -0
  213. package/dist/lib/testing/trace-query.d.ts +59 -0
  214. package/dist/lib/testing/trace-query.d.ts.map +1 -0
  215. package/dist/lib/testing/trace-query.js +462 -0
  216. package/dist/lib/testing/vitest-harness.d.ts +135 -0
  217. package/dist/lib/testing/vitest-harness.d.ts.map +1 -0
  218. package/dist/lib/testing/vitest-harness.js +486 -0
  219. package/dist/lib/threadId.d.ts +58 -0
  220. package/dist/lib/threadId.d.ts.map +1 -0
  221. package/dist/lib/threadId.js +123 -0
  222. package/dist/lib/traceContext.d.ts +116 -0
  223. package/dist/lib/traceContext.d.ts.map +1 -0
  224. package/dist/lib/traceContext.js +37 -0
  225. package/dist/lib/traceId.d.ts +78 -0
  226. package/dist/lib/traceId.d.ts.map +1 -0
  227. package/dist/lib/traceId.js +87 -0
  228. package/dist/lib/traceRoot.d.ts +133 -0
  229. package/dist/lib/traceRoot.d.ts.map +1 -0
  230. package/dist/lib/traceRoot.es.d.ts +75 -0
  231. package/dist/lib/traceRoot.es.d.ts.map +1 -0
  232. package/dist/lib/traceRoot.es.js +129 -0
  233. package/dist/lib/traceRoot.js +19 -0
  234. package/dist/lib/traceRoot.node.d.ts +77 -0
  235. package/dist/lib/traceRoot.node.d.ts.map +1 -0
  236. package/dist/lib/traceRoot.node.js +133 -0
  237. package/dist/lib/traceRoot.universal.d.ts +3 -0
  238. package/dist/lib/traceRoot.universal.d.ts.map +1 -0
  239. package/dist/lib/traceRoot.universal.js +17 -0
  240. package/dist/lib/tracer.d.ts +296 -0
  241. package/dist/lib/tracer.d.ts.map +1 -0
  242. package/dist/lib/tracer.js +346 -0
  243. package/dist/lib/tracers/ArrayQueueTracer.d.ts +56 -0
  244. package/dist/lib/tracers/ArrayQueueTracer.d.ts.map +1 -0
  245. package/dist/lib/tracers/ArrayQueueTracer.js +67 -0
  246. package/dist/lib/tracers/CompositeTracer.d.ts +24 -0
  247. package/dist/lib/tracers/CompositeTracer.d.ts.map +1 -0
  248. package/dist/lib/tracers/CompositeTracer.js +57 -0
  249. package/dist/lib/tracers/NoOpTracer.d.ts +58 -0
  250. package/dist/lib/tracers/NoOpTracer.d.ts.map +1 -0
  251. package/dist/lib/tracers/NoOpTracer.js +41 -0
  252. package/dist/lib/tracers/SQLiteTracer.d.ts +42 -0
  253. package/dist/lib/tracers/SQLiteTracer.d.ts.map +1 -0
  254. package/dist/lib/tracers/SQLiteTracer.js +84 -0
  255. package/dist/lib/tracers/StdioTracer.d.ts +83 -0
  256. package/dist/lib/tracers/StdioTracer.d.ts.map +1 -0
  257. package/dist/lib/tracers/StdioTracer.js +270 -0
  258. package/dist/lib/tracers/TestTracer.d.ts +95 -0
  259. package/dist/lib/tracers/TestTracer.d.ts.map +1 -0
  260. package/dist/lib/tracers/TestTracer.js +87 -0
  261. package/dist/lib/tracers/index.d.ts +12 -0
  262. package/dist/lib/tracers/index.d.ts.map +1 -0
  263. package/dist/lib/tracers/index.js +11 -0
  264. package/dist/lib/types.d.ts +366 -0
  265. package/dist/lib/types.d.ts.map +1 -0
  266. package/dist/lib/types.js +1 -0
  267. package/dist/lib/utf8Cache.d.ts +111 -0
  268. package/dist/lib/utf8Cache.d.ts.map +1 -0
  269. package/dist/lib/utf8Cache.js +177 -0
  270. package/dist/lib/wasm/WasmBufferStrategy.d.ts +88 -0
  271. package/dist/lib/wasm/WasmBufferStrategy.d.ts.map +1 -0
  272. package/dist/lib/wasm/WasmBufferStrategy.js +138 -0
  273. package/dist/lib/wasm/wasmAllocator.d.ts +109 -0
  274. package/dist/lib/wasm/wasmAllocator.d.ts.map +1 -0
  275. package/dist/lib/wasm/wasmAllocator.js +227 -0
  276. package/dist/lib/wasm/wasmSpanBuffer.d.ts +123 -0
  277. package/dist/lib/wasm/wasmSpanBuffer.d.ts.map +1 -0
  278. package/dist/lib/wasm/wasmSpanBuffer.js +772 -0
  279. package/dist/lib/wasm/wasmTraceRoot.d.ts +167 -0
  280. package/dist/lib/wasm/wasmTraceRoot.d.ts.map +1 -0
  281. package/dist/lib/wasm/wasmTraceRoot.js +264 -0
  282. package/dist/node.d.ts +7 -0
  283. package/dist/node.d.ts.map +1 -0
  284. package/dist/node.js +8 -0
  285. package/dist/testing.d.ts +18 -0
  286. package/dist/testing.d.ts.map +1 -0
  287. package/dist/testing.js +17 -0
  288. package/package.json +193 -0
  289. package/src/bun/preload.ts +11 -0
  290. package/src/bun/trace-preload.ts +14 -0
  291. package/src/es.ts +11 -0
  292. package/src/index.ts +194 -0
  293. package/src/lib/JsBufferStrategy.ts +102 -0
  294. package/src/lib/__tests__/arrow-builder-integration/arrow-conversion.test.ts +485 -0
  295. package/src/lib/__tests__/arrow-builder-integration/binary-arrow-conversion.test.ts +390 -0
  296. package/src/lib/__tests__/arrow-builder-integration/binary-comparison.test.ts +647 -0
  297. package/src/lib/__tests__/arrow-builder-integration/binary-format-compliance.test.ts +292 -0
  298. package/src/lib/__tests__/arrow-builder-integration/buffer-chaining.test.ts +354 -0
  299. package/src/lib/__tests__/arrow-builder-integration/foundation.test.ts +127 -0
  300. package/src/lib/__tests__/arrow-builder-integration/integration.test.ts +392 -0
  301. package/src/lib/__tests__/arrow-builder-integration/lazy-columns.test.ts +389 -0
  302. package/src/lib/__tests__/arrow-conversion-algorithms.test.ts +54 -0
  303. package/src/lib/__tests__/arrow-test-helpers.ts +71 -0
  304. package/src/lib/__tests__/binary-e2e.test.ts +203 -0
  305. package/src/lib/__tests__/buffer-overflow-op-api.test.ts +608 -0
  306. package/src/lib/__tests__/buffer-overflow.test.ts +612 -0
  307. package/src/lib/__tests__/capacity-tuning.test.ts +544 -0
  308. package/src/lib/__tests__/effective-schema.test.ts +439 -0
  309. package/src/lib/__tests__/flechette.test.ts +42 -0
  310. package/src/lib/__tests__/flushScheduler.test.ts +537 -0
  311. package/src/lib/__tests__/integration.test.ts +600 -0
  312. package/src/lib/__tests__/library.test.ts +934 -0
  313. package/src/lib/__tests__/nested-library-tasks.test.ts +849 -0
  314. package/src/lib/__tests__/op-context-binding.test.ts +135 -0
  315. package/src/lib/__tests__/op-metadata.test.ts +198 -0
  316. package/src/lib/__tests__/op-type-safety.test.ts +71 -0
  317. package/src/lib/__tests__/package-exports.test.ts +57 -0
  318. package/src/lib/__tests__/remapped-buffer-view-integration.test.ts +319 -0
  319. package/src/lib/__tests__/remapped-buffer-view.test.ts +635 -0
  320. package/src/lib/__tests__/scope-attributes.test.ts +348 -0
  321. package/src/lib/__tests__/span-lifecycle.test.ts +680 -0
  322. package/src/lib/__tests__/sync-async-trace.test.ts +435 -0
  323. package/src/lib/__tests__/test-helpers.ts +318 -0
  324. package/src/lib/__tests__/timestamp.test.ts +259 -0
  325. package/src/lib/__tests__/trace-archive-primitives.test.ts +98 -0
  326. package/src/lib/__tests__/traceContext-type-enforcement.test.ts +271 -0
  327. package/src/lib/__tests__/tracer.test.ts +211 -0
  328. package/src/lib/__tests__/type-narrowing.test.ts +137 -0
  329. package/src/lib/archive/chunkCompaction.ts +44 -0
  330. package/src/lib/archive/chunkEnvelope.ts +79 -0
  331. package/src/lib/archive/chunkRouting.ts +70 -0
  332. package/src/lib/archive/chunkStats.ts +25 -0
  333. package/src/lib/archive/index.ts +4 -0
  334. package/src/lib/arrow/capacityStats.ts +340 -0
  335. package/src/lib/arrow/dictionaries.ts +159 -0
  336. package/src/lib/arrow/flechette.ts +114 -0
  337. package/src/lib/arrow/utils.ts +126 -0
  338. package/src/lib/buffer/Nanoseconds.ts +131 -0
  339. package/src/lib/bufferStrategy.ts +106 -0
  340. package/src/lib/capacityTuning.ts +102 -0
  341. package/src/lib/codegen/__tests__/__snapshots__/evaluatorGenerator.test.ts.snap +160 -0
  342. package/src/lib/codegen/__tests__/__snapshots__/scopeGenerator.test.ts.snap +196 -0
  343. package/src/lib/codegen/__tests__/__snapshots__/spanLoggerGenerator.test.ts.snap +1965 -0
  344. package/src/lib/codegen/__tests__/evaluatorGenerator.test.ts +516 -0
  345. package/src/lib/codegen/__tests__/nullBitmap.test.ts +207 -0
  346. package/src/lib/codegen/__tests__/spanLoggerGenerator.test.ts +237 -0
  347. package/src/lib/codegen/evaluatorGenerator.ts +309 -0
  348. package/src/lib/codegen/fixedPositionWriterGenerator.ts +444 -0
  349. package/src/lib/codegen/spanLoggerGenerator.ts +715 -0
  350. package/src/lib/convertToArrow.ts +1805 -0
  351. package/src/lib/defineOpContext.ts +398 -0
  352. package/src/lib/errors/Blocked.ts +165 -0
  353. package/src/lib/errors/CodeError.ts +132 -0
  354. package/src/lib/errors/RetriesExhausted.ts +78 -0
  355. package/src/lib/errors/Transient.ts +168 -0
  356. package/src/lib/errors/__tests__/Blocked-config.test.ts +152 -0
  357. package/src/lib/errors/__tests__/Transient.test.ts +129 -0
  358. package/src/lib/errors/__tests__/retry-policy.test.ts +85 -0
  359. package/src/lib/errors/index.ts +24 -0
  360. package/src/lib/errors/retry-policy.ts +87 -0
  361. package/src/lib/flushScheduler.ts +509 -0
  362. package/src/lib/library.ts +682 -0
  363. package/src/lib/logApi.ts +70 -0
  364. package/src/lib/logBinding.ts +67 -0
  365. package/src/lib/op.ts +103 -0
  366. package/src/lib/opContext/__tests__/retry.test.ts +764 -0
  367. package/src/lib/opContext/contextTypes.ts +130 -0
  368. package/src/lib/opContext/createOpGroup.ts +456 -0
  369. package/src/lib/opContext/defineOp.ts +281 -0
  370. package/src/lib/opContext/featureFlagTypes.ts +54 -0
  371. package/src/lib/opContext/index.ts +16 -0
  372. package/src/lib/opContext/opGroupTypes.ts +342 -0
  373. package/src/lib/opContext/opTypes.ts +80 -0
  374. package/src/lib/opContext/spanContextTypes.ts +398 -0
  375. package/src/lib/opContext/types.ts +403 -0
  376. package/src/lib/result.ts +550 -0
  377. package/src/lib/schema/LogSchema.ts +153 -0
  378. package/src/lib/schema/__tests__/defineLogSchema.test.ts +342 -0
  379. package/src/lib/schema/__tests__/featureFlags.test.ts +443 -0
  380. package/src/lib/schema/builder.ts +201 -0
  381. package/src/lib/schema/defineFeatureFlags.ts +91 -0
  382. package/src/lib/schema/defineLogSchema.ts +291 -0
  383. package/src/lib/schema/evaluator.ts +404 -0
  384. package/src/lib/schema/extend.ts +69 -0
  385. package/src/lib/schema/systemSchema.ts +339 -0
  386. package/src/lib/schema/typeGuards.ts +163 -0
  387. package/src/lib/schema/types.ts +265 -0
  388. package/src/lib/spanBuffer.ts +571 -0
  389. package/src/lib/spanBufferHelpers.ts +73 -0
  390. package/src/lib/spanBufferStats.ts +40 -0
  391. package/src/lib/spanContext.ts +1566 -0
  392. package/src/lib/sqlite/__tests__/sqlite-common.test.ts +89 -0
  393. package/src/lib/sqlite/index.ts +26 -0
  394. package/src/lib/sqlite/sqlite-async-writer.ts +101 -0
  395. package/src/lib/sqlite/sqlite-common.ts +309 -0
  396. package/src/lib/sqlite/sqlite-d1.ts +104 -0
  397. package/src/lib/sqlite/sqlite-db.ts +32 -0
  398. package/src/lib/sqlite/sqlite-node.ts +83 -0
  399. package/src/lib/sqlite/sqlite-writer.ts +128 -0
  400. package/src/lib/testing/TRACE-TESTING.md +100 -0
  401. package/src/lib/testing/__tests__/bun-harness.test.ts +108 -0
  402. package/src/lib/testing/__tests__/extractFacts.test.ts +279 -0
  403. package/src/lib/testing/__tests__/facts.test.ts +324 -0
  404. package/src/lib/testing/__tests__/vitest-harness.test.ts +32 -0
  405. package/src/lib/testing/bun-harness.ts +990 -0
  406. package/src/lib/testing/extractFacts.ts +362 -0
  407. package/src/lib/testing/facts.ts +470 -0
  408. package/src/lib/testing/index.ts +141 -0
  409. package/src/lib/testing/queryable-span.ts +108 -0
  410. package/src/lib/testing/span-query.ts +65 -0
  411. package/src/lib/testing/stdio-replay.ts +50 -0
  412. package/src/lib/testing/trace-query.ts +329 -0
  413. package/src/lib/testing/vitest-harness.ts +691 -0
  414. package/src/lib/threadId.ts +135 -0
  415. package/src/lib/traceContext.ts +182 -0
  416. package/src/lib/traceId.ts +142 -0
  417. package/src/lib/traceRoot.es.ts +157 -0
  418. package/src/lib/traceRoot.node.ts +170 -0
  419. package/src/lib/traceRoot.ts +154 -0
  420. package/src/lib/traceRoot.universal.ts +22 -0
  421. package/src/lib/tracer.ts +896 -0
  422. package/src/lib/tracers/ArrayQueueTracer.ts +76 -0
  423. package/src/lib/tracers/CompositeTracer.ts +76 -0
  424. package/src/lib/tracers/NoOpTracer.ts +73 -0
  425. package/src/lib/tracers/SQLiteTracer.ts +115 -0
  426. package/src/lib/tracers/StdioTracer.ts +380 -0
  427. package/src/lib/tracers/TestTracer.ts +146 -0
  428. package/src/lib/tracers/__tests__/ArrayQueueTracer.test.ts +184 -0
  429. package/src/lib/tracers/__tests__/NoOpTracer.test.ts +204 -0
  430. package/src/lib/tracers/__tests__/StdioTracer.test.ts +313 -0
  431. package/src/lib/tracers/__tests__/TestTracer.test.ts +200 -0
  432. package/src/lib/tracers/index.ts +12 -0
  433. package/src/lib/types.ts +498 -0
  434. package/src/lib/utf8Cache.ts +201 -0
  435. package/src/lib/wasm/WasmBufferStrategy.ts +219 -0
  436. package/src/lib/wasm/__tests__/WasmBufferStrategy.test.ts +256 -0
  437. package/src/lib/wasm/__tests__/wasm-integration.test.ts +476 -0
  438. package/src/lib/wasm/__tests__/wasmAllocator.test.ts +699 -0
  439. package/src/lib/wasm/__tests__/wasmSpanBuffer.test.ts +449 -0
  440. package/src/lib/wasm/__tests__/wasmTraceRoot.test.ts +390 -0
  441. package/src/lib/wasm/__tests__/wasmTracer.test.ts.disabled +444 -0
  442. package/src/lib/wasm/allocator.zig +945 -0
  443. package/src/lib/wasm/wasmAllocator.ts +469 -0
  444. package/src/lib/wasm/wasmSpanBuffer.ts +1014 -0
  445. package/src/lib/wasm/wasmTraceRoot.ts +315 -0
  446. package/src/node.ts +10 -0
  447. package/src/testing.ts +18 -0
@@ -0,0 +1,764 @@
1
+ /**
2
+ * Retry Integration Tests for LMAO Op
3
+ *
4
+ * Verifies end-to-end retry behavior in LMAO's span execution:
5
+ * - TransientError triggers retry based on error.policy
6
+ * - BlockedError returns immediately without retry
7
+ * - Non-transient errors return immediately
8
+ * - All backoff strategies work correctly
9
+ * - Policy override per-call works
10
+ * - span-retry entries are written for observability
11
+ *
12
+ * IMPORTANT: Retry logic is implemented in span execution (ctx.span()), not at tracer.trace() level.
13
+ * Root traces do NOT have retry. Tests use ctx.span() to trigger retry behavior.
14
+ *
15
+ * Note: Tests use very short delays (0-1ms) with jitter disabled to run quickly.
16
+ * The retry loop is tested with real time, not fake timers.
17
+ */
18
+
19
+ import { describe, expect, it } from 'bun:test';
20
+ import { createTestTracerOptions, requireFloat64Array, requireStringArray } from '../../__tests__/test-helpers.js';
21
+ import { defineOpContext } from '../../defineOpContext.js';
22
+ import { Blocked } from '../../errors/Blocked.js';
23
+ import { Code } from '../../errors/CodeError.js';
24
+ import { exponentialBackoff, fixedDelay, linearBackoff, Transient, TransientError } from '../../errors/Transient.js';
25
+ import type { OpContextOf, SpanContext } from '../../opContext/types.js';
26
+ import type { Result } from '../../result.js';
27
+ import { S } from '../../schema/builder.js';
28
+ import { defineLogSchema } from '../../schema/defineLogSchema.js';
29
+ import { ENTRY_TYPE_SPAN_RETRY } from '../../schema/systemSchema.js';
30
+ import { TestTracer } from '../../tracers/TestTracer.js';
31
+
32
+ // Test schema
33
+ const testSchema = defineLogSchema({
34
+ operation: S.category(),
35
+ service: S.category(),
36
+ });
37
+
38
+ // Test op context
39
+ const testOpContext = defineOpContext({
40
+ logSchema: testSchema,
41
+ });
42
+
43
+ const { defineOp } = testOpContext;
44
+ type TestSpanContext = SpanContext<OpContextOf<typeof testOpContext>>;
45
+
46
+ // Define transient error codes with SHORT delays for fast tests
47
+ // Using jitter: false and 0-1ms delays to avoid slow tests
48
+ const SERVICE_UNAVAILABLE = Transient<{ status?: number }>('SERVICE_UNAVAILABLE', {
49
+ backoff: 'exponential',
50
+ maxAttempts: 3,
51
+ baseDelayMs: 0,
52
+ jitter: false,
53
+ });
54
+ const NETWORK_ERROR = Transient<{ service: string }>('NETWORK_ERROR', {
55
+ backoff: 'linear',
56
+ maxAttempts: 3,
57
+ baseDelayMs: 0,
58
+ jitter: false,
59
+ });
60
+ // Non-transient error codes
61
+ const VALIDATION_ERROR = Code<{ field: string }>('VALIDATION_ERROR');
62
+ const PLAIN_ERROR = Code<{ detail: string }>('PLAIN_ERROR');
63
+ const CHILD_FAILED = Code<Record<string, never>>('CHILD_FAILED');
64
+
65
+ describe('LMAO Op Retry', () => {
66
+ // Helper to test retry behavior via child span
67
+ // Retry logic is in span execution (ctx.span()), not tracer.trace()
68
+ const executeWithRetry = async <TValue, TError>(
69
+ tracer: TestTracer<typeof testOpContext>,
70
+ spanName: string,
71
+ opFn: (ctx: TestSpanContext) => Result<TValue, TError> | Promise<Result<TValue, TError>>,
72
+ ): Promise<Result<TValue, TError>> => {
73
+ return tracer.trace('root', async (ctx) => {
74
+ // Use ctx.span() to trigger span execution with retry logic
75
+ return ctx.span(spanName, opFn);
76
+ });
77
+ };
78
+
79
+ describe('TransientError triggers retry', () => {
80
+ it('should retry on TransientError and succeed on second attempt', async () => {
81
+ let attempts = 0;
82
+
83
+ const tracer = new TestTracer(testOpContext, createTestTracerOptions());
84
+
85
+ const result = await executeWithRetry(tracer, 'testOp', async (ctx) => {
86
+ attempts++;
87
+ if (attempts < 2) {
88
+ return ctx.err(SERVICE_UNAVAILABLE({ status: 503 }));
89
+ }
90
+ return ctx.ok({ success: true });
91
+ });
92
+
93
+ expect(attempts).toBe(2);
94
+ expect(result.success).toBe(true);
95
+ });
96
+
97
+ it('should exhaust retries and return final TransientError', async () => {
98
+ let attempts = 0;
99
+
100
+ const tracer = new TestTracer(testOpContext, createTestTracerOptions());
101
+
102
+ const result = await executeWithRetry(tracer, 'testOp', async (ctx) => {
103
+ attempts++;
104
+ return ctx.err(NETWORK_ERROR({ service: 'payment-api' }));
105
+ });
106
+
107
+ expect(attempts).toBe(3); // maxAttempts from NETWORK_ERROR
108
+ expect(result.success).toBe(false);
109
+ if (!result.success) {
110
+ expect(result.error).toBeInstanceOf(TransientError);
111
+ }
112
+ });
113
+
114
+ it('should verify error is instanceof TransientError', async () => {
115
+ const tracer = new TestTracer(testOpContext, createTestTracerOptions());
116
+
117
+ await executeWithRetry(tracer, 'testOp', async (ctx) => {
118
+ const error = SERVICE_UNAVAILABLE({ status: 503 });
119
+ expect(error).toBeInstanceOf(TransientError);
120
+ expect(error).toBeInstanceOf(Error);
121
+ return ctx.err(error);
122
+ });
123
+ });
124
+ });
125
+
126
+ describe('BlockedError does not trigger retry', () => {
127
+ it('should return immediately without retry for Blocked.service', async () => {
128
+ let attempts = 0;
129
+
130
+ const tracer = new TestTracer(testOpContext, createTestTracerOptions());
131
+
132
+ const result = await executeWithRetry(tracer, 'testOp', async (ctx) => {
133
+ attempts++;
134
+ return ctx.err(Blocked.service('payment-api'));
135
+ });
136
+
137
+ expect(attempts).toBe(1); // No retries
138
+ expect(result.success).toBe(false);
139
+ });
140
+
141
+ it('should return immediately for Blocked.index', async () => {
142
+ let attempts = 0;
143
+
144
+ const tracer = new TestTracer(testOpContext, createTestTracerOptions());
145
+
146
+ const result = await executeWithRetry(tracer, 'testOp', async (ctx) => {
147
+ attempts++;
148
+ return ctx.err(Blocked.index('orders-index'));
149
+ });
150
+
151
+ expect(attempts).toBe(1); // No retries
152
+ expect(result.success).toBe(false);
153
+ if (!result.success) {
154
+ expect(result.error).toBeInstanceOf(Blocked);
155
+ }
156
+ });
157
+
158
+ it('should return immediately for Blocked.ended', async () => {
159
+ let attempts = 0;
160
+
161
+ const tracer = new TestTracer(testOpContext, createTestTracerOptions());
162
+
163
+ const result = await executeWithRetry(tracer, 'testOp', async (ctx) => {
164
+ attempts++;
165
+ return ctx.err(Blocked.ended('execution-123'));
166
+ });
167
+
168
+ expect(attempts).toBe(1); // No retries
169
+ expect(result.success).toBe(false);
170
+ if (!result.success) {
171
+ const error = result.error;
172
+ expect(error).toBeInstanceOf(Blocked);
173
+ if (error instanceof Blocked) {
174
+ expect(error.reason.type).toBe('ended');
175
+ }
176
+ }
177
+ });
178
+ });
179
+
180
+ describe('Non-transient errors do not trigger retry', () => {
181
+ it('should return error immediately for regular CodeError', async () => {
182
+ let attempts = 0;
183
+
184
+ const tracer = new TestTracer(testOpContext, createTestTracerOptions());
185
+
186
+ const result = await executeWithRetry(tracer, 'testOp', async (ctx) => {
187
+ attempts++;
188
+ return ctx.err(VALIDATION_ERROR({ field: 'email' }));
189
+ });
190
+
191
+ expect(attempts).toBe(1); // No retries
192
+ expect(result.success).toBe(false);
193
+ });
194
+
195
+ it('should return error immediately for plain object error', async () => {
196
+ let attempts = 0;
197
+
198
+ const tracer = new TestTracer(testOpContext, createTestTracerOptions());
199
+
200
+ const result = await executeWithRetry(tracer, 'testOp', async (ctx) => {
201
+ attempts++;
202
+ return ctx.err(PLAIN_ERROR({ detail: 'something' }));
203
+ });
204
+
205
+ expect(attempts).toBe(1); // No retries
206
+ expect(result.success).toBe(false);
207
+ });
208
+ });
209
+
210
+ describe('Backoff strategies', () => {
211
+ it('should use exponential backoff', async () => {
212
+ let attempts = 0;
213
+
214
+ const expBackoffError = Transient<void>('EXP_ERROR', {
215
+ backoff: 'exponential',
216
+ maxAttempts: 4,
217
+ baseDelayMs: 0,
218
+ jitter: false,
219
+ });
220
+
221
+ const tracer = new TestTracer(testOpContext, createTestTracerOptions());
222
+
223
+ const result = await executeWithRetry(tracer, 'testOp', async (ctx) => {
224
+ attempts++;
225
+ if (attempts < 4) {
226
+ return ctx.err(expBackoffError());
227
+ }
228
+ return ctx.ok({ success: true });
229
+ });
230
+
231
+ expect(result.success).toBe(true);
232
+ expect(attempts).toBe(4);
233
+ });
234
+
235
+ it('should use linear backoff', async () => {
236
+ let attempts = 0;
237
+
238
+ const linearError = Transient<void>('LINEAR_ERROR', {
239
+ backoff: 'linear',
240
+ maxAttempts: 4,
241
+ baseDelayMs: 0,
242
+ jitter: false,
243
+ });
244
+
245
+ const tracer = new TestTracer(testOpContext, createTestTracerOptions());
246
+
247
+ const result = await executeWithRetry(tracer, 'testOp', async (ctx) => {
248
+ attempts++;
249
+ if (attempts < 4) {
250
+ return ctx.err(linearError());
251
+ }
252
+ return ctx.ok({ success: true });
253
+ });
254
+
255
+ expect(result.success).toBe(true);
256
+ expect(attempts).toBe(4);
257
+ });
258
+
259
+ it('should use fixed delay', async () => {
260
+ let attempts = 0;
261
+
262
+ const fixedError = Transient<void>('FIXED_ERROR', {
263
+ backoff: 'fixed',
264
+ maxAttempts: 4,
265
+ baseDelayMs: 0,
266
+ jitter: false,
267
+ });
268
+
269
+ const tracer = new TestTracer(testOpContext, createTestTracerOptions());
270
+
271
+ const result = await executeWithRetry(tracer, 'testOp', async (ctx) => {
272
+ attempts++;
273
+ if (attempts < 4) {
274
+ return ctx.err(fixedError());
275
+ }
276
+ return ctx.ok({ success: true });
277
+ });
278
+
279
+ expect(result.success).toBe(true);
280
+ expect(attempts).toBe(4);
281
+ });
282
+
283
+ it('should respect maxDelayMs cap', async () => {
284
+ let attempts = 0;
285
+
286
+ // Exponential with low cap: would grow but is capped at maxDelayMs
287
+ const cappedError = Transient<void>('CAPPED_ERROR', {
288
+ backoff: 'exponential',
289
+ maxAttempts: 4,
290
+ baseDelayMs: 10,
291
+ maxDelayMs: 10, // Cap at 10ms
292
+ jitter: false,
293
+ });
294
+
295
+ const tracer = new TestTracer(testOpContext, createTestTracerOptions());
296
+
297
+ const result = await executeWithRetry(tracer, 'testOp', async (ctx) => {
298
+ attempts++;
299
+ if (attempts < 4) {
300
+ return ctx.err(cappedError());
301
+ }
302
+ return ctx.ok({ success: true });
303
+ });
304
+
305
+ expect(result.success).toBe(true);
306
+ expect(attempts).toBe(4);
307
+ });
308
+
309
+ it('should verify policy helpers create correct backoff types', () => {
310
+ // Verify exponentialBackoff helper
311
+ const expPolicy = exponentialBackoff(5);
312
+ expect(expPolicy.backoff).toBe('exponential');
313
+ expect(expPolicy.maxAttempts).toBe(5);
314
+ expect(expPolicy.jitter).toBe(true);
315
+
316
+ // Verify linearBackoff helper
317
+ const linPolicy = linearBackoff(3, 200);
318
+ expect(linPolicy.backoff).toBe('linear');
319
+ expect(linPolicy.maxAttempts).toBe(3);
320
+ expect(linPolicy.baseDelayMs).toBe(200);
321
+
322
+ // Verify fixedDelay helper
323
+ const fixPolicy = fixedDelay(2, 5000);
324
+ expect(fixPolicy.backoff).toBe('fixed');
325
+ expect(fixPolicy.maxAttempts).toBe(2);
326
+ expect(fixPolicy.baseDelayMs).toBe(5000);
327
+ expect(fixPolicy.jitter).toBe(false);
328
+ });
329
+ });
330
+
331
+ describe('Policy override', () => {
332
+ it('should allow per-call policy override to reduce maxAttempts', async () => {
333
+ let attempts = 0;
334
+
335
+ // Default policy has 3 attempts
336
+ const OVERRIDE_ERROR = Transient<void>('OVERRIDE_ERROR', {
337
+ backoff: 'exponential',
338
+ maxAttempts: 3,
339
+ baseDelayMs: 0,
340
+ jitter: false,
341
+ });
342
+
343
+ const tracer = new TestTracer(testOpContext, createTestTracerOptions());
344
+
345
+ const result = await executeWithRetry(tracer, 'testOp', async (ctx) => {
346
+ attempts++;
347
+ // Override to only 1 attempt (immediate failure)
348
+ return ctx.err(OVERRIDE_ERROR({ maxAttempts: 1 }));
349
+ });
350
+
351
+ expect(attempts).toBe(1); // Override to 1 attempt
352
+ expect(result.success).toBe(false);
353
+ });
354
+
355
+ it('should allow per-call policy override to change backoff strategy', async () => {
356
+ let attempts = 0;
357
+
358
+ // Default is exponential
359
+ const STRATEGY_ERROR = Transient<{ info: string }>('STRATEGY_ERROR', {
360
+ backoff: 'exponential',
361
+ maxAttempts: 3,
362
+ baseDelayMs: 0,
363
+ jitter: false,
364
+ });
365
+
366
+ const tracer = new TestTracer(testOpContext, createTestTracerOptions());
367
+
368
+ const result = await executeWithRetry(tracer, 'testOp', async (ctx) => {
369
+ attempts++;
370
+ if (attempts < 3) {
371
+ // Override to fixed delay
372
+ return ctx.err(STRATEGY_ERROR({ info: 'retry' }, { backoff: 'fixed', baseDelayMs: 0 }));
373
+ }
374
+ return ctx.ok({ success: true });
375
+ });
376
+
377
+ expect(result.success).toBe(true);
378
+ expect(attempts).toBe(3);
379
+ });
380
+
381
+ it('should allow complete policy replacement', async () => {
382
+ let attempts = 0;
383
+
384
+ const BASE_ERROR = Transient<void>('BASE_ERROR', exponentialBackoff(5));
385
+
386
+ const tracer = new TestTracer(testOpContext, createTestTracerOptions());
387
+
388
+ const result = await executeWithRetry(tracer, 'testOp', async (ctx) => {
389
+ attempts++;
390
+ // Replace entire policy with 1 attempt = no retry
391
+ return ctx.err(BASE_ERROR({ maxAttempts: 1, baseDelayMs: 0, jitter: false }));
392
+ });
393
+
394
+ expect(attempts).toBe(1);
395
+ expect(result.success).toBe(false);
396
+ });
397
+ });
398
+
399
+ describe('Distinguishing TransientError from BlockedError', () => {
400
+ it('TransientError triggers retry, BlockedError does not', async () => {
401
+ let transientAttempts = 0;
402
+ let blockedAttempts = 0;
403
+
404
+ const tracer = new TestTracer(testOpContext, createTestTracerOptions());
405
+
406
+ // Execute blocked - should return immediately
407
+ const blockedResult = await tracer.trace('blocked-trace', async (ctx) => {
408
+ return ctx.span('blocked-span', async (spanCtx) => {
409
+ blockedAttempts++;
410
+ return spanCtx.err(Blocked.service('dependency'));
411
+ });
412
+ });
413
+ expect(blockedAttempts).toBe(1);
414
+ expect(blockedResult.success).toBe(false);
415
+
416
+ // Execute transient - should retry
417
+ const transientResult = await tracer.trace('transient-trace', async (ctx) => {
418
+ return ctx.span('transient-span', async (spanCtx) => {
419
+ transientAttempts++;
420
+ return spanCtx.err(SERVICE_UNAVAILABLE({ status: 503 }));
421
+ });
422
+ });
423
+
424
+ expect(transientAttempts).toBe(3); // maxAttempts: 3
425
+ expect(transientResult.success).toBe(false);
426
+ });
427
+
428
+ it('different error types have correct instanceof checks', () => {
429
+ const transientErr = SERVICE_UNAVAILABLE({ status: 503 });
430
+ const blockedErr = Blocked.service('api');
431
+ const codeErr = VALIDATION_ERROR({ field: 'email' });
432
+
433
+ // TransientError checks
434
+ expect(transientErr instanceof TransientError).toBe(true);
435
+ expect(transientErr instanceof Blocked).toBe(false);
436
+ expect(transientErr instanceof Error).toBe(true);
437
+
438
+ // Blocked checks
439
+ expect(blockedErr instanceof Blocked).toBe(true);
440
+ expect(blockedErr instanceof TransientError).toBe(false);
441
+ expect(blockedErr instanceof Error).toBe(true);
442
+
443
+ // CodeError checks
444
+ expect(codeErr instanceof TransientError).toBe(false);
445
+ expect(codeErr instanceof Blocked).toBe(false);
446
+ expect(codeErr instanceof Error).toBe(true);
447
+ });
448
+ });
449
+
450
+ describe('span-retry entries', () => {
451
+ it('should write span-retry entries for each retry attempt', async () => {
452
+ let attempts = 0;
453
+ const RETRY_OBSERVABILITY = Transient<{ status?: number }>('RETRY_OBSERVABILITY', {
454
+ backoff: 'fixed',
455
+ maxAttempts: 3,
456
+ baseDelayMs: 17,
457
+ jitter: false,
458
+ });
459
+
460
+ const tracer = new TestTracer(testOpContext, createTestTracerOptions());
461
+
462
+ const result = await tracer.trace('root', async (ctx) => {
463
+ return ctx.span('retryObservability', async (spanCtx) => {
464
+ attempts++;
465
+ if (attempts < 3) {
466
+ return spanCtx.err(RETRY_OBSERVABILITY({ status: 503 }));
467
+ }
468
+ return spanCtx.ok({ success: true });
469
+ });
470
+ });
471
+
472
+ expect(result.success).toBe(true);
473
+
474
+ // Verify span-retry entries were written
475
+ expect(tracer.rootBuffers.length).toBe(1);
476
+ const rootBuffer = tracer.rootBuffers[0];
477
+
478
+ // Get child span buffer (the span execution)
479
+ const childBuffers = rootBuffer._children;
480
+ expect(childBuffers.length).toBe(1);
481
+ const spanBuffer = childBuffers[0];
482
+
483
+ // Check entry_type for ENTRY_TYPE_SPAN_RETRY (value 5)
484
+ // Row 0: span-start
485
+ // Row 1: span-ok/span-err
486
+ // Row 2+: log entries and span-retry entries
487
+ const entryTypes = spanBuffer.entry_type;
488
+ const retryEntries: number[] = [];
489
+ for (let i = 2; i < spanBuffer._writeIndex; i++) {
490
+ if (entryTypes[i] === ENTRY_TYPE_SPAN_RETRY) {
491
+ retryEntries.push(i);
492
+ }
493
+ }
494
+
495
+ // Should have 2 retry entries (attempts 1 and 2 failed)
496
+ expect(retryEntries.length).toBe(2);
497
+
498
+ // Verify message format: retry:op:{opName}
499
+ // Note: For inline functions, the opMetadata name comes from the parent context
500
+ // which in this test is 'root' (the root trace name)
501
+ const messages = requireStringArray(spanBuffer.getColumnIfAllocated('message'), 'retry messages');
502
+ const retryAttempts = requireFloat64Array(spanBuffer.getColumnIfAllocated('retry_attempt'), 'retry attempts');
503
+ const retryDelays = requireFloat64Array(spanBuffer.getColumnIfAllocated('retry_delay_ms'), 'retry delays');
504
+ for (const idx of retryEntries) {
505
+ expect(messages[idx]).toBe('retry:op:root');
506
+ }
507
+
508
+ expect(retryAttempts[retryEntries[0]]).toBe(1);
509
+ expect(retryAttempts[retryEntries[1]]).toBe(2);
510
+ expect(retryDelays[retryEntries[0]]).toBe(17);
511
+ expect(retryDelays[retryEntries[1]]).toBe(17);
512
+ });
513
+
514
+ it('should not write span-retry entries when no retries occur', async () => {
515
+ const tracer = new TestTracer(testOpContext, createTestTracerOptions());
516
+
517
+ await tracer.trace('root', async (ctx) => {
518
+ return ctx.span('noRetry', async (spanCtx) => {
519
+ return spanCtx.ok({ success: true });
520
+ });
521
+ });
522
+
523
+ expect(tracer.rootBuffers.length).toBe(1);
524
+ const rootBuffer = tracer.rootBuffers[0];
525
+ const childBuffers = rootBuffer._children;
526
+ expect(childBuffers.length).toBe(1);
527
+ const spanBuffer = childBuffers[0];
528
+
529
+ // Check for any retry entries
530
+ const entryTypes = spanBuffer.entry_type;
531
+ let retryCount = 0;
532
+ for (let i = 0; i < spanBuffer._writeIndex; i++) {
533
+ if (entryTypes[i] === ENTRY_TYPE_SPAN_RETRY) {
534
+ retryCount++;
535
+ }
536
+ }
537
+
538
+ // No retries occurred, so no span-retry entries
539
+ expect(retryCount).toBe(0);
540
+ });
541
+
542
+ it('should write span-retry entries even when retries are exhausted', async () => {
543
+ const tracer = new TestTracer(testOpContext, createTestTracerOptions());
544
+
545
+ const result = await tracer.trace('root', async (ctx) => {
546
+ return ctx.span('exhaustedRetries', async (spanCtx) => {
547
+ return spanCtx.err(SERVICE_UNAVAILABLE({ status: 503 }));
548
+ });
549
+ });
550
+
551
+ expect(result.success).toBe(false);
552
+
553
+ const rootBuffer = tracer.rootBuffers[0];
554
+ const spanBuffer = rootBuffer._children[0];
555
+
556
+ // Check for retry entries
557
+ const entryTypes = spanBuffer.entry_type;
558
+ let retryCount = 0;
559
+ for (let i = 0; i < spanBuffer._writeIndex; i++) {
560
+ if (entryTypes[i] === ENTRY_TYPE_SPAN_RETRY) {
561
+ retryCount++;
562
+ }
563
+ }
564
+
565
+ // maxAttempts: 3 means 3 attempts total, 2 retries
566
+ // Each failed attempt before exhaustion writes a retry entry
567
+ expect(retryCount).toBe(2);
568
+ });
569
+
570
+ it('should include error code in span-retry entry', async () => {
571
+ let attempts = 0;
572
+
573
+ const tracer = new TestTracer(testOpContext, createTestTracerOptions());
574
+
575
+ await tracer.trace('root', async (ctx) => {
576
+ return ctx.span('retryErrorCode', async (spanCtx) => {
577
+ attempts++;
578
+ if (attempts < 2) {
579
+ return spanCtx.err(SERVICE_UNAVAILABLE({ status: 503 }));
580
+ }
581
+ return spanCtx.ok({ success: true });
582
+ });
583
+ });
584
+
585
+ const rootBuffer = tracer.rootBuffers[0];
586
+ const spanBuffer = rootBuffer._children[0];
587
+
588
+ // Find retry entry
589
+ const entryTypes = spanBuffer.entry_type;
590
+ let retryIdx = -1;
591
+ for (let i = 2; i < spanBuffer._writeIndex; i++) {
592
+ if (entryTypes[i] === ENTRY_TYPE_SPAN_RETRY) {
593
+ retryIdx = i;
594
+ break;
595
+ }
596
+ }
597
+
598
+ expect(retryIdx).toBeGreaterThan(-1);
599
+ // Check error_code was written
600
+ const errorCodes = requireStringArray(spanBuffer.getColumnIfAllocated('error_code'), 'error codes');
601
+ expect(errorCodes[retryIdx]).toBe('SERVICE_UNAVAILABLE');
602
+ });
603
+ });
604
+
605
+ describe('Edge cases', () => {
606
+ it('should handle immediate success (no retries needed)', async () => {
607
+ let attempts = 0;
608
+
609
+ const tracer = new TestTracer(testOpContext, createTestTracerOptions());
610
+
611
+ const result = await executeWithRetry(tracer, 'immediateSuccess', async (ctx) => {
612
+ attempts++;
613
+ return ctx.ok({ immediate: true });
614
+ });
615
+
616
+ expect(attempts).toBe(1);
617
+ expect(result.success).toBe(true);
618
+ if (result.success) {
619
+ expect(result.value.immediate).toBe(true);
620
+ }
621
+ });
622
+
623
+ it('should handle maxAttempts of 1 (no retry)', async () => {
624
+ let attempts = 0;
625
+
626
+ const noRetryError = Transient<void>('NO_RETRY', {
627
+ backoff: 'fixed',
628
+ maxAttempts: 1,
629
+ baseDelayMs: 0,
630
+ jitter: false,
631
+ });
632
+
633
+ const tracer = new TestTracer(testOpContext, createTestTracerOptions());
634
+
635
+ const result = await executeWithRetry(tracer, 'noRetryOp', async (ctx) => {
636
+ attempts++;
637
+ return ctx.err(noRetryError());
638
+ });
639
+
640
+ expect(attempts).toBe(1); // No retries with maxAttempts=1
641
+ expect(result.success).toBe(false);
642
+ });
643
+
644
+ it('should preserve tags written before retry', async () => {
645
+ let attempts = 0;
646
+
647
+ const tracer = new TestTracer(testOpContext, createTestTracerOptions());
648
+
649
+ const result = await tracer.trace('root', async (ctx) => {
650
+ return ctx.span('tagPreservation', async (spanCtx) => {
651
+ attempts++;
652
+ // Write tag on first attempt
653
+ if (attempts === 1) {
654
+ spanCtx.tag.operation('INSERT').service('payment-api');
655
+ }
656
+ if (attempts < 2) {
657
+ return spanCtx.err(SERVICE_UNAVAILABLE({ status: 503 }));
658
+ }
659
+ return spanCtx.ok({ success: true });
660
+ });
661
+ });
662
+
663
+ expect(result.success).toBe(true);
664
+
665
+ // Verify tags were preserved through retry
666
+ const rootBuffer = tracer.rootBuffers[0];
667
+ const spanBuffer = rootBuffer._children[0];
668
+
669
+ // Tags are written at row 0 (span-start)
670
+ const operations = requireStringArray(spanBuffer.getColumnIfAllocated('operation'), 'operations');
671
+ const services = requireStringArray(spanBuffer.getColumnIfAllocated('service'), 'services');
672
+ expect(operations[0]).toBe('INSERT');
673
+ expect(services[0]).toBe('payment-api');
674
+ });
675
+
676
+ it('should work with nested child spans containing retry logic', async () => {
677
+ let childAttempts = 0;
678
+
679
+ const tracer = new TestTracer(testOpContext, createTestTracerOptions());
680
+
681
+ const result = await tracer.trace('root', async (rootCtx) => {
682
+ return rootCtx.span('parent', async (parentCtx) => {
683
+ const childResult = await parentCtx.span('childWithRetry', async (childCtx) => {
684
+ childAttempts++;
685
+ if (childAttempts < 2) {
686
+ return childCtx.err(SERVICE_UNAVAILABLE({ status: 503 }));
687
+ }
688
+ return childCtx.ok({ child: true });
689
+ });
690
+
691
+ if (!childResult.success) {
692
+ return parentCtx.err(CHILD_FAILED({}));
693
+ }
694
+
695
+ return parentCtx.ok({ parent: true, childResult: childResult.value });
696
+ });
697
+ });
698
+
699
+ expect(result.success).toBe(true);
700
+ expect(childAttempts).toBe(2);
701
+ });
702
+
703
+ it('should handle multiple retries', async () => {
704
+ let attempts = 0;
705
+
706
+ // Use 5 retries to fit within default buffer capacity of 8
707
+ // (span-start, span-ok/err, 4 retry entries = 6 rows)
708
+ const multiRetryError = Transient<void>('MULTI_RETRY', {
709
+ backoff: 'fixed',
710
+ maxAttempts: 5,
711
+ baseDelayMs: 0,
712
+ jitter: false,
713
+ });
714
+
715
+ const tracer = new TestTracer(testOpContext, createTestTracerOptions());
716
+
717
+ const result = await tracer.trace('root', async (ctx) => {
718
+ return ctx.span('multiRetries', async (spanCtx) => {
719
+ attempts++;
720
+ if (attempts < 5) {
721
+ return spanCtx.err(multiRetryError());
722
+ }
723
+ return spanCtx.ok({ success: true });
724
+ });
725
+ });
726
+
727
+ expect(result.success).toBe(true);
728
+ expect(attempts).toBe(5);
729
+
730
+ // Verify 4 retry entries (attempts 1-4 failed)
731
+ const spanBuffer = tracer.rootBuffers[0]._children[0];
732
+ const entryTypes = spanBuffer.entry_type;
733
+ let retryCount = 0;
734
+ for (let i = 0; i < spanBuffer._writeIndex; i++) {
735
+ if (entryTypes[i] === ENTRY_TYPE_SPAN_RETRY) {
736
+ retryCount++;
737
+ }
738
+ }
739
+ expect(retryCount).toBe(4);
740
+ });
741
+
742
+ it('should work with defineOp inside span', async () => {
743
+ let attempts = 0;
744
+
745
+ const retryOp = defineOp('retryOp', async (ctx) => {
746
+ attempts++;
747
+ if (attempts < 2) {
748
+ return ctx.err(SERVICE_UNAVAILABLE({ status: 503 }));
749
+ }
750
+ return ctx.ok({ done: true });
751
+ });
752
+
753
+ const tracer = new TestTracer(testOpContext, createTestTracerOptions());
754
+
755
+ const result = await tracer.trace('root', async (ctx) => {
756
+ // Using Op via ctx.span triggers the retry logic
757
+ return ctx.span('op-span', retryOp);
758
+ });
759
+
760
+ expect(attempts).toBe(2);
761
+ expect(result.success).toBe(true);
762
+ });
763
+ });
764
+ });