effect 4.0.0-rc.112 → 4.0.0-rc.113
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/AGENTS.md +24 -9
- package/CLAUDE.md +24 -9
- package/ai-docs/package.json +2 -2
- package/ai-docs/src/01_effect/01_basics/02_effect-fn.ts +18 -5
- package/ai-docs/src/01_effect/01_basics/index.md +5 -3
- package/ai-docs/src/01_effect/03_services/20_layer-composition.ts +1 -1
- package/ai-docs/src/01_effect/03_services/20_layer-unwrap.ts +2 -2
- package/ai-docs/src/01_effect/05_resources/10_acquire-release.ts +2 -2
- package/ai-docs/src/03_stream/30_encoding.ts +5 -7
- package/ai-docs/src/08_observability/10_logging.ts +1 -1
- package/ai-docs/src/70_cli/10_basics.ts +7 -7
- package/ai-docs/src/71_ai/10_language-model.ts +2 -2
- package/ai-docs/src/71_ai/20_tools.ts +1 -1
- package/ai-docs/src/71_ai/30_chat.ts +1 -1
- package/dist/Array.d.ts +86 -50
- package/dist/Array.d.ts.map +1 -1
- package/dist/Array.js +58 -32
- package/dist/Array.js.map +1 -1
- package/dist/BigDecimal.d.ts +5 -1
- package/dist/BigDecimal.d.ts.map +1 -1
- package/dist/BigDecimal.js +40 -23
- package/dist/BigDecimal.js.map +1 -1
- package/dist/ByteSize.d.ts +633 -0
- package/dist/ByteSize.d.ts.map +1 -0
- package/dist/ByteSize.js +524 -0
- package/dist/ByteSize.js.map +1 -0
- package/dist/Cache.d.ts.map +1 -1
- package/dist/Cache.js +17 -3
- package/dist/Cache.js.map +1 -1
- package/dist/Cause.d.ts +1 -1
- package/dist/Cause.d.ts.map +1 -1
- package/dist/Channel.d.ts +97 -24
- package/dist/Channel.d.ts.map +1 -1
- package/dist/Channel.js +66 -39
- package/dist/Channel.js.map +1 -1
- package/dist/Chunk.d.ts +49 -28
- package/dist/Chunk.d.ts.map +1 -1
- package/dist/Chunk.js +27 -18
- package/dist/Chunk.js.map +1 -1
- package/dist/Config.d.ts +162 -201
- package/dist/Config.d.ts.map +1 -1
- package/dist/Config.js +103 -212
- package/dist/Config.js.map +1 -1
- package/dist/ConfigProvider.d.ts +4 -4
- package/dist/ConfigProvider.d.ts.map +1 -1
- package/dist/ConfigProvider.js +7 -7
- package/dist/ConfigProvider.js.map +1 -1
- package/dist/Context.d.ts +31 -0
- package/dist/Context.d.ts.map +1 -1
- package/dist/Context.js.map +1 -1
- package/dist/Cron.d.ts +2 -2
- package/dist/Cron.d.ts.map +1 -1
- package/dist/Cron.js +2 -2
- package/dist/Cron.js.map +1 -1
- package/dist/Crypto.d.ts +1 -1
- package/dist/Crypto.d.ts.map +1 -1
- package/dist/Crypto.js +3 -2
- package/dist/Crypto.js.map +1 -1
- package/dist/DateTime.d.ts +2 -2
- package/dist/DateTime.d.ts.map +1 -1
- package/dist/Deferred.d.ts.map +1 -1
- package/dist/Deferred.js +6 -6
- package/dist/Deferred.js.map +1 -1
- package/dist/Duration.d.ts +1 -1
- package/dist/Duration.d.ts.map +1 -1
- package/dist/Duration.js +1 -1
- package/dist/Duration.js.map +1 -1
- package/dist/Effect.d.ts +220 -113
- package/dist/Effect.d.ts.map +1 -1
- package/dist/Effect.js +27 -26
- package/dist/Effect.js.map +1 -1
- package/dist/Effectable.d.ts +58 -2
- package/dist/Effectable.d.ts.map +1 -1
- package/dist/Effectable.js +58 -6
- package/dist/Effectable.js.map +1 -1
- package/dist/Encoding.d.ts +3 -1
- package/dist/Encoding.d.ts.map +1 -1
- package/dist/Encoding.js +40 -10
- package/dist/Encoding.js.map +1 -1
- package/dist/Equal.d.ts +1 -1
- package/dist/Equal.d.ts.map +1 -1
- package/dist/Equal.js +1 -1
- package/dist/Equal.js.map +1 -1
- package/dist/ExecutionPlan.d.ts.map +1 -1
- package/dist/ExecutionPlan.js +1 -0
- package/dist/ExecutionPlan.js.map +1 -1
- package/dist/Fiber.d.ts +32 -8
- package/dist/Fiber.d.ts.map +1 -1
- package/dist/Fiber.js.map +1 -1
- package/dist/FiberHandle.js +3 -3
- package/dist/FiberHandle.js.map +1 -1
- package/dist/FiberMap.d.ts +12 -6
- package/dist/FiberMap.d.ts.map +1 -1
- package/dist/FiberMap.js +11 -6
- package/dist/FiberMap.js.map +1 -1
- package/dist/FileSystem.d.ts +42 -210
- package/dist/FileSystem.d.ts.map +1 -1
- package/dist/FileSystem.js +16 -148
- package/dist/FileSystem.js.map +1 -1
- package/dist/Formatter.d.ts +1 -0
- package/dist/Formatter.d.ts.map +1 -1
- package/dist/Formatter.js +19 -3
- package/dist/Formatter.js.map +1 -1
- package/dist/Graph.d.ts +48 -20
- package/dist/Graph.d.ts.map +1 -1
- package/dist/Graph.js +20 -5
- package/dist/Graph.js.map +1 -1
- package/dist/Hash.d.ts +1 -1
- package/dist/Hash.d.ts.map +1 -1
- package/dist/Hash.js +5 -14
- package/dist/Hash.js.map +1 -1
- package/dist/HashMap.d.ts +1 -1
- package/dist/HashMap.d.ts.map +1 -1
- package/dist/HashRing.d.ts +6 -1
- package/dist/HashRing.d.ts.map +1 -1
- package/dist/HashRing.js +9 -2
- package/dist/HashRing.js.map +1 -1
- package/dist/HashSet.d.ts +1 -1
- package/dist/HashSet.d.ts.map +1 -1
- package/dist/HashSet.js.map +1 -1
- package/dist/Iterable.d.ts +33 -15
- package/dist/Iterable.d.ts.map +1 -1
- package/dist/Iterable.js +58 -45
- package/dist/Iterable.js.map +1 -1
- package/dist/JsonPatch.js +4 -4
- package/dist/JsonPatch.js.map +1 -1
- package/dist/JsonPointer.d.ts +68 -4
- package/dist/JsonPointer.d.ts.map +1 -1
- package/dist/JsonPointer.js +90 -4
- package/dist/JsonPointer.js.map +1 -1
- package/dist/JsonSchema.js +8 -22
- package/dist/JsonSchema.js.map +1 -1
- package/dist/Layer.d.ts +47 -4
- package/dist/Layer.d.ts.map +1 -1
- package/dist/Layer.js +4 -6
- package/dist/Layer.js.map +1 -1
- package/dist/LayerMap.d.ts +1 -3
- package/dist/LayerMap.d.ts.map +1 -1
- package/dist/LayerMap.js +7 -5
- package/dist/LayerMap.js.map +1 -1
- package/dist/LayerRef.d.ts.map +1 -1
- package/dist/LayerRef.js +7 -5
- package/dist/LayerRef.js.map +1 -1
- package/dist/Logger.d.ts +114 -9
- package/dist/Logger.d.ts.map +1 -1
- package/dist/Logger.js +109 -9
- package/dist/Logger.js.map +1 -1
- package/dist/ManagedRuntime.js +1 -1
- package/dist/ManagedRuntime.js.map +1 -1
- package/dist/Match.d.ts +43 -31
- package/dist/Match.d.ts.map +1 -1
- package/dist/Match.js +5 -2
- package/dist/Match.js.map +1 -1
- package/dist/Metric.d.ts +11 -4
- package/dist/Metric.d.ts.map +1 -1
- package/dist/Metric.js +14 -18
- package/dist/Metric.js.map +1 -1
- package/dist/MutableHashMap.d.ts +1 -1
- package/dist/MutableHashMap.d.ts.map +1 -1
- package/dist/MutableHashMap.js +1 -1
- package/dist/MutableHashMap.js.map +1 -1
- package/dist/MutableHashSet.d.ts +1 -1
- package/dist/MutableHashSet.d.ts.map +1 -1
- package/dist/MutableHashSet.js +1 -1
- package/dist/MutableHashSet.js.map +1 -1
- package/dist/MutableList.d.ts +13 -2
- package/dist/MutableList.d.ts.map +1 -1
- package/dist/MutableList.js +18 -2
- package/dist/MutableList.js.map +1 -1
- package/dist/Number.d.ts +6 -0
- package/dist/Number.d.ts.map +1 -1
- package/dist/Number.js +3 -1
- package/dist/Number.js.map +1 -1
- package/dist/Optic.d.ts.map +1 -1
- package/dist/Optic.js +5 -4
- package/dist/Optic.js.map +1 -1
- package/dist/Option.d.ts +1 -1
- package/dist/Option.d.ts.map +1 -1
- package/dist/Option.js +1 -1
- package/dist/Option.js.map +1 -1
- package/dist/Order.d.ts +1 -0
- package/dist/Order.d.ts.map +1 -1
- package/dist/Order.js +3 -1
- package/dist/Order.js.map +1 -1
- package/dist/PartitionedSemaphore.d.ts.map +1 -1
- package/dist/PartitionedSemaphore.js +1 -2
- package/dist/PartitionedSemaphore.js.map +1 -1
- package/dist/Path.d.ts +1 -1
- package/dist/Path.d.ts.map +1 -1
- package/dist/Path.js +1 -1
- package/dist/Path.js.map +1 -1
- package/dist/PlatformError.d.ts +1 -1
- package/dist/PlatformError.d.ts.map +1 -1
- package/dist/PlatformError.js +1 -1
- package/dist/PlatformError.js.map +1 -1
- package/dist/Pool.d.ts +38 -1
- package/dist/Pool.d.ts.map +1 -1
- package/dist/Pool.js +81 -5
- package/dist/Pool.js.map +1 -1
- package/dist/PrimaryKey.d.ts +1 -1
- package/dist/PrimaryKey.d.ts.map +1 -1
- package/dist/PrimaryKey.js +1 -1
- package/dist/PrimaryKey.js.map +1 -1
- package/dist/PubSub.d.ts +21 -9
- package/dist/PubSub.d.ts.map +1 -1
- package/dist/PubSub.js +18 -14
- package/dist/PubSub.js.map +1 -1
- package/dist/Queue.d.ts +82 -6
- package/dist/Queue.d.ts.map +1 -1
- package/dist/Queue.js +116 -27
- package/dist/Queue.js.map +1 -1
- package/dist/Random.d.ts +17 -4
- package/dist/Random.d.ts.map +1 -1
- package/dist/Random.js +1 -1
- package/dist/Random.js.map +1 -1
- package/dist/RcMap.d.ts.map +1 -1
- package/dist/RcMap.js +15 -9
- package/dist/RcMap.js.map +1 -1
- package/dist/Redacted.d.ts +1 -1
- package/dist/Redacted.d.ts.map +1 -1
- package/dist/Redacted.js +1 -1
- package/dist/Redacted.js.map +1 -1
- package/dist/RequestResolver.d.ts +15 -9
- package/dist/RequestResolver.d.ts.map +1 -1
- package/dist/RequestResolver.js +33 -15
- package/dist/RequestResolver.js.map +1 -1
- package/dist/Result.d.ts +1 -1
- package/dist/Result.d.ts.map +1 -1
- package/dist/Result.js +1 -1
- package/dist/Result.js.map +1 -1
- package/dist/Scheduler.d.ts.map +1 -1
- package/dist/Scheduler.js +19 -10
- package/dist/Scheduler.js.map +1 -1
- package/dist/Schema.d.ts +2155 -2415
- package/dist/Schema.d.ts.map +1 -1
- package/dist/Schema.js +2755 -4174
- package/dist/Schema.js.map +1 -1
- package/dist/SchemaAST.d.ts +354 -183
- package/dist/SchemaAST.d.ts.map +1 -1
- package/dist/SchemaAST.js +277 -601
- package/dist/SchemaAST.js.map +1 -1
- package/dist/SchemaGetter.d.ts +46 -22
- package/dist/SchemaGetter.d.ts.map +1 -1
- package/dist/SchemaGetter.js +56 -53
- package/dist/SchemaGetter.js.map +1 -1
- package/dist/SchemaIssue.d.ts +122 -188
- package/dist/SchemaIssue.d.ts.map +1 -1
- package/dist/SchemaIssue.js +48 -263
- package/dist/SchemaIssue.js.map +1 -1
- package/dist/SchemaParser.js +2 -9
- package/dist/SchemaParser.js.map +1 -1
- package/dist/SchemaRepresentation.d.ts +1099 -16
- package/dist/SchemaRepresentation.d.ts.map +1 -1
- package/dist/SchemaRepresentation.js +1341 -20
- package/dist/SchemaRepresentation.js.map +1 -1
- package/dist/SchemaTransformation.d.ts +49 -16
- package/dist/SchemaTransformation.d.ts.map +1 -1
- package/dist/SchemaTransformation.js +75 -98
- package/dist/SchemaTransformation.js.map +1 -1
- package/dist/ScopedCache.d.ts.map +1 -1
- package/dist/ScopedCache.js +10 -3
- package/dist/ScopedCache.js.map +1 -1
- package/dist/Sink.d.ts +9 -4
- package/dist/Sink.d.ts.map +1 -1
- package/dist/Sink.js +49 -31
- package/dist/Sink.js.map +1 -1
- package/dist/Stream.d.ts +221 -35
- package/dist/Stream.d.ts.map +1 -1
- package/dist/Stream.js +168 -84
- package/dist/Stream.js.map +1 -1
- package/dist/String.d.ts +16 -6
- package/dist/String.d.ts.map +1 -1
- package/dist/String.js +12 -5
- package/dist/String.js.map +1 -1
- package/dist/Struct.d.ts.map +1 -1
- package/dist/Struct.js +7 -4
- package/dist/Struct.js.map +1 -1
- package/dist/SynchronizedRef.d.ts +3 -2
- package/dist/SynchronizedRef.d.ts.map +1 -1
- package/dist/SynchronizedRef.js.map +1 -1
- package/dist/Terminal.d.ts +3 -3
- package/dist/Terminal.d.ts.map +1 -1
- package/dist/Terminal.js +3 -3
- package/dist/Terminal.js.map +1 -1
- package/dist/Tracer.d.ts +27 -7
- package/dist/Tracer.d.ts.map +1 -1
- package/dist/Tracer.js +38 -13
- package/dist/Tracer.js.map +1 -1
- package/dist/Trie.d.ts +1 -1
- package/dist/Trie.d.ts.map +1 -1
- package/dist/Tuple.d.ts +2 -1
- package/dist/Tuple.d.ts.map +1 -1
- package/dist/Tuple.js.map +1 -1
- package/dist/TxChunk.d.ts +1 -1
- package/dist/TxChunk.d.ts.map +1 -1
- package/dist/TxChunk.js +1 -1
- package/dist/TxChunk.js.map +1 -1
- package/dist/TxDeferred.d.ts +1 -1
- package/dist/TxDeferred.d.ts.map +1 -1
- package/dist/TxDeferred.js +1 -1
- package/dist/TxDeferred.js.map +1 -1
- package/dist/TxHashMap.d.ts +1 -1
- package/dist/TxHashMap.d.ts.map +1 -1
- package/dist/TxHashMap.js +1 -1
- package/dist/TxHashMap.js.map +1 -1
- package/dist/TxHashSet.d.ts +1 -1
- package/dist/TxHashSet.d.ts.map +1 -1
- package/dist/TxHashSet.js +1 -1
- package/dist/TxHashSet.js.map +1 -1
- package/dist/TxPriorityQueue.d.ts +1 -1
- package/dist/TxPriorityQueue.d.ts.map +1 -1
- package/dist/TxPriorityQueue.js +1 -1
- package/dist/TxPriorityQueue.js.map +1 -1
- package/dist/TxPubSub.d.ts +1 -1
- package/dist/TxPubSub.d.ts.map +1 -1
- package/dist/TxPubSub.js +1 -1
- package/dist/TxPubSub.js.map +1 -1
- package/dist/TxQueue.d.ts +9 -9
- package/dist/TxQueue.d.ts.map +1 -1
- package/dist/TxQueue.js +93 -86
- package/dist/TxQueue.js.map +1 -1
- package/dist/TxReentrantLock.d.ts +29 -1
- package/dist/TxReentrantLock.d.ts.map +1 -1
- package/dist/TxReentrantLock.js +29 -1
- package/dist/TxReentrantLock.js.map +1 -1
- package/dist/TxRef.d.ts +1 -1
- package/dist/TxRef.d.ts.map +1 -1
- package/dist/TxRef.js +1 -1
- package/dist/TxRef.js.map +1 -1
- package/dist/TxSemaphore.d.ts +1 -1
- package/dist/TxSemaphore.d.ts.map +1 -1
- package/dist/TxSemaphore.js +1 -1
- package/dist/TxSemaphore.js.map +1 -1
- package/dist/TxSubscriptionRef.d.ts +1 -1
- package/dist/TxSubscriptionRef.d.ts.map +1 -1
- package/dist/TxSubscriptionRef.js +1 -1
- package/dist/TxSubscriptionRef.js.map +1 -1
- package/dist/Types.d.ts +33 -19
- package/dist/Types.d.ts.map +1 -1
- package/dist/Utils.d.ts.map +1 -1
- package/dist/Utils.js +2 -1
- package/dist/Utils.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/internal/arbitrary/model.d.ts +2 -0
- package/dist/internal/arbitrary/model.d.ts.map +1 -0
- package/dist/internal/arbitrary/model.js +495 -0
- package/dist/internal/arbitrary/model.js.map +1 -0
- package/dist/internal/arbitrary/regexp.d.ts +2 -0
- package/dist/internal/arbitrary/regexp.d.ts.map +1 -0
- package/dist/internal/arbitrary/regexp.js +789 -0
- package/dist/internal/arbitrary/regexp.js.map +1 -0
- package/dist/internal/arbitrary/runner.d.ts +2 -0
- package/dist/internal/arbitrary/runner.d.ts.map +1 -0
- package/dist/internal/arbitrary/runner.js +496 -0
- package/dist/internal/arbitrary/runner.js.map +1 -0
- package/dist/internal/arbitrary/schema.d.ts.map +1 -0
- package/dist/internal/arbitrary/schema.js +1340 -0
- package/dist/internal/arbitrary/schema.js.map +1 -0
- package/dist/internal/core.js +27 -13
- package/dist/internal/core.js.map +1 -1
- package/dist/internal/count.d.ts +2 -0
- package/dist/internal/count.d.ts.map +1 -0
- package/dist/internal/count.js +14 -0
- package/dist/internal/count.js.map +1 -0
- package/dist/internal/dateTime.js +4 -10
- package/dist/internal/dateTime.js.map +1 -1
- package/dist/internal/effect.js +386 -251
- package/dist/internal/effect.js.map +1 -1
- package/dist/internal/graph.js +3 -1
- package/dist/internal/graph.js.map +1 -1
- package/dist/internal/hashMap.js +5 -3
- package/dist/internal/hashMap.js.map +1 -1
- package/dist/internal/hashSet.js +1 -1
- package/dist/internal/hashSet.js.map +1 -1
- package/dist/internal/matcher.js +1 -1
- package/dist/internal/matcher.js.map +1 -1
- package/dist/internal/metric.js +1 -1
- package/dist/internal/metric.js.map +1 -1
- package/dist/internal/option.js +6 -5
- package/dist/internal/option.js.map +1 -1
- package/dist/internal/random.js +17 -0
- package/dist/internal/random.js.map +1 -1
- package/dist/internal/rcRef.js +10 -7
- package/dist/internal/rcRef.js.map +1 -1
- package/dist/internal/references.js +1 -0
- package/dist/internal/references.js.map +1 -1
- package/dist/internal/request.js +13 -6
- package/dist/internal/request.js.map +1 -1
- package/dist/internal/result.js +11 -9
- package/dist/internal/result.js.map +1 -1
- package/dist/internal/schema/annotations.js +1 -1
- package/dist/internal/schema/annotations.js.map +1 -1
- package/dist/internal/schema/fromJsonSchemaDocument.js +14 -12
- package/dist/internal/schema/fromJsonSchemaDocument.js.map +1 -1
- package/dist/internal/schema/fromRepresentation.js +5 -5
- package/dist/internal/schema/fromRepresentation.js.map +1 -1
- package/dist/internal/schema/make.d.ts +2 -0
- package/dist/internal/schema/make.d.ts.map +1 -0
- package/dist/internal/schema/{schema.js → make.js} +1 -25
- package/dist/internal/schema/make.js.map +1 -0
- package/dist/internal/schema/parser.d.ts +0 -12
- package/dist/internal/schema/parser.d.ts.map +1 -1
- package/dist/internal/schema/parser.js +7 -0
- package/dist/internal/schema/parser.js.map +1 -1
- package/dist/internal/schema/standardSchema.d.ts +2 -0
- package/dist/internal/schema/standardSchema.d.ts.map +1 -0
- package/dist/internal/schema/standardSchema.js +112 -0
- package/dist/internal/schema/standardSchema.js.map +1 -0
- package/dist/internal/schema/toCodeDocument.js +34 -22
- package/dist/internal/schema/toCodeDocument.js.map +1 -1
- package/dist/internal/schema/toCodec.d.ts +2 -0
- package/dist/internal/schema/toCodec.d.ts.map +1 -0
- package/dist/internal/schema/toCodec.js +242 -0
- package/dist/internal/schema/toCodec.js.map +1 -0
- package/dist/internal/schema/toDifferJsonPatch.d.ts +2 -0
- package/dist/internal/schema/toDifferJsonPatch.d.ts.map +1 -0
- package/dist/internal/schema/toDifferJsonPatch.js +20 -0
- package/dist/internal/schema/toDifferJsonPatch.js.map +1 -0
- package/dist/internal/schema/toEncoderXml.d.ts +2 -0
- package/dist/internal/schema/toEncoderXml.d.ts.map +1 -0
- package/dist/internal/schema/toEncoderXml.js +104 -0
- package/dist/internal/schema/toEncoderXml.js.map +1 -0
- package/dist/internal/schema/toEquivalence.js +66 -0
- package/dist/internal/schema/toEquivalence.js.map +1 -1
- package/dist/internal/schema/toFormatter.d.ts +2 -0
- package/dist/internal/schema/toFormatter.d.ts.map +1 -0
- package/dist/internal/schema/toFormatter.js +227 -0
- package/dist/internal/schema/toFormatter.js.map +1 -0
- package/dist/internal/schema/toIso.d.ts +2 -0
- package/dist/internal/schema/toIso.d.ts.map +1 -0
- package/dist/internal/schema/toIso.js +17 -0
- package/dist/internal/schema/toIso.js.map +1 -0
- package/dist/internal/schema/toJsonSchemaDocument.js +122 -71
- package/dist/internal/schema/toJsonSchemaDocument.js.map +1 -1
- package/dist/internal/schema/toRepresentation.js +3 -1
- package/dist/internal/schema/toRepresentation.js.map +1 -1
- package/dist/internal/schemaError.d.ts +4 -0
- package/dist/internal/schemaError.d.ts.map +1 -0
- package/dist/internal/schemaError.js +6 -0
- package/dist/internal/schemaError.js.map +1 -0
- package/dist/internal/stream.js +5 -6
- package/dist/internal/stream.js.map +1 -1
- package/dist/internal/tracer.d.ts +1 -3
- package/dist/internal/tracer.d.ts.map +1 -1
- package/dist/internal/tracer.js +6 -0
- package/dist/internal/tracer.js.map +1 -1
- package/dist/internal/trie.js +2 -2
- package/dist/internal/trie.js.map +1 -1
- package/dist/internal/uuid.d.ts +1 -2
- package/dist/internal/uuid.d.ts.map +1 -1
- package/dist/internal/uuid.js +2 -0
- package/dist/internal/uuid.js.map +1 -1
- package/dist/testing/TestSchema.d.ts +9 -11
- package/dist/testing/TestSchema.d.ts.map +1 -1
- package/dist/testing/TestSchema.js +20 -18
- package/dist/testing/TestSchema.js.map +1 -1
- package/dist/testing/index.d.ts +0 -4
- package/dist/testing/index.d.ts.map +1 -1
- package/dist/testing/index.js +0 -4
- package/dist/testing/index.js.map +1 -1
- package/dist/unstable/ai/AiError.d.ts +74 -23
- package/dist/unstable/ai/AiError.d.ts.map +1 -1
- package/dist/unstable/ai/AiError.js +59 -5
- package/dist/unstable/ai/AiError.js.map +1 -1
- package/dist/unstable/ai/AnthropicStructuredOutput.d.ts.map +1 -1
- package/dist/unstable/ai/AnthropicStructuredOutput.js +2 -1
- package/dist/unstable/ai/AnthropicStructuredOutput.js.map +1 -1
- package/dist/unstable/ai/Chat.d.ts +27 -32
- package/dist/unstable/ai/Chat.d.ts.map +1 -1
- package/dist/unstable/ai/Chat.js +10 -13
- package/dist/unstable/ai/Chat.js.map +1 -1
- package/dist/unstable/ai/EmbeddingModel.d.ts +23 -16
- package/dist/unstable/ai/EmbeddingModel.d.ts.map +1 -1
- package/dist/unstable/ai/EmbeddingModel.js +13 -11
- package/dist/unstable/ai/EmbeddingModel.js.map +1 -1
- package/dist/unstable/ai/LanguageModel.d.ts +48 -37
- package/dist/unstable/ai/LanguageModel.d.ts.map +1 -1
- package/dist/unstable/ai/LanguageModel.js +150 -47
- package/dist/unstable/ai/LanguageModel.js.map +1 -1
- package/dist/unstable/ai/McpServer.d.ts +2 -2
- package/dist/unstable/ai/McpServer.d.ts.map +1 -1
- package/dist/unstable/ai/McpServer.js +21 -12
- package/dist/unstable/ai/McpServer.js.map +1 -1
- package/dist/unstable/ai/OpenAiStructuredOutput.d.ts.map +1 -1
- package/dist/unstable/ai/OpenAiStructuredOutput.js +2 -1
- package/dist/unstable/ai/OpenAiStructuredOutput.js.map +1 -1
- package/dist/unstable/ai/Prompt.d.ts +1 -1
- package/dist/unstable/ai/Prompt.d.ts.map +1 -1
- package/dist/unstable/ai/Prompt.js +15 -4
- package/dist/unstable/ai/Prompt.js.map +1 -1
- package/dist/unstable/ai/Response.d.ts +37 -94
- package/dist/unstable/ai/Response.d.ts.map +1 -1
- package/dist/unstable/ai/Response.js +46 -96
- package/dist/unstable/ai/Response.js.map +1 -1
- package/dist/unstable/ai/Tokenizer.js +4 -5
- package/dist/unstable/ai/Tokenizer.js.map +1 -1
- package/dist/unstable/ai/Tool.d.ts +38 -20
- package/dist/unstable/ai/Tool.d.ts.map +1 -1
- package/dist/unstable/ai/Tool.js +27 -1
- package/dist/unstable/ai/Tool.js.map +1 -1
- package/dist/unstable/ai/Toolkit.d.ts +1 -1
- package/dist/unstable/ai/Toolkit.d.ts.map +1 -1
- package/dist/unstable/ai/Toolkit.js +30 -18
- package/dist/unstable/ai/Toolkit.js.map +1 -1
- package/dist/unstable/ai/internal/structured-output.js +8 -5
- package/dist/unstable/ai/internal/structured-output.js.map +1 -1
- package/dist/unstable/arbitrary/Arbitrary.d.ts +626 -0
- package/dist/unstable/arbitrary/Arbitrary.d.ts.map +1 -0
- package/dist/unstable/arbitrary/Arbitrary.js +238 -0
- package/dist/unstable/arbitrary/Arbitrary.js.map +1 -0
- package/dist/unstable/arbitrary/index.d.ts +8 -0
- package/dist/unstable/arbitrary/index.d.ts.map +1 -0
- package/dist/unstable/arbitrary/index.js +9 -0
- package/dist/unstable/arbitrary/index.js.map +1 -0
- package/dist/unstable/cli/Argument.d.ts +104 -108
- package/dist/unstable/cli/Argument.d.ts.map +1 -1
- package/dist/unstable/cli/Argument.js +56 -57
- package/dist/unstable/cli/Argument.js.map +1 -1
- package/dist/unstable/cli/CliError.d.ts +2 -0
- package/dist/unstable/cli/CliError.d.ts.map +1 -1
- package/dist/unstable/cli/CliError.js +2 -0
- package/dist/unstable/cli/CliError.js.map +1 -1
- package/dist/unstable/cli/CliOutput.js +26 -3
- package/dist/unstable/cli/CliOutput.js.map +1 -1
- package/dist/unstable/cli/Command.d.ts +73 -73
- package/dist/unstable/cli/Command.js +18 -18
- package/dist/unstable/cli/Completions.d.ts +4 -4
- package/dist/unstable/cli/Completions.d.ts.map +1 -1
- package/dist/unstable/cli/Flag.d.ts +150 -161
- package/dist/unstable/cli/Flag.d.ts.map +1 -1
- package/dist/unstable/cli/Flag.js +79 -90
- package/dist/unstable/cli/Flag.js.map +1 -1
- package/dist/unstable/cli/GlobalFlag.d.ts +3 -3
- package/dist/unstable/cli/GlobalFlag.js +13 -13
- package/dist/unstable/cli/GlobalFlag.js.map +1 -1
- package/dist/unstable/cli/Param.d.ts +118 -126
- package/dist/unstable/cli/Param.d.ts.map +1 -1
- package/dist/unstable/cli/Param.js +104 -113
- package/dist/unstable/cli/Param.js.map +1 -1
- package/dist/unstable/cli/Primitive.d.ts +69 -58
- package/dist/unstable/cli/Primitive.d.ts.map +1 -1
- package/dist/unstable/cli/Primitive.js +65 -66
- package/dist/unstable/cli/Primitive.js.map +1 -1
- package/dist/unstable/cli/Prompt.d.ts +23 -24
- package/dist/unstable/cli/Prompt.d.ts.map +1 -1
- package/dist/unstable/cli/Prompt.js +68 -63
- package/dist/unstable/cli/Prompt.js.map +1 -1
- package/dist/unstable/cli/internal/completions/descriptor.js +23 -11
- package/dist/unstable/cli/internal/completions/descriptor.js.map +1 -1
- package/dist/unstable/cli/internal/completions/zsh.js +2 -2
- package/dist/unstable/cli/internal/completions/zsh.js.map +1 -1
- package/dist/unstable/cli/internal/config.js +4 -4
- package/dist/unstable/cli/internal/parser.js +1 -1
- package/dist/unstable/cli/internal/parser.js.map +1 -1
- package/dist/unstable/cli/internal/wizard.d.ts.map +1 -1
- package/dist/unstable/cli/internal/wizard.js +14 -13
- package/dist/unstable/cli/internal/wizard.js.map +1 -1
- package/dist/unstable/cluster/ClusterSchema.d.ts +13 -0
- package/dist/unstable/cluster/ClusterSchema.d.ts.map +1 -1
- package/dist/unstable/cluster/ClusterSchema.js +16 -1
- package/dist/unstable/cluster/ClusterSchema.js.map +1 -1
- package/dist/unstable/cluster/ClusterWorkflowEngine.d.ts.map +1 -1
- package/dist/unstable/cluster/ClusterWorkflowEngine.js +57 -14
- package/dist/unstable/cluster/ClusterWorkflowEngine.js.map +1 -1
- package/dist/unstable/cluster/Entity.d.ts.map +1 -1
- package/dist/unstable/cluster/Entity.js +2 -0
- package/dist/unstable/cluster/Entity.js.map +1 -1
- package/dist/unstable/cluster/EntityProxyServer.d.ts +2 -2
- package/dist/unstable/cluster/EntityProxyServer.d.ts.map +1 -1
- package/dist/unstable/cluster/EntityProxyServer.js.map +1 -1
- package/dist/unstable/cluster/Envelope.d.ts +4 -4
- package/dist/unstable/cluster/Envelope.d.ts.map +1 -1
- package/dist/unstable/cluster/Envelope.js +2 -3
- package/dist/unstable/cluster/Envelope.js.map +1 -1
- package/dist/unstable/cluster/HttpRunner.d.ts.map +1 -1
- package/dist/unstable/cluster/HttpRunner.js +5 -2
- package/dist/unstable/cluster/HttpRunner.js.map +1 -1
- package/dist/unstable/cluster/MessageStorage.d.ts +34 -4
- package/dist/unstable/cluster/MessageStorage.d.ts.map +1 -1
- package/dist/unstable/cluster/MessageStorage.js +28 -9
- package/dist/unstable/cluster/MessageStorage.js.map +1 -1
- package/dist/unstable/cluster/Reply.d.ts +1 -1
- package/dist/unstable/cluster/Sharding.d.ts +1 -1
- package/dist/unstable/cluster/Sharding.d.ts.map +1 -1
- package/dist/unstable/cluster/Sharding.js +32 -17
- package/dist/unstable/cluster/Sharding.js.map +1 -1
- package/dist/unstable/cluster/ShardingConfig.js +23 -23
- package/dist/unstable/cluster/ShardingConfig.js.map +1 -1
- package/dist/unstable/cluster/SocketRunner.d.ts +2 -2
- package/dist/unstable/cluster/SocketRunner.d.ts.map +1 -1
- package/dist/unstable/cluster/SocketRunner.js +4 -3
- package/dist/unstable/cluster/SocketRunner.js.map +1 -1
- package/dist/unstable/cluster/SqlMessageStorage.js +11 -8
- package/dist/unstable/cluster/SqlMessageStorage.js.map +1 -1
- package/dist/unstable/cluster/SqlRunnerStorage.d.ts.map +1 -1
- package/dist/unstable/cluster/SqlRunnerStorage.js +11 -4
- package/dist/unstable/cluster/SqlRunnerStorage.js.map +1 -1
- package/dist/unstable/cluster/internal/clusterAbandon.d.ts +5 -0
- package/dist/unstable/cluster/internal/clusterAbandon.d.ts.map +1 -0
- package/dist/unstable/cluster/internal/clusterAbandon.js +9 -0
- package/dist/unstable/cluster/internal/clusterAbandon.js.map +1 -0
- package/dist/unstable/cluster/internal/entityManager.js +7 -4
- package/dist/unstable/cluster/internal/entityManager.js.map +1 -1
- package/dist/unstable/cluster/internal/interruptors.js +30 -1
- package/dist/unstable/cluster/internal/interruptors.js.map +1 -1
- package/dist/unstable/cluster/internal/resourceRef.js +12 -7
- package/dist/unstable/cluster/internal/resourceRef.js.map +1 -1
- package/dist/unstable/devtools/DevToolsClient.d.ts.map +1 -1
- package/dist/unstable/devtools/DevToolsClient.js +12 -7
- package/dist/unstable/devtools/DevToolsClient.js.map +1 -1
- package/dist/unstable/encoding/Ini.d.ts +2 -0
- package/dist/unstable/encoding/Ini.d.ts.map +1 -1
- package/dist/unstable/encoding/Ini.js +2 -0
- package/dist/unstable/encoding/Ini.js.map +1 -1
- package/dist/unstable/encoding/SchemaBinary.d.ts +27 -3
- package/dist/unstable/encoding/SchemaBinary.d.ts.map +1 -1
- package/dist/unstable/encoding/SchemaBinary.js +108 -39
- package/dist/unstable/encoding/SchemaBinary.js.map +1 -1
- package/dist/unstable/encoding/Sse.js +1 -1
- package/dist/unstable/encoding/Sse.js.map +1 -1
- package/dist/unstable/encoding/Toml.d.ts +2 -0
- package/dist/unstable/encoding/Toml.d.ts.map +1 -1
- package/dist/unstable/encoding/Toml.js +6 -4
- package/dist/unstable/encoding/Toml.js.map +1 -1
- package/dist/unstable/encoding/Yaml.d.ts +2 -0
- package/dist/unstable/encoding/Yaml.d.ts.map +1 -1
- package/dist/unstable/encoding/Yaml.js +16 -5
- package/dist/unstable/encoding/Yaml.js.map +1 -1
- package/dist/unstable/encoding/index.d.ts +0 -4
- package/dist/unstable/encoding/index.d.ts.map +1 -1
- package/dist/unstable/encoding/index.js +0 -4
- package/dist/unstable/encoding/index.js.map +1 -1
- package/dist/unstable/eventlog/Event.d.ts +5 -5
- package/dist/unstable/eventlog/Event.d.ts.map +1 -1
- package/dist/unstable/eventlog/Event.js +3 -3
- package/dist/unstable/eventlog/Event.js.map +1 -1
- package/dist/unstable/eventlog/EventJournal.d.ts +7 -7
- package/dist/unstable/eventlog/EventJournal.d.ts.map +1 -1
- package/dist/unstable/eventlog/EventJournal.js +9 -9
- package/dist/unstable/eventlog/EventJournal.js.map +1 -1
- package/dist/unstable/eventlog/EventLog.d.ts +1 -1
- package/dist/unstable/eventlog/EventLog.d.ts.map +1 -1
- package/dist/unstable/eventlog/EventLog.js +4 -4
- package/dist/unstable/eventlog/EventLog.js.map +1 -1
- package/dist/unstable/eventlog/EventLogMessage.d.ts +11 -5
- package/dist/unstable/eventlog/EventLogMessage.d.ts.map +1 -1
- package/dist/unstable/eventlog/EventLogMessage.js +25 -15
- package/dist/unstable/eventlog/EventLogMessage.js.map +1 -1
- package/dist/unstable/eventlog/EventLogRemote.d.ts +7 -1
- package/dist/unstable/eventlog/EventLogRemote.d.ts.map +1 -1
- package/dist/unstable/eventlog/EventLogRemote.js +13 -3
- package/dist/unstable/eventlog/EventLogRemote.js.map +1 -1
- package/dist/unstable/eventlog/EventLogServerUnencrypted.js +2 -2
- package/dist/unstable/eventlog/EventLogServerUnencrypted.js.map +1 -1
- package/dist/unstable/eventlog/SqlEventJournal.d.ts.map +1 -1
- package/dist/unstable/eventlog/SqlEventJournal.js +26 -13
- package/dist/unstable/eventlog/SqlEventJournal.js.map +1 -1
- package/dist/unstable/eventlog/SqlEventLogServerUnencrypted.d.ts.map +1 -1
- package/dist/unstable/eventlog/SqlEventLogServerUnencrypted.js +5 -1
- package/dist/unstable/eventlog/SqlEventLogServerUnencrypted.js.map +1 -1
- package/dist/unstable/http/Cookies.d.ts +1 -45
- package/dist/unstable/http/Cookies.d.ts.map +1 -1
- package/dist/unstable/http/Cookies.js +2 -64
- package/dist/unstable/http/Cookies.js.map +1 -1
- package/dist/unstable/http/FetchHttpClient.js +1 -1
- package/dist/unstable/http/FetchHttpClient.js.map +1 -1
- package/dist/unstable/http/FindMyWay/internal/router.js +124 -33
- package/dist/unstable/http/FindMyWay/internal/router.js.map +1 -1
- package/dist/unstable/http/FindMyWay.d.ts +15 -5
- package/dist/unstable/http/FindMyWay.d.ts.map +1 -1
- package/dist/unstable/http/FindMyWay.js +3 -1
- package/dist/unstable/http/FindMyWay.js.map +1 -1
- package/dist/unstable/http/Headers.d.ts +0 -22
- package/dist/unstable/http/Headers.d.ts.map +1 -1
- package/dist/unstable/http/Headers.js +3 -34
- package/dist/unstable/http/Headers.js.map +1 -1
- package/dist/unstable/http/HttpBody.d.ts +41 -10
- package/dist/unstable/http/HttpBody.d.ts.map +1 -1
- package/dist/unstable/http/HttpBody.js +64 -10
- package/dist/unstable/http/HttpBody.js.map +1 -1
- package/dist/unstable/http/HttpClient.d.ts +1 -1
- package/dist/unstable/http/HttpClient.d.ts.map +1 -1
- package/dist/unstable/http/HttpClient.js +28 -18
- package/dist/unstable/http/HttpClient.js.map +1 -1
- package/dist/unstable/http/HttpClientRequest.d.ts +28 -6
- package/dist/unstable/http/HttpClientRequest.d.ts.map +1 -1
- package/dist/unstable/http/HttpClientRequest.js +8 -19
- package/dist/unstable/http/HttpClientRequest.js.map +1 -1
- package/dist/unstable/http/HttpClientResponse.d.ts +6 -1
- package/dist/unstable/http/HttpClientResponse.d.ts.map +1 -1
- package/dist/unstable/http/HttpClientResponse.js +10 -6
- package/dist/unstable/http/HttpClientResponse.js.map +1 -1
- package/dist/unstable/http/HttpEffect.d.ts +16 -0
- package/dist/unstable/http/HttpEffect.d.ts.map +1 -1
- package/dist/unstable/http/HttpEffect.js +121 -65
- package/dist/unstable/http/HttpEffect.js.map +1 -1
- package/dist/unstable/http/HttpIncomingMessage.d.ts +3 -3
- package/dist/unstable/http/HttpIncomingMessage.d.ts.map +1 -1
- package/dist/unstable/http/HttpIncomingMessage.js +1 -13
- package/dist/unstable/http/HttpIncomingMessage.js.map +1 -1
- package/dist/unstable/http/HttpMiddleware.d.ts +1 -1
- package/dist/unstable/http/HttpMiddleware.d.ts.map +1 -1
- package/dist/unstable/http/HttpMiddleware.js +29 -21
- package/dist/unstable/http/HttpMiddleware.js.map +1 -1
- package/dist/unstable/http/HttpPlatform.d.ts +12 -11
- package/dist/unstable/http/HttpPlatform.d.ts.map +1 -1
- package/dist/unstable/http/HttpPlatform.js +36 -10
- package/dist/unstable/http/HttpPlatform.js.map +1 -1
- package/dist/unstable/http/HttpRouter.d.ts +5 -1
- package/dist/unstable/http/HttpRouter.d.ts.map +1 -1
- package/dist/unstable/http/HttpRouter.js +22 -8
- package/dist/unstable/http/HttpRouter.js.map +1 -1
- package/dist/unstable/http/HttpServer.d.ts +11 -42
- package/dist/unstable/http/HttpServer.d.ts.map +1 -1
- package/dist/unstable/http/HttpServer.js +16 -20
- package/dist/unstable/http/HttpServer.js.map +1 -1
- package/dist/unstable/http/HttpServerRequest.d.ts.map +1 -1
- package/dist/unstable/http/HttpServerRequest.js +11 -11
- package/dist/unstable/http/HttpServerRequest.js.map +1 -1
- package/dist/unstable/http/HttpServerRespondable.js +1 -1
- package/dist/unstable/http/HttpServerRespondable.js.map +1 -1
- package/dist/unstable/http/HttpServerResponse.d.ts +9 -13
- package/dist/unstable/http/HttpServerResponse.d.ts.map +1 -1
- package/dist/unstable/http/HttpServerResponse.js +34 -44
- package/dist/unstable/http/HttpServerResponse.js.map +1 -1
- package/dist/unstable/http/HttpStaticServer.d.ts +2 -2
- package/dist/unstable/http/HttpStaticServer.d.ts.map +1 -1
- package/dist/unstable/http/HttpStaticServer.js +19 -19
- package/dist/unstable/http/HttpStaticServer.js.map +1 -1
- package/dist/unstable/http/Mime.d.ts +28 -0
- package/dist/unstable/http/Mime.d.ts.map +1 -0
- package/dist/unstable/http/Mime.js +72 -0
- package/dist/unstable/http/Mime.js.map +1 -0
- package/dist/unstable/http/Multipart.d.ts +22 -9
- package/dist/unstable/http/Multipart.d.ts.map +1 -1
- package/dist/unstable/http/Multipart.js +26 -10
- package/dist/unstable/http/Multipart.js.map +1 -1
- package/dist/unstable/http/MultipartParser/internal/multipart.d.ts +1 -1
- package/dist/unstable/http/MultipartParser/internal/multipart.d.ts.map +1 -1
- package/dist/unstable/http/MultipartParser/internal/multipart.js +8 -3
- package/dist/unstable/http/MultipartParser/internal/multipart.js.map +1 -1
- package/dist/unstable/http/MultipartParser.d.ts +4 -3
- package/dist/unstable/http/MultipartParser.d.ts.map +1 -1
- package/dist/unstable/http/MultipartParser.js.map +1 -1
- package/dist/unstable/http/UrlParams.d.ts +0 -97
- package/dist/unstable/http/UrlParams.d.ts.map +1 -1
- package/dist/unstable/http/UrlParams.js +3 -104
- package/dist/unstable/http/UrlParams.js.map +1 -1
- package/dist/unstable/http/index.d.ts +4 -0
- package/dist/unstable/http/index.d.ts.map +1 -1
- package/dist/unstable/http/index.js +4 -0
- package/dist/unstable/http/index.js.map +1 -1
- package/dist/unstable/http/internal/compression.js +8 -11
- package/dist/unstable/http/internal/compression.js.map +1 -1
- package/dist/unstable/http/internal/headers.d.ts +2 -0
- package/dist/unstable/http/internal/headers.d.ts.map +1 -0
- package/dist/unstable/http/internal/headers.js +5 -0
- package/dist/unstable/http/internal/headers.js.map +1 -0
- package/dist/unstable/http/internal/httpBody.js +8 -0
- package/dist/unstable/http/internal/httpBody.js.map +1 -1
- package/dist/unstable/http/internal/mimeTypes.d.ts +361 -0
- package/dist/unstable/http/internal/mimeTypes.d.ts.map +1 -0
- package/dist/unstable/http/internal/mimeTypes.js +363 -0
- package/dist/unstable/http/internal/mimeTypes.js.map +1 -0
- package/dist/unstable/httpapi/HttpApiBuilder.d.ts +13 -0
- package/dist/unstable/httpapi/HttpApiBuilder.d.ts.map +1 -1
- package/dist/unstable/httpapi/HttpApiBuilder.js +23 -6
- package/dist/unstable/httpapi/HttpApiBuilder.js.map +1 -1
- package/dist/unstable/httpapi/HttpApiClient.d.ts +4 -3
- package/dist/unstable/httpapi/HttpApiClient.d.ts.map +1 -1
- package/dist/unstable/httpapi/HttpApiClient.js +25 -13
- package/dist/unstable/httpapi/HttpApiClient.js.map +1 -1
- package/dist/unstable/httpapi/HttpApiEndpoint.d.ts +8 -3
- package/dist/unstable/httpapi/HttpApiEndpoint.d.ts.map +1 -1
- package/dist/unstable/httpapi/HttpApiEndpoint.js +9 -6
- package/dist/unstable/httpapi/HttpApiEndpoint.js.map +1 -1
- package/dist/unstable/httpapi/HttpApiError.d.ts.map +1 -1
- package/dist/unstable/httpapi/HttpApiError.js +3 -1
- package/dist/unstable/httpapi/HttpApiError.js.map +1 -1
- package/dist/unstable/httpapi/HttpApiMiddleware.d.ts.map +1 -1
- package/dist/unstable/httpapi/HttpApiMiddleware.js +7 -5
- package/dist/unstable/httpapi/HttpApiMiddleware.js.map +1 -1
- package/dist/unstable/httpapi/HttpApiSchema.d.ts +12 -0
- package/dist/unstable/httpapi/HttpApiSchema.d.ts.map +1 -1
- package/dist/unstable/httpapi/HttpApiSchema.js +8 -10
- package/dist/unstable/httpapi/HttpApiSchema.js.map +1 -1
- package/dist/unstable/httpapi/HttpApiTest.d.ts.map +1 -1
- package/dist/unstable/httpapi/HttpApiTest.js +8 -2
- package/dist/unstable/httpapi/HttpApiTest.js.map +1 -1
- package/dist/unstable/httpapi/OpenApi.d.ts.map +1 -1
- package/dist/unstable/httpapi/OpenApi.js +31 -20
- package/dist/unstable/httpapi/OpenApi.js.map +1 -1
- package/dist/unstable/net/IpInterface.d.ts +140 -0
- package/dist/unstable/net/IpInterface.d.ts.map +1 -0
- package/dist/unstable/net/IpInterface.js +149 -0
- package/dist/unstable/net/IpInterface.js.map +1 -0
- package/dist/unstable/net/IpNetwork.d.ts +227 -0
- package/dist/unstable/net/IpNetwork.d.ts.map +1 -0
- package/dist/unstable/net/IpNetwork.js +239 -0
- package/dist/unstable/net/IpNetwork.js.map +1 -0
- package/dist/unstable/net/NetAddress.d.ts +705 -0
- package/dist/unstable/net/NetAddress.d.ts.map +1 -0
- package/dist/unstable/net/NetAddress.js +956 -0
- package/dist/unstable/net/NetAddress.js.map +1 -0
- package/dist/unstable/net/index.d.ts +16 -0
- package/dist/unstable/net/index.d.ts.map +1 -0
- package/dist/unstable/net/index.js +17 -0
- package/dist/unstable/net/index.js.map +1 -0
- package/dist/unstable/observability/OtlpExporter.d.ts +1 -0
- package/dist/unstable/observability/OtlpExporter.d.ts.map +1 -1
- package/dist/unstable/observability/OtlpExporter.js +4 -6
- package/dist/unstable/observability/OtlpExporter.js.map +1 -1
- package/dist/unstable/observability/OtlpLogger.js +9 -9
- package/dist/unstable/observability/OtlpLogger.js.map +1 -1
- package/dist/unstable/observability/OtlpMetrics.d.ts.map +1 -1
- package/dist/unstable/observability/OtlpMetrics.js +9 -8
- package/dist/unstable/observability/OtlpMetrics.js.map +1 -1
- package/dist/unstable/observability/OtlpResource.d.ts.map +1 -1
- package/dist/unstable/observability/OtlpResource.js +2 -2
- package/dist/unstable/observability/OtlpResource.js.map +1 -1
- package/dist/unstable/observability/OtlpTracer.d.ts.map +1 -1
- package/dist/unstable/observability/OtlpTracer.js +82 -55
- package/dist/unstable/observability/OtlpTracer.js.map +1 -1
- package/dist/unstable/observability/internal/otlpEnv.d.ts +1 -1
- package/dist/unstable/observability/internal/otlpEnv.d.ts.map +1 -1
- package/dist/unstable/observability/internal/otlpEnv.js +5 -9
- package/dist/unstable/observability/internal/otlpEnv.js.map +1 -1
- package/dist/unstable/persistence/PersistedCache.js +1 -1
- package/dist/unstable/persistence/PersistedCache.js.map +1 -1
- package/dist/unstable/persistence/PersistedQueue.d.ts +114 -14
- package/dist/unstable/persistence/PersistedQueue.d.ts.map +1 -1
- package/dist/unstable/persistence/PersistedQueue.js +799 -234
- package/dist/unstable/persistence/PersistedQueue.js.map +1 -1
- package/dist/unstable/persistence/RateLimiter.d.ts +28 -15
- package/dist/unstable/persistence/RateLimiter.d.ts.map +1 -1
- package/dist/unstable/persistence/RateLimiter.js +33 -41
- package/dist/unstable/persistence/RateLimiter.js.map +1 -1
- package/dist/unstable/process/ChildProcess.d.ts +8 -2
- package/dist/unstable/process/ChildProcess.d.ts.map +1 -1
- package/dist/unstable/process/ChildProcess.js +7 -2
- package/dist/unstable/process/ChildProcess.js.map +1 -1
- package/dist/unstable/process/ChildProcessSpawner.d.ts +1 -1
- package/dist/unstable/process/ChildProcessSpawner.d.ts.map +1 -1
- package/dist/unstable/process/ChildProcessSpawner.js +1 -1
- package/dist/unstable/process/ChildProcessSpawner.js.map +1 -1
- package/dist/unstable/reactivity/Atom.d.ts.map +1 -1
- package/dist/unstable/reactivity/Atom.js +6 -3
- package/dist/unstable/reactivity/Atom.js.map +1 -1
- package/dist/unstable/reactivity/AtomHttpApi.d.ts +3 -6
- package/dist/unstable/reactivity/AtomHttpApi.d.ts.map +1 -1
- package/dist/unstable/reactivity/AtomHttpApi.js +6 -3
- package/dist/unstable/reactivity/AtomHttpApi.js.map +1 -1
- package/dist/unstable/reactivity/AtomRegistry.js +2 -3
- package/dist/unstable/reactivity/AtomRegistry.js.map +1 -1
- package/dist/unstable/reactivity/AtomRpc.d.ts +2 -2
- package/dist/unstable/reactivity/AtomRpc.d.ts.map +1 -1
- package/dist/unstable/reactivity/AtomRpc.js +1 -1
- package/dist/unstable/reactivity/AtomRpc.js.map +1 -1
- package/dist/unstable/reactivity/Hydration.d.ts +6 -4
- package/dist/unstable/reactivity/Hydration.d.ts.map +1 -1
- package/dist/unstable/reactivity/Hydration.js +20 -6
- package/dist/unstable/reactivity/Hydration.js.map +1 -1
- package/dist/unstable/reactivity/Reactivity.d.ts +26 -26
- package/dist/unstable/reactivity/Reactivity.d.ts.map +1 -1
- package/dist/unstable/reactivity/Reactivity.js +10 -12
- package/dist/unstable/reactivity/Reactivity.js.map +1 -1
- package/dist/unstable/rpc/RpcClient.d.ts.map +1 -1
- package/dist/unstable/rpc/RpcClient.js +64 -64
- package/dist/unstable/rpc/RpcClient.js.map +1 -1
- package/dist/unstable/rpc/RpcClientError.d.ts +1 -1
- package/dist/unstable/rpc/RpcMessage.d.ts +3 -1
- package/dist/unstable/rpc/RpcMessage.d.ts.map +1 -1
- package/dist/unstable/rpc/RpcMessage.js +1 -1
- package/dist/unstable/rpc/RpcMessage.js.map +1 -1
- package/dist/unstable/rpc/RpcMiddleware.d.ts.map +1 -1
- package/dist/unstable/rpc/RpcMiddleware.js +7 -5
- package/dist/unstable/rpc/RpcMiddleware.js.map +1 -1
- package/dist/unstable/rpc/RpcSerialization.d.ts +5 -39
- package/dist/unstable/rpc/RpcSerialization.d.ts.map +1 -1
- package/dist/unstable/rpc/RpcSerialization.js +22 -115
- package/dist/unstable/rpc/RpcSerialization.js.map +1 -1
- package/dist/unstable/rpc/RpcServer.d.ts.map +1 -1
- package/dist/unstable/rpc/RpcServer.js +104 -57
- package/dist/unstable/rpc/RpcServer.js.map +1 -1
- package/dist/unstable/schema/Model.d.ts.map +1 -1
- package/dist/unstable/schema/Model.js +7 -6
- package/dist/unstable/schema/Model.js.map +1 -1
- package/dist/unstable/schema/VariantSchema.d.ts.map +1 -1
- package/dist/unstable/schema/VariantSchema.js +3 -0
- package/dist/unstable/schema/VariantSchema.js.map +1 -1
- package/dist/unstable/socket/Socket.d.ts +287 -102
- package/dist/unstable/socket/Socket.d.ts.map +1 -1
- package/dist/unstable/socket/Socket.js +408 -215
- package/dist/unstable/socket/Socket.js.map +1 -1
- package/dist/unstable/socket/SocketServer.d.ts +5 -32
- package/dist/unstable/socket/SocketServer.d.ts.map +1 -1
- package/dist/unstable/socket/SocketServer.js +3 -3
- package/dist/unstable/socket/SocketServer.js.map +1 -1
- package/dist/unstable/sql/SqlClient.d.ts +20 -0
- package/dist/unstable/sql/SqlClient.d.ts.map +1 -1
- package/dist/unstable/sql/SqlClient.js +14 -7
- package/dist/unstable/sql/SqlClient.js.map +1 -1
- package/dist/unstable/sql/SqlConnection.d.ts +15 -0
- package/dist/unstable/sql/SqlConnection.d.ts.map +1 -1
- package/dist/unstable/sql/SqlConnection.js.map +1 -1
- package/dist/unstable/sql/SqlModel.d.ts +1 -1
- package/dist/unstable/sql/SqlModel.d.ts.map +1 -1
- package/dist/unstable/sql/Statement.d.ts +13 -5
- package/dist/unstable/sql/Statement.d.ts.map +1 -1
- package/dist/unstable/sql/Statement.js +29 -15
- package/dist/unstable/sql/Statement.js.map +1 -1
- package/dist/unstable/workers/Transferable.js +1 -1
- package/dist/unstable/workers/Worker.d.ts.map +1 -1
- package/dist/unstable/workers/Worker.js +3 -1
- package/dist/unstable/workers/Worker.js.map +1 -1
- package/dist/unstable/workflow/Activity.d.ts +7 -0
- package/dist/unstable/workflow/Activity.d.ts.map +1 -1
- package/dist/unstable/workflow/Activity.js +14 -4
- package/dist/unstable/workflow/Activity.js.map +1 -1
- package/dist/unstable/workflow/DurableClock.js +1 -1
- package/dist/unstable/workflow/DurableClock.js.map +1 -1
- package/dist/unstable/workflow/DurableDeferred.d.ts +2 -2
- package/dist/unstable/workflow/DurableDeferred.d.ts.map +1 -1
- package/dist/unstable/workflow/DurableDeferred.js.map +1 -1
- package/dist/unstable/workflow/DurableQueue.d.ts +8 -0
- package/dist/unstable/workflow/DurableQueue.d.ts.map +1 -1
- package/dist/unstable/workflow/DurableQueue.js +8 -0
- package/dist/unstable/workflow/DurableQueue.js.map +1 -1
- package/dist/unstable/workflow/Workflow.d.ts +5 -0
- package/dist/unstable/workflow/Workflow.d.ts.map +1 -1
- package/dist/unstable/workflow/Workflow.js +70 -12
- package/dist/unstable/workflow/Workflow.js.map +1 -1
- package/dist/unstable/workflow/WorkflowEngine.d.ts +6 -0
- package/dist/unstable/workflow/WorkflowEngine.d.ts.map +1 -1
- package/dist/unstable/workflow/WorkflowEngine.js +11 -0
- package/dist/unstable/workflow/WorkflowEngine.js.map +1 -1
- package/package.json +7 -9
- package/src/Array.ts +118 -67
- package/src/BigDecimal.ts +50 -28
- package/src/ByteSize.ts +838 -0
- package/src/Cache.ts +17 -3
- package/src/Cause.ts +1 -1
- package/src/Channel.ts +183 -48
- package/src/Chunk.ts +65 -36
- package/src/Config.ts +237 -248
- package/src/ConfigProvider.ts +7 -8
- package/src/Context.ts +31 -0
- package/src/Cron.ts +2 -2
- package/src/Crypto.ts +3 -2
- package/src/Deferred.ts +7 -6
- package/src/Duration.ts +1 -1
- package/src/Effect.ts +226 -122
- package/src/Effectable.ts +78 -9
- package/src/Encoding.ts +101 -11
- package/src/Equal.ts +1 -1
- package/src/ExecutionPlan.ts +3 -0
- package/src/Fiber.ts +33 -8
- package/src/FiberHandle.ts +3 -3
- package/src/FiberMap.ts +19 -10
- package/src/FileSystem.ts +55 -230
- package/src/Formatter.ts +21 -3
- package/src/Graph.ts +55 -25
- package/src/Hash.ts +5 -16
- package/src/HashRing.ts +9 -2
- package/src/HashSet.ts +56 -0
- package/src/Iterable.ts +66 -41
- package/src/JsonPatch.ts +4 -4
- package/src/JsonPointer.ts +97 -4
- package/src/JsonSchema.ts +8 -26
- package/src/Layer.ts +59 -18
- package/src/LayerMap.ts +8 -6
- package/src/LayerRef.ts +7 -5
- package/src/Logger.ts +125 -18
- package/src/ManagedRuntime.ts +1 -1
- package/src/Match.ts +33 -14
- package/src/Metric.ts +24 -21
- package/src/MutableHashMap.ts +1 -1
- package/src/MutableHashSet.ts +1 -1
- package/src/MutableList.ts +18 -2
- package/src/Number.ts +7 -1
- package/src/Optic.ts +8 -4
- package/src/Option.ts +1 -1
- package/src/Order.ts +3 -1
- package/src/PartitionedSemaphore.ts +1 -2
- package/src/Path.ts +1 -1
- package/src/PlatformError.ts +1 -1
- package/src/Pool.ts +125 -8
- package/src/PrimaryKey.ts +1 -1
- package/src/PubSub.ts +32 -20
- package/src/Queue.ts +119 -28
- package/src/Random.ts +20 -6
- package/src/RcMap.ts +20 -13
- package/src/Redacted.ts +1 -1
- package/src/RequestResolver.ts +49 -26
- package/src/Result.ts +1 -1
- package/src/Scheduler.ts +21 -11
- package/src/Schema.ts +4809 -6368
- package/src/SchemaAST.ts +1031 -284
- package/src/SchemaGetter.ts +75 -21
- package/src/SchemaIssue.ts +259 -15
- package/src/SchemaParser.ts +2 -12
- package/src/SchemaRepresentation.ts +1593 -29
- package/src/SchemaTransformation.ts +145 -22
- package/src/ScopedCache.ts +10 -3
- package/src/Sink.ts +31 -15
- package/src/Stream.ts +294 -76
- package/src/String.ts +20 -9
- package/src/Struct.ts +8 -4
- package/src/SynchronizedRef.ts +3 -5
- package/src/Terminal.ts +3 -3
- package/src/Tracer.ts +43 -14
- package/src/Tuple.ts +3 -1
- package/src/TxChunk.ts +1 -1
- package/src/TxDeferred.ts +1 -1
- package/src/TxHashMap.ts +1 -1
- package/src/TxHashSet.ts +92 -11
- package/src/TxPriorityQueue.ts +1 -1
- package/src/TxPubSub.ts +1 -1
- package/src/TxQueue.ts +22 -17
- package/src/TxReentrantLock.ts +29 -1
- package/src/TxRef.ts +1 -1
- package/src/TxSemaphore.ts +1 -1
- package/src/TxSubscriptionRef.ts +1 -1
- package/src/Types.ts +40 -17
- package/src/Utils.ts +3 -1
- package/src/index.ts +5 -0
- package/src/internal/arbitrary/model.ts +701 -0
- package/src/internal/arbitrary/regexp.ts +855 -0
- package/src/internal/arbitrary/runner.ts +608 -0
- package/src/internal/arbitrary/schema.ts +1800 -0
- package/src/internal/core.ts +48 -22
- package/src/internal/count.ts +14 -0
- package/src/internal/dateTime.ts +8 -10
- package/src/internal/effect.ts +475 -295
- package/src/internal/graph.ts +6 -1
- package/src/internal/hashMap.ts +5 -3
- package/src/internal/hashSet.ts +1 -1
- package/src/internal/matcher.ts +34 -19
- package/src/internal/metric.ts +1 -1
- package/src/internal/option.ts +8 -6
- package/src/internal/random.ts +20 -7
- package/src/internal/rcRef.ts +10 -7
- package/src/internal/references.ts +1 -0
- package/src/internal/request.ts +12 -7
- package/src/internal/result.ts +15 -11
- package/src/internal/schema/annotations.ts +3 -3
- package/src/internal/schema/fromJsonSchemaDocument.ts +14 -29
- package/src/internal/schema/fromRepresentation.ts +5 -3
- package/src/internal/schema/{schema.ts → make.ts} +0 -40
- package/src/internal/schema/parser.ts +8 -0
- package/src/internal/schema/standardSchema.ts +125 -0
- package/src/internal/schema/toCodeDocument.ts +58 -44
- package/src/internal/schema/toCodec.ts +312 -0
- package/src/internal/schema/toDifferJsonPatch.ts +24 -0
- package/src/internal/schema/toEncoderXml.ts +110 -0
- package/src/internal/schema/toEquivalence.ts +76 -0
- package/src/internal/schema/toFormatter.ts +230 -0
- package/src/internal/schema/toIso.ts +20 -0
- package/src/internal/schema/toJsonSchemaDocument.ts +125 -67
- package/src/internal/schema/toRepresentation.ts +1 -1
- package/src/internal/schemaError.ts +8 -0
- package/src/internal/stream.ts +14 -6
- package/src/internal/tracer.ts +4 -0
- package/src/internal/trie.ts +5 -2
- package/src/internal/uuid.ts +4 -0
- package/src/testing/TestSchema.ts +36 -30
- package/src/testing/index.ts +0 -5
- package/src/unstable/ai/AiError.ts +69 -5
- package/src/unstable/ai/AnthropicStructuredOutput.ts +4 -1
- package/src/unstable/ai/Chat.ts +35 -36
- package/src/unstable/ai/EmbeddingModel.ts +27 -15
- package/src/unstable/ai/LanguageModel.ts +283 -100
- package/src/unstable/ai/McpServer.ts +36 -20
- package/src/unstable/ai/OpenAiStructuredOutput.ts +4 -1
- package/src/unstable/ai/Prompt.ts +19 -4
- package/src/unstable/ai/Response.ts +107 -189
- package/src/unstable/ai/Tokenizer.ts +4 -5
- package/src/unstable/ai/Tool.ts +58 -35
- package/src/unstable/ai/Toolkit.ts +43 -37
- package/src/unstable/ai/internal/structured-output.ts +5 -5
- package/src/unstable/arbitrary/Arbitrary.ts +715 -0
- package/src/unstable/arbitrary/index.ts +10 -0
- package/src/unstable/cli/Argument.ts +111 -115
- package/src/unstable/cli/CliError.ts +2 -0
- package/src/unstable/cli/CliOutput.ts +40 -3
- package/src/unstable/cli/Command.ts +74 -74
- package/src/unstable/cli/Completions.ts +4 -4
- package/src/unstable/cli/Flag.ts +158 -169
- package/src/unstable/cli/GlobalFlag.ts +13 -13
- package/src/unstable/cli/Param.ts +150 -159
- package/src/unstable/cli/Primitive.ts +75 -76
- package/src/unstable/cli/Prompt.ts +88 -87
- package/src/unstable/cli/internal/completions/descriptor.ts +23 -11
- package/src/unstable/cli/internal/completions/zsh.ts +2 -2
- package/src/unstable/cli/internal/config.ts +4 -4
- package/src/unstable/cli/internal/parser.ts +1 -1
- package/src/unstable/cli/internal/wizard.ts +18 -13
- package/src/unstable/cluster/ClusterSchema.ts +19 -1
- package/src/unstable/cluster/ClusterWorkflowEngine.ts +66 -16
- package/src/unstable/cluster/Entity.ts +3 -0
- package/src/unstable/cluster/EntityProxyServer.ts +6 -2
- package/src/unstable/cluster/Envelope.ts +3 -3
- package/src/unstable/cluster/HttpRunner.ts +7 -2
- package/src/unstable/cluster/MessageStorage.ts +62 -21
- package/src/unstable/cluster/Reply.ts +2 -2
- package/src/unstable/cluster/Sharding.ts +44 -19
- package/src/unstable/cluster/ShardingConfig.ts +23 -23
- package/src/unstable/cluster/SocketRunner.ts +5 -4
- package/src/unstable/cluster/SqlMessageStorage.ts +12 -8
- package/src/unstable/cluster/SqlRunnerStorage.ts +18 -10
- package/src/unstable/cluster/internal/clusterAbandon.ts +14 -0
- package/src/unstable/cluster/internal/entityManager.ts +12 -4
- package/src/unstable/cluster/internal/interruptors.ts +58 -1
- package/src/unstable/cluster/internal/resourceRef.ts +15 -7
- package/src/unstable/devtools/DevToolsClient.ts +13 -3
- package/src/unstable/encoding/Ini.ts +2 -0
- package/src/unstable/encoding/SchemaBinary.ts +150 -44
- package/src/unstable/encoding/Sse.ts +1 -1
- package/src/unstable/encoding/Toml.ts +7 -5
- package/src/unstable/encoding/Yaml.ts +18 -5
- package/src/unstable/encoding/index.ts +0 -5
- package/src/unstable/eventlog/Event.ts +7 -7
- package/src/unstable/eventlog/EventJournal.ts +9 -9
- package/src/unstable/eventlog/EventLog.ts +5 -5
- package/src/unstable/eventlog/EventLogMessage.ts +25 -15
- package/src/unstable/eventlog/EventLogRemote.ts +15 -4
- package/src/unstable/eventlog/EventLogServerUnencrypted.ts +2 -2
- package/src/unstable/eventlog/SqlEventJournal.ts +32 -9
- package/src/unstable/eventlog/SqlEventLogServerUnencrypted.ts +11 -1
- package/src/unstable/http/Cookies.ts +2 -102
- package/src/unstable/http/FetchHttpClient.ts +1 -1
- package/src/unstable/http/FindMyWay/internal/router.ts +139 -33
- package/src/unstable/http/FindMyWay.ts +15 -5
- package/src/unstable/http/Headers.ts +3 -48
- package/src/unstable/http/HttpBody.ts +107 -36
- package/src/unstable/http/HttpClient.ts +41 -30
- package/src/unstable/http/HttpClientRequest.ts +32 -18
- package/src/unstable/http/HttpClientResponse.ts +16 -3
- package/src/unstable/http/HttpEffect.ts +145 -73
- package/src/unstable/http/HttpIncomingMessage.ts +4 -4
- package/src/unstable/http/HttpMiddleware.ts +43 -24
- package/src/unstable/http/HttpPlatform.ts +62 -20
- package/src/unstable/http/HttpRouter.ts +27 -16
- package/src/unstable/http/HttpServer.ts +18 -57
- package/src/unstable/http/HttpServerRequest.ts +17 -15
- package/src/unstable/http/HttpServerRespondable.ts +1 -1
- package/src/unstable/http/HttpServerResponse.ts +49 -40
- package/src/unstable/http/HttpStaticServer.ts +30 -28
- package/src/unstable/http/Mime.ts +76 -0
- package/src/unstable/http/Multipart.ts +35 -18
- package/src/unstable/http/MultipartParser/internal/multipart.ts +10 -3
- package/src/unstable/http/MultipartParser.ts +4 -3
- package/src/unstable/http/UrlParams.ts +3 -161
- package/src/unstable/http/index.ts +5 -0
- package/src/unstable/http/internal/compression.ts +11 -12
- package/src/unstable/http/internal/headers.ts +7 -0
- package/src/unstable/http/internal/httpBody.ts +9 -0
- package/src/unstable/http/internal/mimeTypes.ts +395 -0
- package/src/unstable/httpapi/HttpApiBuilder.ts +52 -6
- package/src/unstable/httpapi/HttpApiClient.ts +44 -24
- package/src/unstable/httpapi/HttpApiEndpoint.ts +24 -11
- package/src/unstable/httpapi/HttpApiError.ts +3 -1
- package/src/unstable/httpapi/HttpApiMiddleware.ts +7 -5
- package/src/unstable/httpapi/HttpApiSchema.ts +14 -7
- package/src/unstable/httpapi/HttpApiTest.ts +6 -1
- package/src/unstable/httpapi/OpenApi.ts +32 -22
- package/src/unstable/net/IpInterface.ts +242 -0
- package/src/unstable/net/IpNetwork.ts +357 -0
- package/src/unstable/net/NetAddress.ts +1271 -0
- package/src/unstable/net/index.ts +20 -0
- package/src/unstable/observability/OtlpExporter.ts +5 -6
- package/src/unstable/observability/OtlpLogger.ts +9 -9
- package/src/unstable/observability/OtlpMetrics.ts +9 -8
- package/src/unstable/observability/OtlpResource.ts +5 -4
- package/src/unstable/observability/OtlpTracer.ts +103 -81
- package/src/unstable/observability/internal/otlpEnv.ts +10 -13
- package/src/unstable/persistence/PersistedCache.ts +1 -1
- package/src/unstable/persistence/PersistedQueue.ts +1100 -291
- package/src/unstable/persistence/RateLimiter.ts +64 -58
- package/src/unstable/process/ChildProcess.ts +15 -4
- package/src/unstable/process/ChildProcessSpawner.ts +1 -1
- package/src/unstable/reactivity/Atom.ts +6 -3
- package/src/unstable/reactivity/AtomHttpApi.ts +21 -10
- package/src/unstable/reactivity/AtomRegistry.ts +2 -4
- package/src/unstable/reactivity/AtomRpc.ts +6 -5
- package/src/unstable/reactivity/Hydration.ts +26 -7
- package/src/unstable/reactivity/Reactivity.ts +49 -36
- package/src/unstable/rpc/RpcClient.ts +62 -59
- package/src/unstable/rpc/RpcMessage.ts +3 -1
- package/src/unstable/rpc/RpcMiddleware.ts +7 -5
- package/src/unstable/rpc/RpcSerialization.ts +27 -117
- package/src/unstable/rpc/RpcServer.ts +143 -80
- package/src/unstable/schema/Model.ts +8 -7
- package/src/unstable/schema/VariantSchema.ts +3 -0
- package/src/unstable/socket/Socket.ts +714 -383
- package/src/unstable/socket/SocketServer.ts +5 -35
- package/src/unstable/sql/SqlClient.ts +42 -7
- package/src/unstable/sql/SqlConnection.ts +18 -0
- package/src/unstable/sql/SqlModel.ts +1 -1
- package/src/unstable/sql/Statement.ts +46 -20
- package/src/unstable/workers/Transferable.ts +1 -1
- package/src/unstable/workers/Worker.ts +3 -1
- package/src/unstable/workflow/Activity.ts +20 -9
- package/src/unstable/workflow/DurableClock.ts +1 -1
- package/src/unstable/workflow/DurableDeferred.ts +6 -0
- package/src/unstable/workflow/DurableQueue.ts +8 -0
- package/src/unstable/workflow/Workflow.ts +105 -28
- package/src/unstable/workflow/WorkflowEngine.ts +22 -0
- package/dist/internal/schema/schema.d.ts.map +0 -1
- package/dist/internal/schema/schema.js.map +0 -1
- package/dist/internal/schema/toArbitrary.d.ts +0 -2
- package/dist/internal/schema/toArbitrary.d.ts.map +0 -1
- package/dist/internal/schema/toArbitrary.js +0 -705
- package/dist/internal/schema/toArbitrary.js.map +0 -1
- package/dist/testing/FastCheck.d.ts +0 -90
- package/dist/testing/FastCheck.d.ts.map +0 -1
- package/dist/testing/FastCheck.js +0 -90
- package/dist/testing/FastCheck.js.map +0 -1
- package/dist/unstable/encoding/Msgpack.d.ts +0 -185
- package/dist/unstable/encoding/Msgpack.d.ts.map +0 -1
- package/dist/unstable/encoding/Msgpack.js +0 -227
- package/dist/unstable/encoding/Msgpack.js.map +0 -1
- package/src/internal/schema/toArbitrary.ts +0 -843
- package/src/testing/FastCheck.ts +0 -90
- package/src/unstable/encoding/Msgpack.ts +0 -432
- /package/dist/internal/{schema → arbitrary}/schema.d.ts +0 -0
|
@@ -1,14 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stores schema-encoded queue work in persistent storage.
|
|
3
|
+
*
|
|
4
|
+
* A `PersistedQueue<A>` keeps JSON-encoded values in a named queue and lets
|
|
5
|
+
* workers take one value at a time inside a scoped processing window. It is
|
|
6
|
+
* useful for durable handoffs, background jobs, outbox-style integrations, and
|
|
7
|
+
* work that should retry across fibers, process restarts, or multiple workers.
|
|
8
|
+
* This module includes a queue factory, store service, id-based de-duplication,
|
|
9
|
+
* retry handling, and in-memory, Redis, and SQL-backed store layers.
|
|
10
|
+
*
|
|
11
|
+
* Delivery is at-least-once: a crash between handler success and the
|
|
12
|
+
* acknowledgement redelivers the element, so handlers must be idempotent.
|
|
13
|
+
*
|
|
14
|
+
* @since 4.0.0
|
|
15
|
+
*/
|
|
1
16
|
import * as Cause from "../../Cause.js";
|
|
17
|
+
import * as Clock from "../../Clock.js";
|
|
2
18
|
import * as Context from "../../Context.js";
|
|
3
|
-
import * as Data from "../../Data.js";
|
|
4
19
|
import * as Duration from "../../Duration.js";
|
|
5
20
|
import * as Effect from "../../Effect.js";
|
|
6
|
-
import * as Exit from "../../Exit.js";
|
|
7
21
|
import { flow } from "../../Function.js";
|
|
8
|
-
import
|
|
22
|
+
import { sqlCleanupBatchSize } from "../../internal/persistence.js";
|
|
9
23
|
import * as Latch from "../../Latch.js";
|
|
10
24
|
import * as Layer from "../../Layer.js";
|
|
11
25
|
import * as MutableRef from "../../MutableRef.js";
|
|
26
|
+
import * as Predicate from "../../Predicate.js";
|
|
27
|
+
import * as Pull from "../../Pull.js";
|
|
12
28
|
import * as Queue from "../../Queue.js";
|
|
13
29
|
import * as RcMap from "../../RcMap.js";
|
|
14
30
|
import * as Schedule from "../../Schedule.js";
|
|
@@ -35,10 +51,47 @@ export class PersistedQueueFactory extends /*#__PURE__*/Context.Service()("effec
|
|
|
35
51
|
* Accesses `PersistedQueueFactory` to create a named persisted queue for a
|
|
36
52
|
* schema.
|
|
37
53
|
*
|
|
54
|
+
* **Details**
|
|
55
|
+
*
|
|
56
|
+
* `maxAttempts` defaults to 10. `retrySchedule` controls the delay before a
|
|
57
|
+
* failed element becomes visible again, and defaults to an exponential delay
|
|
58
|
+
* starting at 1 second and capped at 5 minutes.
|
|
59
|
+
*
|
|
60
|
+
* The schedule's state is the element's persisted attempt count. On each
|
|
61
|
+
* failure the schedule is replayed up to the current attempt, so delays keep
|
|
62
|
+
* progressing even when consecutive retries run in different processes. The
|
|
63
|
+
* schedule input is the attempt number.
|
|
64
|
+
*
|
|
65
|
+
* Replay simulates elapsed time from the sum of the computed delays.
|
|
66
|
+
* Attempt-driven schedules are therefore exact, while wall-clock-anchored
|
|
67
|
+
* schedules observe this idealized time. In particular,
|
|
68
|
+
* `Schedule.upTo({ duration })` caps the summed delays rather than real time
|
|
69
|
+
* since the original failure.
|
|
70
|
+
*
|
|
38
71
|
* @category accessors
|
|
39
72
|
* @since 4.0.0
|
|
40
73
|
*/
|
|
41
74
|
export const make = options => PersistedQueueFactory.use(factory => factory.make(options));
|
|
75
|
+
const defaultRetrySchedule = /*#__PURE__*/Schedule.min([/*#__PURE__*/Schedule.exponential("1 second"), /*#__PURE__*/Schedule.spaced("5 minutes")]);
|
|
76
|
+
// The persisted attempt count is the schedule state: consecutive retries of an
|
|
77
|
+
// element can run in different processes, so a fresh schedule step is replayed
|
|
78
|
+
// up to the given attempt on every call. Delays therefore depend only on the
|
|
79
|
+
// attempt count, with elapsed time simulated from the summed delays.
|
|
80
|
+
const retryDelay = /*#__PURE__*/Effect.fnUntraced(function* (schedule, attempts) {
|
|
81
|
+
const step = yield* Schedule.toStep(schedule);
|
|
82
|
+
let now = 0;
|
|
83
|
+
let delay = Duration.zero;
|
|
84
|
+
for (let i = 0; i < attempts; i++) {
|
|
85
|
+
const result = yield* Pull.catchDone(step(now, i + 1), () => Effect.undefined);
|
|
86
|
+
if (result === undefined) {
|
|
87
|
+
// the schedule is done, keep using its final delay
|
|
88
|
+
break;
|
|
89
|
+
}
|
|
90
|
+
delay = result[1];
|
|
91
|
+
now += Duration.toMillis(delay);
|
|
92
|
+
}
|
|
93
|
+
return delay;
|
|
94
|
+
});
|
|
42
95
|
/**
|
|
43
96
|
* Creates a `PersistedQueueFactory` from the current `PersistedQueueStore`.
|
|
44
97
|
*
|
|
@@ -58,6 +111,12 @@ export const makeFactory = /*#__PURE__*/Effect.gen(function* () {
|
|
|
58
111
|
const jsonSchema = Schema.toCodecJson(options.schema);
|
|
59
112
|
const encodeUnknown = Schema.encodeUnknownEffect(jsonSchema);
|
|
60
113
|
const decodeUnknown = Schema.decodeUnknownEffect(jsonSchema);
|
|
114
|
+
const retrySchedule = options.retrySchedule ?? defaultRetrySchedule;
|
|
115
|
+
const takeOptions = {
|
|
116
|
+
name: options.name,
|
|
117
|
+
maxAttempts: options.maxAttempts ?? 10,
|
|
118
|
+
retryDelay: attempts => retryDelay(retrySchedule, attempts)
|
|
119
|
+
};
|
|
61
120
|
return Effect.succeed({
|
|
62
121
|
[TypeId]: TypeId,
|
|
63
122
|
offer: (value, opts) => Effect.flatMap(encodeUnknown(value), element => {
|
|
@@ -69,17 +128,13 @@ export const makeFactory = /*#__PURE__*/Effect.gen(function* () {
|
|
|
69
128
|
isCustomId: opts?.id !== undefined
|
|
70
129
|
}), id);
|
|
71
130
|
}),
|
|
72
|
-
take:
|
|
73
|
-
const
|
|
74
|
-
name: options.name,
|
|
75
|
-
maxAttempts: opts?.maxAttempts ?? 10
|
|
76
|
-
}).pipe(Scope.provide(scope));
|
|
77
|
-
const decoded = yield* decodeUnknown(item.element);
|
|
78
|
-
return yield* f(decoded, {
|
|
131
|
+
take: f => {
|
|
132
|
+
const loop = Effect.scopedWith(scope => store.take(takeOptions).pipe(Scope.provide(scope), Effect.flatMap(item => decodeUnknown(item.element).pipe(Effect.catchCause(cause => Cause.hasInterruptsOnly(cause) ? Effect.failCause(cause) : Effect.fail(new DeadLetter(cause))), Effect.flatMap(value => f(value, {
|
|
79
133
|
id: item.id,
|
|
80
134
|
attempts: item.attempts
|
|
81
|
-
});
|
|
82
|
-
|
|
135
|
+
})))))).pipe(Effect.catchIf(isDeadLetter, () => loop));
|
|
136
|
+
return loop;
|
|
137
|
+
}
|
|
83
138
|
});
|
|
84
139
|
}
|
|
85
140
|
});
|
|
@@ -91,13 +146,41 @@ export const makeFactory = /*#__PURE__*/Effect.gen(function* () {
|
|
|
91
146
|
* @since 4.0.0
|
|
92
147
|
*/
|
|
93
148
|
export const layer = /*#__PURE__*/Layer.effect(PersistedQueueFactory, makeFactory);
|
|
149
|
+
/**
|
|
150
|
+
* Runs `PersistedQueueStore.cleanup` on a schedule.
|
|
151
|
+
*
|
|
152
|
+
* **Details**
|
|
153
|
+
*
|
|
154
|
+
* Completed elements are retained for `timeToLive` (default 30 days) so
|
|
155
|
+
* offer de-duplication keeps working across replays, then removed. Failed
|
|
156
|
+
* elements are the dead-letter record and are kept forever unless
|
|
157
|
+
* `failedTimeToLive` is set.
|
|
158
|
+
*
|
|
159
|
+
* Run this layer in one instance of a deployment rather than on every worker;
|
|
160
|
+
* racing instances are harmless since deletes are idempotent, but the work is
|
|
161
|
+
* redundant.
|
|
162
|
+
*
|
|
163
|
+
* @category layers
|
|
164
|
+
* @since 4.0.0
|
|
165
|
+
*/
|
|
166
|
+
export const layerCleanup = options => Layer.effectDiscard(Effect.gen(function* () {
|
|
167
|
+
const store = yield* PersistedQueueStore;
|
|
168
|
+
const cleanupOptions = {
|
|
169
|
+
timeToLive: Duration.fromInputUnsafe(options?.timeToLive ?? Duration.days(30)),
|
|
170
|
+
failedTimeToLive: options?.failedTimeToLive === undefined ? undefined : Duration.fromInputUnsafe(options.failedTimeToLive)
|
|
171
|
+
};
|
|
172
|
+
yield* store.cleanup(cleanupOptions).pipe(Effect.catchCause(cause => Effect.logWarning("Failed to clean up persisted queue", cause)), Effect.repeat(Schedule.spaced(options?.interval ?? Duration.hours(1))), Effect.interruptible, Effect.forkScoped, Effect.annotateLogs({
|
|
173
|
+
module: "effect/persistence/PersistedQueue",
|
|
174
|
+
fiber: "cleanup"
|
|
175
|
+
}));
|
|
176
|
+
}));
|
|
94
177
|
/**
|
|
95
178
|
* Runtime type identifier for `PersistedQueueError`.
|
|
96
179
|
*
|
|
97
180
|
* @category type IDs
|
|
98
181
|
* @since 4.0.0
|
|
99
182
|
*/
|
|
100
|
-
export const ErrorTypeId = "
|
|
183
|
+
export const ErrorTypeId = "~effect/persistence/PersistedQueue/PersistedQueueError";
|
|
101
184
|
/**
|
|
102
185
|
* Error raised by persisted queue store operations.
|
|
103
186
|
*
|
|
@@ -116,6 +199,47 @@ export class PersistedQueueError extends /*#__PURE__*/Schema.Error("effect/persi
|
|
|
116
199
|
*/
|
|
117
200
|
[ErrorTypeId] = ErrorTypeId;
|
|
118
201
|
}
|
|
202
|
+
const makeQueueStates = () => {
|
|
203
|
+
const states = new Map();
|
|
204
|
+
return {
|
|
205
|
+
peek: name => states.get(name),
|
|
206
|
+
get: name => {
|
|
207
|
+
let state = states.get(name);
|
|
208
|
+
if (state === undefined) {
|
|
209
|
+
// the placeholder is overwritten by take before any mailbox reads it,
|
|
210
|
+
// and is kept int32-safe for SQL parameters
|
|
211
|
+
state = {
|
|
212
|
+
maxAttempts: 2147483647,
|
|
213
|
+
nudge: Latch.makeUnsafe(false)
|
|
214
|
+
};
|
|
215
|
+
states.set(name, state);
|
|
216
|
+
}
|
|
217
|
+
return state;
|
|
218
|
+
}
|
|
219
|
+
};
|
|
220
|
+
};
|
|
221
|
+
const makeAckRetrySchedule = lockExpiration => Schedule.min([Schedule.exponential(200, 1.5), Schedule.spaced(5000)]).pipe(Schedule.upTo({
|
|
222
|
+
duration: lockExpiration
|
|
223
|
+
}));
|
|
224
|
+
// Internal signal used by the factory to tell a store that a taken element
|
|
225
|
+
// cannot ever be processed (its stored payload fails to decode) and must be
|
|
226
|
+
// dead-lettered instead of retried.
|
|
227
|
+
class DeadLetter {
|
|
228
|
+
_tag = "~effect/persistence/PersistedQueue/DeadLetter";
|
|
229
|
+
cause;
|
|
230
|
+
constructor(cause) {
|
|
231
|
+
this.cause = cause;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
const isDeadLetter = u => Predicate.isTagged(u, "~effect/persistence/PersistedQueue/DeadLetter");
|
|
235
|
+
const deadLetterFromCause = cause => {
|
|
236
|
+
for (const reason of cause.reasons) {
|
|
237
|
+
if (Cause.isFailReason(reason) && isDeadLetter(reason.error)) {
|
|
238
|
+
return reason.error;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
return undefined;
|
|
242
|
+
};
|
|
119
243
|
/**
|
|
120
244
|
* Defines the low-level backing store service used by `PersistedQueue`.
|
|
121
245
|
*
|
|
@@ -129,6 +253,12 @@ export class PersistedQueueError extends /*#__PURE__*/Schema.Error("effect/persi
|
|
|
129
253
|
* The store persists offered elements and returns taken elements in a scope so
|
|
130
254
|
* the finalizer can complete or retry them based on the processing exit.
|
|
131
255
|
*
|
|
256
|
+
* Claiming an element counts an attempt, so the `attempts` returned by `take`
|
|
257
|
+
* is 1-based. When the take scope closes with a success the element is marked
|
|
258
|
+
* completed; a failure retries it according to `retryDelay` or marks it failed
|
|
259
|
+
* once `maxAttempts` is exhausted; an interruption releases it without
|
|
260
|
+
* counting the attempt.
|
|
261
|
+
*
|
|
132
262
|
* @category services
|
|
133
263
|
* @since 4.0.0
|
|
134
264
|
*/
|
|
@@ -138,21 +268,23 @@ export class PersistedQueueStore extends /*#__PURE__*/Context.Service()("effect/
|
|
|
138
268
|
*
|
|
139
269
|
* **Details**
|
|
140
270
|
*
|
|
141
|
-
* The store is process-local and volatile; failed takes are requeued
|
|
142
|
-
* configured maximum attempts is reached
|
|
271
|
+
* The store is process-local and volatile; failed takes are requeued with the
|
|
272
|
+
* queue's retry schedule until the configured maximum attempts is reached,
|
|
273
|
+
* after which the element is marked as failed.
|
|
143
274
|
*
|
|
144
275
|
* @category layers
|
|
145
276
|
* @since 4.0.0
|
|
146
277
|
*/
|
|
147
|
-
export const layerStoreMemory = /*#__PURE__*/Layer.
|
|
278
|
+
export const layerStoreMemory = /*#__PURE__*/Layer.effect(PersistedQueueStore, /*#__PURE__*/Effect.gen(function* () {
|
|
279
|
+
const clock = yield* Clock.Clock;
|
|
148
280
|
const queues = new Map();
|
|
149
281
|
const getOrCreateQueue = name => {
|
|
150
282
|
let queue = queues.get(name);
|
|
151
283
|
if (!queue) {
|
|
152
284
|
queue = {
|
|
153
285
|
latch: Latch.makeUnsafe(false),
|
|
154
|
-
|
|
155
|
-
|
|
286
|
+
entries: new Map(),
|
|
287
|
+
pending: new Set()
|
|
156
288
|
};
|
|
157
289
|
queues.set(name, queue);
|
|
158
290
|
}
|
|
@@ -160,102 +292,176 @@ export const layerStoreMemory = /*#__PURE__*/Layer.sync(PersistedQueueStore, ()
|
|
|
160
292
|
};
|
|
161
293
|
return PersistedQueueStore.of({
|
|
162
294
|
offer: options => Effect.sync(() => {
|
|
295
|
+
const now = clock.currentTimeMillisUnsafe();
|
|
163
296
|
const queue = getOrCreateQueue(options.name);
|
|
164
|
-
if (queue.
|
|
165
|
-
|
|
166
|
-
queue.items.add({
|
|
297
|
+
if (queue.entries.has(options.id)) return;
|
|
298
|
+
const entry = {
|
|
167
299
|
id: options.id,
|
|
300
|
+
element: options.element,
|
|
168
301
|
attempts: 0,
|
|
169
|
-
|
|
170
|
-
|
|
302
|
+
state: "pending",
|
|
303
|
+
visibleAt: now,
|
|
304
|
+
stateChangedAt: now
|
|
305
|
+
};
|
|
306
|
+
queue.entries.set(options.id, entry);
|
|
307
|
+
queue.pending.add(entry);
|
|
171
308
|
queue.latch.openUnsafe();
|
|
172
309
|
}),
|
|
173
310
|
take: Effect.fnUntraced(function* (options) {
|
|
174
311
|
const queue = getOrCreateQueue(options.name);
|
|
175
312
|
while (true) {
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
313
|
+
// close before scanning so a mutation after the scan reopens the latch
|
|
314
|
+
queue.latch.closeUnsafe();
|
|
315
|
+
const now = clock.currentTimeMillisUnsafe();
|
|
316
|
+
let item;
|
|
317
|
+
let nextVisibleAt = Infinity;
|
|
318
|
+
for (const entry of queue.pending) {
|
|
319
|
+
if (entry.attempts >= options.maxAttempts) continue;
|
|
320
|
+
if (entry.visibleAt <= now) {
|
|
321
|
+
item = entry;
|
|
322
|
+
break;
|
|
323
|
+
}
|
|
324
|
+
nextVisibleAt = Math.min(nextVisibleAt, entry.visibleAt);
|
|
181
325
|
}
|
|
182
|
-
|
|
326
|
+
if (item === undefined) {
|
|
327
|
+
yield* nextVisibleAt === Infinity ? queue.latch.await : Effect.race(queue.latch.await, Effect.sleep(Duration.millis(nextVisibleAt - now)));
|
|
328
|
+
continue;
|
|
329
|
+
}
|
|
330
|
+
const entry = item;
|
|
331
|
+
entry.state = "processing";
|
|
332
|
+
entry.attempts += 1;
|
|
333
|
+
queue.pending.delete(entry);
|
|
334
|
+
queue.latch.openUnsafe();
|
|
335
|
+
yield* Effect.addFinalizer(Effect.fnUntraced(function* (exit) {
|
|
336
|
+
const now = clock.currentTimeMillisUnsafe();
|
|
183
337
|
if (exit._tag === "Success") {
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
338
|
+
entry.state = "completed";
|
|
339
|
+
entry.stateChangedAt = now;
|
|
340
|
+
return;
|
|
341
|
+
}
|
|
342
|
+
const deadLetter = deadLetterFromCause(exit.cause);
|
|
343
|
+
if (deadLetter !== undefined) {
|
|
344
|
+
entry.state = "failed";
|
|
345
|
+
entry.stateChangedAt = now;
|
|
346
|
+
return;
|
|
187
347
|
}
|
|
188
|
-
if (
|
|
189
|
-
|
|
348
|
+
if (Cause.hasInterruptsOnly(exit.cause)) {
|
|
349
|
+
entry.attempts -= 1;
|
|
350
|
+
} else if (entry.attempts >= options.maxAttempts) {
|
|
351
|
+
entry.state = "failed";
|
|
352
|
+
entry.stateChangedAt = now;
|
|
353
|
+
return;
|
|
354
|
+
} else {
|
|
355
|
+
entry.visibleAt = now + Duration.toMillis(yield* options.retryDelay(entry.attempts));
|
|
190
356
|
}
|
|
191
|
-
|
|
357
|
+
entry.state = "pending";
|
|
358
|
+
queue.pending.add(entry);
|
|
192
359
|
queue.latch.openUnsafe();
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
360
|
+
}));
|
|
361
|
+
return {
|
|
362
|
+
id: entry.id,
|
|
363
|
+
attempts: entry.attempts,
|
|
364
|
+
element: entry.element
|
|
365
|
+
};
|
|
366
|
+
}
|
|
367
|
+
}),
|
|
368
|
+
cleanup: options => Effect.sync(() => {
|
|
369
|
+
const now = clock.currentTimeMillisUnsafe();
|
|
370
|
+
const completedCutoff = now - Duration.toMillis(options.timeToLive);
|
|
371
|
+
const failedCutoff = options.failedTimeToLive === undefined ? undefined : now - Duration.toMillis(options.failedTimeToLive);
|
|
372
|
+
for (const queue of queues.values()) {
|
|
373
|
+
for (const [id, entry] of queue.entries) {
|
|
374
|
+
const cutoff = entry.state === "completed" ? completedCutoff : entry.state === "failed" ? failedCutoff : undefined;
|
|
375
|
+
if (cutoff !== undefined && entry.stateChangedAt <= cutoff) {
|
|
376
|
+
queue.entries.delete(id);
|
|
377
|
+
}
|
|
378
|
+
}
|
|
196
379
|
}
|
|
197
380
|
})
|
|
198
381
|
});
|
|
199
|
-
});
|
|
382
|
+
}));
|
|
200
383
|
/**
|
|
201
384
|
* Creates a Redis-backed `PersistedQueueStore`.
|
|
202
385
|
*
|
|
203
386
|
* **Details**
|
|
204
387
|
*
|
|
205
|
-
* The store uses Redis lists and
|
|
206
|
-
* refreshes locks while items are being processed,
|
|
207
|
-
* to a failed
|
|
388
|
+
* The store uses Redis lists, hashes, and sorted sets with worker locks,
|
|
389
|
+
* periodically refreshes locks while items are being processed, delays retried
|
|
390
|
+
* items with the queue's retry schedule, and moves exhausted items to a failed
|
|
391
|
+
* queue.
|
|
208
392
|
*
|
|
209
393
|
* @category constructors
|
|
210
394
|
* @since 4.0.0
|
|
211
395
|
*/
|
|
212
396
|
export const makeStoreRedis = /*#__PURE__*/Effect.fnUntraced(function* (options) {
|
|
213
397
|
const redis = yield* Redis.Redis;
|
|
398
|
+
const clock = yield* Clock.Clock;
|
|
214
399
|
const pollInterval = Duration.max(options?.pollInterval ? Duration.fromInputUnsafe(options.pollInterval) : Duration.seconds(1), Duration.millis(1));
|
|
215
400
|
const lockRefreshMillis = Math.max(options?.lockRefreshInterval ? Duration.toMillis(Duration.fromInputUnsafe(options.lockRefreshInterval)) : 30_000, 1);
|
|
216
401
|
const lockExpirationMillis = Math.max(options?.lockExpiration ? Duration.toMillis(Duration.fromInputUnsafe(options.lockExpiration)) : 90_000, 1);
|
|
217
402
|
const prefix = options?.prefix ?? "effectq:";
|
|
218
|
-
const keyQueue = name => `${prefix}${name}`;
|
|
219
403
|
const keyLock = id => `${prefix}${id}:lock`;
|
|
220
|
-
const
|
|
221
|
-
|
|
404
|
+
const keysFor = name => ({
|
|
405
|
+
queue: `${prefix}${name}`,
|
|
406
|
+
pending: `${prefix}${name}:pending`,
|
|
407
|
+
failed: `${prefix}${name}:failed`,
|
|
408
|
+
delayed: `${prefix}${name}:delayed`,
|
|
409
|
+
attempts: `${prefix}${name}:attempts`,
|
|
410
|
+
ids: `${prefix}${name}:ids`
|
|
411
|
+
});
|
|
222
412
|
const workerId = crypto.randomUUID();
|
|
413
|
+
const ackRetrySchedule = makeAckRetrySchedule(lockExpirationMillis);
|
|
223
414
|
const requeue = redis.eval(requeueRedis);
|
|
224
415
|
const complete = redis.eval(completeRedis);
|
|
225
416
|
const failed = redis.eval(failedRedis);
|
|
417
|
+
const retry = redis.eval(retryRedis);
|
|
226
418
|
const resetQueue = redis.eval(resetQueueRedis);
|
|
227
419
|
const offer = redis.eval(offerRedis);
|
|
228
420
|
const take = redis.eval(takeRedis);
|
|
229
421
|
const expireAll = redis.eval(expireAllRedis);
|
|
422
|
+
const trimFailed = redis.eval(trimFailedRedis);
|
|
423
|
+
const queueStates = makeQueueStates();
|
|
230
424
|
const queues = yield* RcMap.make({
|
|
231
425
|
lookup: Effect.fnUntraced(function* (name) {
|
|
232
|
-
const
|
|
233
|
-
const pendingKey = keyPending(name);
|
|
426
|
+
const keys = keysFor(name);
|
|
234
427
|
const queue = yield* Queue.make();
|
|
235
428
|
const takers = MutableRef.make(0);
|
|
236
429
|
const pollLatch = Latch.makeUnsafe();
|
|
237
430
|
const takenLatch = Latch.makeUnsafe();
|
|
238
|
-
|
|
431
|
+
const state = queueStates.get(name);
|
|
432
|
+
yield* Effect.addFinalizer(() => Effect.orDie(Effect.flatMap(Queue.clear(queue), elements => Effect.forEach(elements, element => requeue(keys.queue, keys.pending, keyLock(element.id), keys.attempts, element.id, element.payload), {
|
|
239
433
|
concurrency: "unbounded",
|
|
240
434
|
discard: true
|
|
241
435
|
}))));
|
|
242
|
-
yield* resetQueue(
|
|
243
|
-
const poll = size => take(
|
|
436
|
+
yield* Effect.suspend(() => resetQueue(keys.queue, keys.pending, keys.attempts, keys.failed, keys.ids, prefix, state.maxAttempts, clock.currentTimeMillisUnsafe())).pipe(Effect.andThen(Effect.sleep(lockRefreshMillis)), Effect.forever, Effect.forkScoped);
|
|
437
|
+
const poll = size => Effect.suspend(() => take(keys.queue, keys.pending, keys.delayed, keys.attempts, prefix, workerId, size, lockExpirationMillis, clock.currentTimeMillisUnsafe()));
|
|
244
438
|
yield* Effect.gen(function* () {
|
|
245
439
|
while (true) {
|
|
246
440
|
yield* pollLatch.await;
|
|
247
441
|
yield* Effect.yieldNow;
|
|
442
|
+
state.nudge.closeUnsafe();
|
|
248
443
|
const results = takers.current === 0 ? null : yield* poll(takers.current);
|
|
249
|
-
if (results === null) {
|
|
250
|
-
yield* Effect.sleep(pollInterval);
|
|
444
|
+
if (results === null || results.length === 0) {
|
|
445
|
+
yield* Effect.race(Effect.sleep(pollInterval), state.nudge.await);
|
|
251
446
|
continue;
|
|
252
447
|
}
|
|
253
448
|
takenLatch.closeUnsafe();
|
|
254
|
-
|
|
449
|
+
const elements = [];
|
|
450
|
+
for (let i = 0; i < results.length; i += 2) {
|
|
451
|
+
const payload = results[i];
|
|
452
|
+
const parsed = JSON.parse(payload);
|
|
453
|
+
elements.push({
|
|
454
|
+
id: parsed.id,
|
|
455
|
+
element: parsed.element,
|
|
456
|
+
attempts: Number(results[i + 1]),
|
|
457
|
+
payload
|
|
458
|
+
});
|
|
459
|
+
}
|
|
460
|
+
yield* Queue.offerAll(queue, elements);
|
|
255
461
|
yield* takenLatch.await;
|
|
256
462
|
yield* Effect.yieldNow;
|
|
257
463
|
}
|
|
258
|
-
}).pipe(Effect.sandbox, Effect.retry(Schedule.spaced(500)), Effect.forkScoped, Effect.interruptible);
|
|
464
|
+
}).pipe(Effect.tapCause(Effect.logWarning), Effect.sandbox, Effect.retry(Schedule.spaced(500)), Effect.forkScoped, Effect.interruptible);
|
|
259
465
|
return {
|
|
260
466
|
queue,
|
|
261
467
|
takers,
|
|
@@ -275,70 +481,120 @@ export const makeStoreRedis = /*#__PURE__*/Effect.fnUntraced(function* (options)
|
|
|
275
481
|
module: "effect/persistence/PersistedQueue",
|
|
276
482
|
fiber: "refreshLocks"
|
|
277
483
|
}));
|
|
484
|
+
const scanKeys = pattern => Effect.gen(function* () {
|
|
485
|
+
const keys = [];
|
|
486
|
+
let cursor = "0";
|
|
487
|
+
do {
|
|
488
|
+
const [next, batch] = yield* redis.send("SCAN", cursor, "MATCH", pattern, "COUNT", "100");
|
|
489
|
+
cursor = next;
|
|
490
|
+
for (const key of batch) keys.push(key);
|
|
491
|
+
} while (cursor !== "0");
|
|
492
|
+
return keys;
|
|
493
|
+
});
|
|
278
494
|
return PersistedQueueStore.of({
|
|
279
495
|
offer: ({
|
|
280
496
|
element,
|
|
281
497
|
id,
|
|
282
498
|
isCustomId,
|
|
283
499
|
name
|
|
284
|
-
}) => Effect.mapError(isCustomId ? offer(`${prefix}${name}`, `${prefix}${name}:ids`, id, JSON.stringify({
|
|
285
|
-
id,
|
|
286
|
-
element,
|
|
287
|
-
attempts: 0
|
|
288
|
-
})) : redis.send("RPUSH", `${prefix}${name}`, JSON.stringify({
|
|
289
|
-
id,
|
|
290
|
-
element,
|
|
291
|
-
attempts: 0
|
|
292
|
-
})), ({
|
|
293
|
-
cause
|
|
294
|
-
}) => new PersistedQueueError({
|
|
295
|
-
message: "Failed to offer element to persisted queue",
|
|
296
|
-
cause
|
|
297
|
-
})),
|
|
298
|
-
take: options => Effect.uninterruptibleMask(restore => RcMap.get(queues, options.name).pipe(Effect.flatMap(({
|
|
299
|
-
pollLatch,
|
|
300
|
-
queue,
|
|
301
|
-
takenLatch,
|
|
302
|
-
takers
|
|
303
500
|
}) => {
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
501
|
+
const keys = keysFor(name);
|
|
502
|
+
const payload = JSON.stringify({
|
|
503
|
+
id,
|
|
504
|
+
element
|
|
505
|
+
});
|
|
506
|
+
return (isCustomId ? offer(keys.queue, keys.ids, id, payload) : redis.send("RPUSH", keys.queue, payload)).pipe(Effect.mapError(({
|
|
507
|
+
cause
|
|
508
|
+
}) => new PersistedQueueError({
|
|
509
|
+
message: "Failed to offer element to persisted queue",
|
|
510
|
+
cause
|
|
511
|
+
})), Effect.tap(() => Effect.sync(() => {
|
|
512
|
+
queueStates.peek(name)?.nudge.openUnsafe();
|
|
513
|
+
})));
|
|
514
|
+
},
|
|
515
|
+
take: options => Effect.uninterruptibleMask(restore => {
|
|
516
|
+
queueStates.get(options.name).maxAttempts = options.maxAttempts;
|
|
517
|
+
return RcMap.get(queues, options.name).pipe(Effect.flatMap(({
|
|
518
|
+
pollLatch,
|
|
519
|
+
queue,
|
|
520
|
+
takenLatch,
|
|
521
|
+
takers
|
|
522
|
+
}) => {
|
|
523
|
+
takers.current++;
|
|
524
|
+
if (takers.current === 1) {
|
|
525
|
+
pollLatch.openUnsafe();
|
|
315
526
|
}
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
if (
|
|
325
|
-
|
|
326
|
-
...element,
|
|
327
|
-
lastFailure: Cause.pretty(cause),
|
|
328
|
-
attempts: nextAttempts
|
|
329
|
-
})));
|
|
527
|
+
// onExit so the decrement also runs when a waiting take is
|
|
528
|
+
// interrupted, otherwise the poller keeps fetching for a phantom
|
|
529
|
+
// taker
|
|
530
|
+
return Effect.onExit(restore(Queue.take(queue)), () => Effect.sync(() => {
|
|
531
|
+
takers.current--;
|
|
532
|
+
if (takers.current === 0) {
|
|
533
|
+
pollLatch.closeUnsafe();
|
|
534
|
+
takenLatch.openUnsafe();
|
|
535
|
+
} else if (Queue.sizeUnsafe(queue) === 0) {
|
|
536
|
+
takenLatch.openUnsafe();
|
|
330
537
|
}
|
|
331
|
-
|
|
332
|
-
|
|
538
|
+
}));
|
|
539
|
+
}), Effect.scoped, Effect.tap(element => {
|
|
540
|
+
const keys = keysFor(options.name);
|
|
541
|
+
const lock = keyLock(element.id);
|
|
542
|
+
activeLockKeys.add(lock);
|
|
543
|
+
const ack = effect => effect.pipe(Effect.retry(ackRetrySchedule), Effect.orDie, Effect.ensuring(Effect.sync(() => activeLockKeys.delete(lock))));
|
|
544
|
+
return Effect.addFinalizer(exit => Effect.suspend(() => {
|
|
545
|
+
const now = clock.currentTimeMillisUnsafe();
|
|
546
|
+
if (exit._tag === "Success") {
|
|
547
|
+
return ack(complete(keys.pending, lock, keys.attempts, keys.ids, element.id, now));
|
|
548
|
+
}
|
|
549
|
+
const dead = deadLetterFromCause(exit.cause);
|
|
550
|
+
const failElement = cause => ack(failed(keys.pending, lock, keys.failed, keys.attempts, keys.ids, element.id, JSON.stringify({
|
|
551
|
+
id: element.id,
|
|
552
|
+
element: element.element,
|
|
553
|
+
attempts: element.attempts,
|
|
333
554
|
lastFailure: Cause.pretty(cause),
|
|
334
|
-
|
|
555
|
+
failedAt: now
|
|
335
556
|
})));
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
557
|
+
if (dead !== undefined) {
|
|
558
|
+
return failElement(dead.cause);
|
|
559
|
+
}
|
|
560
|
+
if (Cause.hasInterruptsOnly(exit.cause)) {
|
|
561
|
+
return ack(requeue(keys.queue, keys.pending, lock, keys.attempts, element.id, element.payload));
|
|
562
|
+
}
|
|
563
|
+
if (element.attempts >= options.maxAttempts) {
|
|
564
|
+
return failElement(exit.cause);
|
|
565
|
+
}
|
|
566
|
+
return Effect.flatMap(options.retryDelay(element.attempts), delay => ack(retry(keys.pending, lock, keys.delayed, element.id, element.payload, now + Duration.toMillis(delay))));
|
|
567
|
+
}));
|
|
341
568
|
}));
|
|
569
|
+
}),
|
|
570
|
+
cleanup: ({
|
|
571
|
+
failedTimeToLive,
|
|
572
|
+
timeToLive
|
|
573
|
+
}) => Effect.gen(function* () {
|
|
574
|
+
const now = clock.currentTimeMillisUnsafe();
|
|
575
|
+
const idsKeys = yield* scanKeys(`${prefix}*:ids`);
|
|
576
|
+
const cutoff = now - Duration.toMillis(timeToLive);
|
|
577
|
+
yield* Effect.forEach(idsKeys, key => redis.send("ZREMRANGEBYSCORE", key, "-inf", `(${cutoff}`), {
|
|
578
|
+
concurrency: 16,
|
|
579
|
+
discard: true
|
|
580
|
+
});
|
|
581
|
+
if (failedTimeToLive !== undefined) {
|
|
582
|
+
const failedCutoff = now - Duration.toMillis(failedTimeToLive);
|
|
583
|
+
const failedKeys = yield* scanKeys(`${prefix}*:failed`);
|
|
584
|
+
yield* Effect.forEach(failedKeys, key => trimFailed(key, `${key.slice(0, -":failed".length)}:ids`, failedCutoff).pipe(
|
|
585
|
+
// each call trims at most one batch, so drain until done
|
|
586
|
+
Effect.repeat({
|
|
587
|
+
while: removed => removed >= trimFailedBatchSize
|
|
588
|
+
})), {
|
|
589
|
+
concurrency: 16,
|
|
590
|
+
discard: true
|
|
591
|
+
});
|
|
592
|
+
}
|
|
593
|
+
}).pipe(Effect.mapError(({
|
|
594
|
+
cause
|
|
595
|
+
}) => new PersistedQueueError({
|
|
596
|
+
message: "Failed to clean up persisted queue",
|
|
597
|
+
cause
|
|
342
598
|
})))
|
|
343
599
|
});
|
|
344
600
|
});
|
|
@@ -349,7 +605,9 @@ local key_ids = KEYS[2]
|
|
|
349
605
|
local id = ARGV[1]
|
|
350
606
|
local payload = ARGV[2]
|
|
351
607
|
|
|
352
|
-
|
|
608
|
+
-- park the dedupe entry outside the timeToLive trim range until the element
|
|
609
|
+
-- completes, so unprocessed elements never lose dedupe protection
|
|
610
|
+
local result = redis.call("ZADD", key_ids, "NX", "+inf", id)
|
|
353
611
|
if result == 1 then
|
|
354
612
|
redis.call("RPUSH", key_queue, payload)
|
|
355
613
|
end
|
|
@@ -360,7 +618,12 @@ const resetQueueRedis = /*#__PURE__*/Redis.script((...args) => args, {
|
|
|
360
618
|
lua: `
|
|
361
619
|
local key_queue = KEYS[1]
|
|
362
620
|
local key_pending = KEYS[2]
|
|
621
|
+
local key_attempts = KEYS[3]
|
|
622
|
+
local key_failed = KEYS[4]
|
|
623
|
+
local key_ids = KEYS[5]
|
|
363
624
|
local prefix = ARGV[1]
|
|
625
|
+
local max_attempts = tonumber(ARGV[2])
|
|
626
|
+
local now = ARGV[3]
|
|
364
627
|
|
|
365
628
|
local entries = redis.call("HGETALL", key_pending)
|
|
366
629
|
for i = 1, #entries, 2 do
|
|
@@ -369,76 +632,135 @@ for i = 1, #entries, 2 do
|
|
|
369
632
|
local lock_key = prefix .. id .. ":lock"
|
|
370
633
|
local exists = redis.call("EXISTS", lock_key)
|
|
371
634
|
if exists == 0 then
|
|
372
|
-
redis.call("
|
|
635
|
+
local attempts = tonumber(redis.call("HGET", key_attempts, id) or "0")
|
|
636
|
+
if attempts >= max_attempts then
|
|
637
|
+
-- compose the failed record by hand so the element payload does not go
|
|
638
|
+
-- through a lossy cjson round-trip
|
|
639
|
+
local record = string.sub(payload, 1, -2) .. ',"attempts":' .. attempts ..
|
|
640
|
+
',"lastFailure":"Lock expired after final attempt","failedAt":' .. now .. '}'
|
|
641
|
+
redis.call("RPUSH", key_failed, record)
|
|
642
|
+
redis.call("HDEL", key_attempts, id)
|
|
643
|
+
-- failed ids keep their dedupe entry until failedTimeToLive removes the
|
|
644
|
+
-- dead-letter record, so park them outside the timeToLive trim range
|
|
645
|
+
redis.call("ZADD", key_ids, "XX", "+inf", id)
|
|
646
|
+
else
|
|
647
|
+
redis.call("RPUSH", key_queue, payload)
|
|
648
|
+
end
|
|
373
649
|
redis.call("HDEL", key_pending, id)
|
|
374
650
|
end
|
|
375
651
|
end
|
|
376
652
|
`,
|
|
377
|
-
numberOfKeys:
|
|
653
|
+
numberOfKeys: 5
|
|
378
654
|
});
|
|
379
655
|
const requeueRedis = /*#__PURE__*/Redis.script((...args) => args, {
|
|
380
656
|
lua: `
|
|
381
657
|
local key_queue = KEYS[1]
|
|
382
658
|
local key_pending = KEYS[2]
|
|
383
659
|
local key_lock = KEYS[3]
|
|
660
|
+
local key_attempts = KEYS[4]
|
|
384
661
|
local id = ARGV[1]
|
|
385
662
|
local payload = ARGV[2]
|
|
386
663
|
|
|
387
664
|
redis.call("DEL", key_lock)
|
|
388
665
|
redis.call("HDEL", key_pending, id)
|
|
666
|
+
local attempts = redis.call("HINCRBY", key_attempts, id, -1)
|
|
667
|
+
if attempts <= 0 then
|
|
668
|
+
redis.call("HDEL", key_attempts, id)
|
|
669
|
+
end
|
|
389
670
|
redis.call("RPUSH", key_queue, payload)
|
|
390
671
|
`,
|
|
391
|
-
numberOfKeys:
|
|
672
|
+
numberOfKeys: 4
|
|
392
673
|
});
|
|
393
674
|
const completeRedis = /*#__PURE__*/Redis.script((...args) => args, {
|
|
394
675
|
lua: `
|
|
395
676
|
local key_pending = KEYS[1]
|
|
396
677
|
local key_lock = KEYS[2]
|
|
678
|
+
local key_attempts = KEYS[3]
|
|
679
|
+
local key_ids = KEYS[4]
|
|
397
680
|
local id = ARGV[1]
|
|
681
|
+
local now = ARGV[2]
|
|
398
682
|
|
|
399
683
|
redis.call("DEL", key_lock)
|
|
400
684
|
redis.call("HDEL", key_pending, id)
|
|
685
|
+
redis.call("HDEL", key_attempts, id)
|
|
686
|
+
redis.call("ZADD", key_ids, "XX", now, id)
|
|
401
687
|
`,
|
|
402
|
-
numberOfKeys:
|
|
688
|
+
numberOfKeys: 4
|
|
689
|
+
});
|
|
690
|
+
const retryRedis = /*#__PURE__*/Redis.script((...args) => args, {
|
|
691
|
+
lua: `
|
|
692
|
+
local key_pending = KEYS[1]
|
|
693
|
+
local key_lock = KEYS[2]
|
|
694
|
+
local key_delayed = KEYS[3]
|
|
695
|
+
local id = ARGV[1]
|
|
696
|
+
local payload = ARGV[2]
|
|
697
|
+
local visible_at = ARGV[3]
|
|
698
|
+
|
|
699
|
+
redis.call("DEL", key_lock)
|
|
700
|
+
redis.call("HDEL", key_pending, id)
|
|
701
|
+
redis.call("ZADD", key_delayed, visible_at, payload)
|
|
702
|
+
`,
|
|
703
|
+
numberOfKeys: 3
|
|
403
704
|
});
|
|
404
705
|
const failedRedis = /*#__PURE__*/Redis.script((...args) => args, {
|
|
405
706
|
lua: `
|
|
406
707
|
local key_pending = KEYS[1]
|
|
407
708
|
local key_lock = KEYS[2]
|
|
408
709
|
local key_failed = KEYS[3]
|
|
710
|
+
local key_attempts = KEYS[4]
|
|
711
|
+
local key_ids = KEYS[5]
|
|
409
712
|
local id = ARGV[1]
|
|
410
713
|
local payload = ARGV[2]
|
|
411
714
|
|
|
412
715
|
redis.call("DEL", key_lock)
|
|
413
716
|
redis.call("HDEL", key_pending, id)
|
|
717
|
+
redis.call("HDEL", key_attempts, id)
|
|
414
718
|
redis.call("RPUSH", key_failed, payload)
|
|
719
|
+
-- failed ids keep their dedupe entry until failedTimeToLive removes the
|
|
720
|
+
-- dead-letter record, so park them outside the timeToLive trim range
|
|
721
|
+
redis.call("ZADD", key_ids, "XX", "+inf", id)
|
|
415
722
|
`,
|
|
416
|
-
numberOfKeys:
|
|
723
|
+
numberOfKeys: 5
|
|
417
724
|
});
|
|
418
725
|
const takeRedis = /*#__PURE__*/Redis.script((...args) => args, {
|
|
419
726
|
lua: `
|
|
420
727
|
local key_queue = KEYS[1]
|
|
421
728
|
local key_pending = KEYS[2]
|
|
729
|
+
local key_delayed = KEYS[3]
|
|
730
|
+
local key_attempts = KEYS[4]
|
|
422
731
|
local prefix = ARGV[1]
|
|
423
732
|
local worker_id = ARGV[2]
|
|
424
733
|
local batch_size = tonumber(ARGV[3])
|
|
425
734
|
local pttl = ARGV[4]
|
|
735
|
+
local now = ARGV[5]
|
|
736
|
+
|
|
737
|
+
local due = redis.call("ZRANGEBYSCORE", key_delayed, "-inf", now, "LIMIT", 0, 100)
|
|
738
|
+
if #due > 0 then
|
|
739
|
+
for i, payload in ipairs(due) do
|
|
740
|
+
redis.call("RPUSH", key_queue, payload)
|
|
741
|
+
end
|
|
742
|
+
redis.call("ZREM", key_delayed, unpack(due))
|
|
743
|
+
end
|
|
426
744
|
|
|
427
745
|
local payloads = redis.call("LPOP", key_queue, batch_size)
|
|
428
746
|
if not payloads then
|
|
429
747
|
return nil
|
|
430
748
|
end
|
|
431
749
|
|
|
750
|
+
local result = {}
|
|
432
751
|
for i, payload in ipairs(payloads) do
|
|
433
752
|
local id = cjson.decode(payload).id
|
|
434
753
|
local key_lock = prefix .. id .. ":lock"
|
|
435
754
|
redis.call("SET", key_lock, worker_id, "PX", pttl)
|
|
436
755
|
redis.call("HSET", key_pending, id, payload)
|
|
756
|
+
local attempts = redis.call("HINCRBY", key_attempts, id, 1)
|
|
757
|
+
result[i * 2 - 1] = payload
|
|
758
|
+
result[i * 2] = attempts
|
|
437
759
|
end
|
|
438
760
|
|
|
439
|
-
return
|
|
761
|
+
return result
|
|
440
762
|
`,
|
|
441
|
-
numberOfKeys:
|
|
763
|
+
numberOfKeys: 4
|
|
442
764
|
}).withReturnType();
|
|
443
765
|
const expireAllRedis = /*#__PURE__*/Redis.script((keys, ttl) => [...keys, ttl], {
|
|
444
766
|
numberOfKeys: keys => keys.length,
|
|
@@ -449,6 +771,36 @@ for i, key in ipairs(KEYS) do
|
|
|
449
771
|
end
|
|
450
772
|
`
|
|
451
773
|
});
|
|
774
|
+
const trimFailedBatchSize = 1000;
|
|
775
|
+
const trimFailedRedis = /*#__PURE__*/Redis.script((...args) => args, {
|
|
776
|
+
lua: `
|
|
777
|
+
local key_failed = KEYS[1]
|
|
778
|
+
local key_ids = KEYS[2]
|
|
779
|
+
local cutoff = tonumber(ARGV[1])
|
|
780
|
+
local removed = 0
|
|
781
|
+
|
|
782
|
+
while removed < ${trimFailedBatchSize} do
|
|
783
|
+
local head = redis.call("LINDEX", key_failed, 0)
|
|
784
|
+
if not head then break end
|
|
785
|
+
local ok, decoded = pcall(cjson.decode, head)
|
|
786
|
+
if ok then
|
|
787
|
+
local failed_at = tonumber(decoded.failedAt)
|
|
788
|
+
if failed_at ~= nil and failed_at >= cutoff then break end
|
|
789
|
+
redis.call("LPOP", key_failed)
|
|
790
|
+
if decoded.id ~= nil then
|
|
791
|
+
redis.call("ZREM", key_ids, decoded.id)
|
|
792
|
+
end
|
|
793
|
+
else
|
|
794
|
+
-- a corrupt head would otherwise block trimming of the whole list
|
|
795
|
+
redis.call("LPOP", key_failed)
|
|
796
|
+
end
|
|
797
|
+
removed = removed + 1
|
|
798
|
+
end
|
|
799
|
+
|
|
800
|
+
return removed
|
|
801
|
+
`,
|
|
802
|
+
numberOfKeys: 2
|
|
803
|
+
}).withReturnType();
|
|
452
804
|
/**
|
|
453
805
|
* Provides a Redis-backed `PersistedQueueStore` using `makeStoreRedis`.
|
|
454
806
|
*
|
|
@@ -475,46 +827,56 @@ export const makeStoreSql = /*#__PURE__*/Effect.fnUntraced(function* (options) {
|
|
|
475
827
|
const pollInterval = Duration.max(options?.pollInterval ? Duration.fromInputUnsafe(options.pollInterval) : Duration.millis(1000), Duration.millis(1));
|
|
476
828
|
const lockRefreshInterval = Duration.max(options?.lockRefreshInterval ? Duration.fromInputUnsafe(options.lockRefreshInterval) : Duration.seconds(30), Duration.millis(1));
|
|
477
829
|
const lockExpiration = Duration.max(options?.lockExpiration ? Duration.fromInputUnsafe(options.lockExpiration) : Duration.minutes(2), Duration.millis(1));
|
|
478
|
-
const lockExpirationSql = sql.literal(Math.ceil(Duration.toSeconds(lockExpiration)).toString());
|
|
479
830
|
const workerId = crypto.randomUUID();
|
|
831
|
+
const ackRetrySchedule = makeAckRetrySchedule(lockExpiration);
|
|
480
832
|
yield* Effect.orDie(Migrator.make({})({
|
|
481
833
|
loader: sqlMigrations(tableName),
|
|
482
834
|
table: `${tableName}_migrations`
|
|
483
835
|
}));
|
|
484
836
|
const sqlNow = sql.onDialectOrElse({
|
|
485
|
-
|
|
837
|
+
// GETDATE() rounds to 1/300s and can land in the future, hiding freshly
|
|
838
|
+
// written visible_at values from the poll query
|
|
839
|
+
mssql: () => sql.literal("SYSDATETIME()"),
|
|
486
840
|
mysql: () => sql.literal("NOW()"),
|
|
487
841
|
pg: () => sql.literal("NOW()"),
|
|
488
842
|
// sqlite
|
|
489
843
|
orElse: () => sql.literal("CURRENT_TIMESTAMP")
|
|
490
844
|
});
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
845
|
+
// `seconds` is a whole number, possibly negative
|
|
846
|
+
const secondsOffset = seconds => {
|
|
847
|
+
const s = sql.literal(seconds.toString());
|
|
848
|
+
return sql.onDialectOrElse({
|
|
849
|
+
pg: () => sql`${sqlNow} + INTERVAL '${s} seconds'`,
|
|
850
|
+
mysql: () => sql`DATE_ADD(${sqlNow}, INTERVAL ${s} SECOND)`,
|
|
851
|
+
mssql: () => sql`DATEADD(SECOND, ${s}, ${sqlNow})`,
|
|
852
|
+
orElse: () => sql`datetime(${sqlNow}, '${s} seconds')`
|
|
853
|
+
});
|
|
854
|
+
};
|
|
855
|
+
const secondsAgo = seconds => secondsOffset(-Math.max(Math.ceil(seconds), 0));
|
|
856
|
+
const secondsFromNow = seconds => secondsOffset(Math.max(Math.ceil(seconds), 0));
|
|
857
|
+
const expiresAt = secondsAgo(Duration.toSeconds(lockExpiration));
|
|
497
858
|
const offer = sql.onDialectOrElse({
|
|
498
859
|
pg: () => (id, name, element) => sql`
|
|
499
|
-
INSERT INTO ${tableNameSql} (id, queue_name, element,
|
|
500
|
-
VALUES (${id}, ${name}, ${element},
|
|
860
|
+
INSERT INTO ${tableNameSql} (id, queue_name, element, state, attempts, visible_at, created_at, updated_at)
|
|
861
|
+
VALUES (${id}, ${name}, ${element}, 'pending', 0, ${sqlNow}, ${sqlNow}, ${sqlNow})
|
|
501
862
|
ON CONFLICT (id, queue_name) DO NOTHING
|
|
502
863
|
`,
|
|
503
864
|
mysql: () => (id, name, element) => sql`
|
|
504
|
-
INSERT IGNORE INTO ${tableNameSql} (id, queue_name, element,
|
|
505
|
-
VALUES (${id}, ${name}, ${element},
|
|
865
|
+
INSERT IGNORE INTO ${tableNameSql} (id, queue_name, element, state, attempts, visible_at, created_at, updated_at)
|
|
866
|
+
VALUES (${id}, ${name}, ${element}, 'pending', 0, ${sqlNow}, ${sqlNow}, ${sqlNow})
|
|
506
867
|
`,
|
|
507
868
|
mssql: () => (id, name, element) => sql`
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
869
|
+
MERGE ${tableNameSql} WITH (HOLDLOCK) AS target
|
|
870
|
+
USING (SELECT ${id} AS id, ${name} AS queue_name) AS source
|
|
871
|
+
ON target.id = source.id AND target.queue_name = source.queue_name
|
|
872
|
+
WHEN NOT MATCHED THEN
|
|
873
|
+
INSERT (id, queue_name, element, state, attempts, visible_at, created_at, updated_at)
|
|
874
|
+
VALUES (source.id, source.queue_name, ${element}, 'pending', 0, ${sqlNow}, ${sqlNow}, ${sqlNow});
|
|
513
875
|
`,
|
|
514
876
|
// sqlite
|
|
515
877
|
orElse: () => (id, name, element) => sql`
|
|
516
|
-
INSERT OR IGNORE INTO ${tableNameSql} (id, queue_name, element,
|
|
517
|
-
VALUES (${id}, ${name}, ${element},
|
|
878
|
+
INSERT OR IGNORE INTO ${tableNameSql} (id, queue_name, element, state, attempts, visible_at, created_at, updated_at)
|
|
879
|
+
VALUES (${id}, ${name}, ${element}, 'pending', 0, ${sqlNow}, ${sqlNow}, ${sqlNow})
|
|
518
880
|
`
|
|
519
881
|
});
|
|
520
882
|
const wrapString = sql.onDialectOrElse({
|
|
@@ -522,10 +884,6 @@ export const makeStoreSql = /*#__PURE__*/Effect.fnUntraced(function* (options) {
|
|
|
522
884
|
orElse: () => s => `'${s}'`
|
|
523
885
|
});
|
|
524
886
|
const stringLiteral = s => sql.literal(wrapString(s));
|
|
525
|
-
const sqlTrue = sql.onDialectOrElse({
|
|
526
|
-
sqlite: () => sql.literal("1"),
|
|
527
|
-
orElse: () => sql.literal("TRUE")
|
|
528
|
-
});
|
|
529
887
|
const workerIdSql = stringLiteral(workerId);
|
|
530
888
|
const elementIds = new Set();
|
|
531
889
|
const refreshLocks = Effect.suspend(() => {
|
|
@@ -538,143 +896,156 @@ export const makeStoreSql = /*#__PURE__*/Effect.fnUntraced(function* (options) {
|
|
|
538
896
|
AND acquired_by = ${workerIdSql}
|
|
539
897
|
`;
|
|
540
898
|
});
|
|
541
|
-
const
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
UPDATE ${tableNameSql}
|
|
545
|
-
SET acquired_at = NULL, acquired_by = NULL, updated_at = ${sqlNow}, completed = ${sqlTrue}, attempts = ${attempts}
|
|
546
|
-
WHERE sequence = ${sequence}
|
|
547
|
-
AND acquired_by = ${workerIdSql}
|
|
548
|
-
`.pipe(Effect.retry({
|
|
549
|
-
times: 5,
|
|
550
|
-
schedule: Schedule.exponential(100, 1.5)
|
|
551
|
-
}), Effect.orDie);
|
|
552
|
-
};
|
|
553
|
-
const retry = (sequence, attempts, cause) => {
|
|
554
|
-
elementIds.delete(sequence);
|
|
555
|
-
return sql`
|
|
556
|
-
UPDATE ${tableNameSql}
|
|
557
|
-
SET acquired_at = NULL, acquired_by = NULL, updated_at = ${sqlNow}, attempts = ${attempts}, last_failure = ${Cause.pretty(cause)}
|
|
558
|
-
WHERE sequence = ${sequence}
|
|
559
|
-
AND acquired_by = ${workerIdSql}
|
|
560
|
-
`.pipe(Effect.retry({
|
|
561
|
-
times: 5,
|
|
562
|
-
schedule: Schedule.exponential(100, 1.5)
|
|
563
|
-
}), Effect.orDie);
|
|
564
|
-
};
|
|
565
|
-
const interrupt = ids => {
|
|
566
|
-
for (const id of ids) {
|
|
567
|
-
elementIds.delete(id);
|
|
899
|
+
const ack = (statement, sequences) => statement.pipe(Effect.retry(ackRetrySchedule), Effect.orDie, Effect.ensuring(Effect.sync(() => {
|
|
900
|
+
for (const sequence of sequences) {
|
|
901
|
+
elementIds.delete(sequence);
|
|
568
902
|
}
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
903
|
+
})), Effect.asVoid);
|
|
904
|
+
const complete = sequence => ack(sql`
|
|
905
|
+
UPDATE ${tableNameSql}
|
|
906
|
+
SET acquired_at = NULL, acquired_by = NULL, updated_at = ${sqlNow}, state = 'completed'
|
|
907
|
+
WHERE sequence = ${sequence}
|
|
908
|
+
AND acquired_by = ${workerIdSql}
|
|
909
|
+
`, [sequence]);
|
|
910
|
+
const fail = (sequence, cause) => ack(sql`
|
|
911
|
+
UPDATE ${tableNameSql}
|
|
912
|
+
SET acquired_at = NULL, acquired_by = NULL, updated_at = ${sqlNow}, state = 'failed', last_failure = ${Cause.pretty(cause)}
|
|
913
|
+
WHERE sequence = ${sequence}
|
|
914
|
+
AND acquired_by = ${workerIdSql}
|
|
915
|
+
`, [sequence]);
|
|
916
|
+
const retry = (sequence, delay, cause) => ack(sql`
|
|
917
|
+
UPDATE ${tableNameSql}
|
|
918
|
+
SET acquired_at = NULL, acquired_by = NULL, updated_at = ${sqlNow}, visible_at = ${secondsFromNow(Duration.toSeconds(delay))}, last_failure = ${Cause.pretty(cause)}
|
|
919
|
+
WHERE sequence = ${sequence}
|
|
920
|
+
AND acquired_by = ${workerIdSql}
|
|
921
|
+
`, [sequence]);
|
|
922
|
+
const interrupt = ids => ack(sql`
|
|
923
|
+
UPDATE ${tableNameSql}
|
|
924
|
+
SET acquired_at = NULL, acquired_by = NULL, attempts = attempts - 1
|
|
925
|
+
WHERE sequence IN (${sql.literal(ids.join(","))})
|
|
926
|
+
AND acquired_by = ${workerIdSql}
|
|
927
|
+
`, ids);
|
|
579
928
|
yield* refreshLocks.pipe(Effect.tapCause(Effect.logWarning), Effect.retry(Schedule.spaced(500)), Effect.schedule(Schedule.fixed(lockRefreshInterval)), Effect.annotateLogs({
|
|
580
929
|
package: "@effect/sql",
|
|
581
930
|
module: "SqlPersistedQueue",
|
|
582
931
|
fiber: "refreshLocks"
|
|
583
932
|
}), Effect.forkScoped);
|
|
933
|
+
const queueStates = makeQueueStates();
|
|
584
934
|
const mailboxes = yield* RcMap.make({
|
|
585
|
-
lookup: Effect.fnUntraced(function* ({
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
}) {
|
|
935
|
+
lookup: Effect.fnUntraced(function* (name) {
|
|
936
|
+
const state = queueStates.get(name);
|
|
937
|
+
const maxAttempts = state.maxAttempts;
|
|
589
938
|
const queue = yield* Queue.make();
|
|
590
939
|
const takers = MutableRef.make(0);
|
|
591
940
|
const pollLatch = Latch.makeUnsafe();
|
|
592
941
|
const takenLatch = Latch.makeUnsafe();
|
|
942
|
+
const nudge = state.nudge;
|
|
593
943
|
yield* Effect.addFinalizer(() => Effect.flatMap(Queue.clear(queue), elements => {
|
|
594
944
|
if (elements.length === 0) return Effect.void;
|
|
595
945
|
return interrupt(Array.from(elements, e => e.sequence));
|
|
596
946
|
}));
|
|
947
|
+
// flip exhausted rows whose lock expired (worker crashed on the final
|
|
948
|
+
// attempt) to failed, since no finalizer will ever run for them
|
|
949
|
+
yield* sql`
|
|
950
|
+
UPDATE ${tableNameSql}
|
|
951
|
+
SET state = 'failed', acquired_at = NULL, acquired_by = NULL, updated_at = ${sqlNow},
|
|
952
|
+
last_failure = COALESCE(last_failure, 'Lock expired after final attempt')
|
|
953
|
+
WHERE queue_name = ${name}
|
|
954
|
+
AND state = 'pending'
|
|
955
|
+
AND attempts >= ${maxAttempts}
|
|
956
|
+
AND (acquired_at IS NULL OR acquired_at < ${expiresAt})
|
|
957
|
+
`.pipe(Effect.tapCause(Effect.logWarning), Effect.ignore, Effect.schedule(Schedule.spaced(lockRefreshInterval)), Effect.forkScoped, Effect.interruptible);
|
|
597
958
|
const poll = sql.onDialectOrElse({
|
|
598
959
|
pg: () => size => sql`
|
|
599
960
|
WITH cte AS (
|
|
600
961
|
UPDATE ${tableNameSql}
|
|
601
|
-
SET acquired_at = ${sqlNow}, acquired_by = ${workerIdSql}
|
|
962
|
+
SET acquired_at = ${sqlNow}, acquired_by = ${workerIdSql}, attempts = attempts + 1
|
|
602
963
|
WHERE sequence IN (
|
|
603
964
|
SELECT sequence FROM ${tableNameSql}
|
|
604
965
|
WHERE queue_name = ${name}
|
|
605
|
-
AND
|
|
966
|
+
AND state = 'pending'
|
|
606
967
|
AND attempts < ${maxAttempts}
|
|
968
|
+
AND visible_at <= ${sqlNow}
|
|
607
969
|
AND (acquired_at IS NULL OR acquired_at < ${expiresAt})
|
|
608
|
-
ORDER BY
|
|
970
|
+
ORDER BY visible_at ASC, sequence ASC
|
|
609
971
|
FOR UPDATE SKIP LOCKED
|
|
610
972
|
LIMIT ${sql.literal(size.toString())}
|
|
611
973
|
)
|
|
612
|
-
RETURNING sequence, id,
|
|
974
|
+
RETURNING sequence, id, element, attempts, visible_at
|
|
613
975
|
)
|
|
614
|
-
SELECT sequence, id,
|
|
615
|
-
ORDER BY
|
|
976
|
+
SELECT sequence, id, element, attempts FROM cte
|
|
977
|
+
ORDER BY visible_at ASC, sequence ASC
|
|
616
978
|
`,
|
|
617
979
|
mysql: () => size => sql`
|
|
618
|
-
SELECT sequence, id,
|
|
980
|
+
SELECT sequence, id, element, attempts FROM ${tableNameSql} q
|
|
619
981
|
WHERE queue_name = ${name}
|
|
620
|
-
AND
|
|
982
|
+
AND state = 'pending'
|
|
621
983
|
AND attempts < ${maxAttempts}
|
|
984
|
+
AND visible_at <= ${sqlNow}
|
|
622
985
|
AND (acquired_at IS NULL OR acquired_at < ${expiresAt})
|
|
623
|
-
ORDER BY
|
|
986
|
+
ORDER BY visible_at ASC, sequence ASC
|
|
624
987
|
LIMIT ${sql.literal(size.toString())}
|
|
625
988
|
FOR UPDATE SKIP LOCKED
|
|
626
989
|
`.pipe(Effect.tap(rows => {
|
|
627
990
|
if (rows.length === 0) return Effect.void;
|
|
628
991
|
return sql`
|
|
629
992
|
UPDATE ${tableNameSql}
|
|
630
|
-
SET acquired_at = ${sqlNow}, acquired_by = ${workerIdSql}
|
|
993
|
+
SET acquired_at = ${sqlNow}, acquired_by = ${workerIdSql}, attempts = attempts + 1
|
|
631
994
|
WHERE sequence IN (${sql.literal(rows.map(r => r.sequence).join(","))})
|
|
632
995
|
`.unprepared;
|
|
996
|
+
}), Effect.map(rows => {
|
|
997
|
+
for (const row of rows) {
|
|
998
|
+
row.attempts = Number(row.attempts) + 1;
|
|
999
|
+
}
|
|
1000
|
+
return rows;
|
|
633
1001
|
}), sql.withTransaction),
|
|
634
1002
|
mssql: () => size => sql`
|
|
635
1003
|
WITH cte AS (
|
|
636
1004
|
SELECT TOP ${sql.literal(size.toString())} sequence FROM ${tableNameSql}
|
|
637
1005
|
WHERE queue_name = ${name}
|
|
638
|
-
AND
|
|
1006
|
+
AND state = 'pending'
|
|
639
1007
|
AND attempts < ${maxAttempts}
|
|
1008
|
+
AND visible_at <= ${sqlNow}
|
|
640
1009
|
AND (acquired_at IS NULL OR acquired_at < ${expiresAt})
|
|
641
|
-
ORDER BY
|
|
1010
|
+
ORDER BY visible_at ASC, sequence ASC
|
|
642
1011
|
)
|
|
643
1012
|
UPDATE q
|
|
644
|
-
SET acquired_at = ${sqlNow}, acquired_by = ${workerIdSql}
|
|
645
|
-
OUTPUT inserted.sequence, inserted.id, inserted.
|
|
1013
|
+
SET acquired_at = ${sqlNow}, acquired_by = ${workerIdSql}, attempts = q.attempts + 1
|
|
1014
|
+
OUTPUT inserted.sequence, inserted.id, inserted.element, inserted.attempts
|
|
646
1015
|
FROM ${tableNameSql} AS q
|
|
647
1016
|
INNER JOIN cte ON q.sequence = cte.sequence
|
|
648
1017
|
`,
|
|
649
1018
|
// sqlite
|
|
650
1019
|
orElse: () => size => sql`
|
|
651
1020
|
UPDATE ${tableNameSql}
|
|
652
|
-
SET acquired_at = ${sqlNow}, acquired_by = ${workerIdSql}
|
|
1021
|
+
SET acquired_at = ${sqlNow}, acquired_by = ${workerIdSql}, attempts = attempts + 1
|
|
653
1022
|
WHERE sequence IN (
|
|
654
1023
|
SELECT sequence FROM ${tableNameSql}
|
|
655
1024
|
WHERE queue_name = ${name}
|
|
656
|
-
AND
|
|
1025
|
+
AND state = 'pending'
|
|
657
1026
|
AND attempts < ${maxAttempts}
|
|
1027
|
+
AND visible_at <= ${sqlNow}
|
|
658
1028
|
AND (acquired_at IS NULL OR acquired_at < ${expiresAt})
|
|
659
|
-
ORDER BY
|
|
1029
|
+
ORDER BY visible_at ASC, sequence ASC
|
|
660
1030
|
LIMIT ${sql.literal(size.toString())}
|
|
661
1031
|
)
|
|
662
|
-
RETURNING sequence, id,
|
|
1032
|
+
RETURNING sequence, id, element, attempts
|
|
663
1033
|
`
|
|
664
1034
|
});
|
|
665
1035
|
yield* Effect.gen(function* () {
|
|
666
1036
|
while (true) {
|
|
667
1037
|
yield* pollLatch.await;
|
|
668
1038
|
yield* Effect.yieldNow;
|
|
1039
|
+
nudge.closeUnsafe();
|
|
669
1040
|
const results = takers.current === 0 ? [] : yield* poll(takers.current);
|
|
670
1041
|
if (results.length === 0) {
|
|
671
|
-
yield* Effect.sleep(pollInterval);
|
|
1042
|
+
yield* Effect.race(Effect.sleep(pollInterval), nudge.await);
|
|
672
1043
|
continue;
|
|
673
1044
|
}
|
|
674
1045
|
takenLatch.closeUnsafe();
|
|
675
|
-
for (
|
|
676
|
-
|
|
677
|
-
elementIds.add(
|
|
1046
|
+
for (const row of results) {
|
|
1047
|
+
row.attempts = Number(row.attempts);
|
|
1048
|
+
elementIds.add(row.sequence);
|
|
678
1049
|
}
|
|
679
1050
|
yield* Queue.offerAll(queue, results);
|
|
680
1051
|
yield* takenLatch.await;
|
|
@@ -690,6 +1061,50 @@ export const makeStoreSql = /*#__PURE__*/Effect.fnUntraced(function* (options) {
|
|
|
690
1061
|
}),
|
|
691
1062
|
idleTimeToLive: Duration.seconds(30)
|
|
692
1063
|
});
|
|
1064
|
+
const cleanupBatch = sql.onDialectOrElse({
|
|
1065
|
+
pg: () => (state, seconds) => sql`
|
|
1066
|
+
WITH deleted_entries AS (
|
|
1067
|
+
DELETE FROM ${tableNameSql}
|
|
1068
|
+
WHERE sequence IN (
|
|
1069
|
+
SELECT sequence FROM ${tableNameSql}
|
|
1070
|
+
WHERE state = ${state} AND updated_at <= ${secondsAgo(seconds)}
|
|
1071
|
+
LIMIT ${sql.literal(String(sqlCleanupBatchSize))}
|
|
1072
|
+
)
|
|
1073
|
+
RETURNING 1
|
|
1074
|
+
)
|
|
1075
|
+
SELECT COUNT(*)::INT AS count FROM deleted_entries
|
|
1076
|
+
`.pipe(Effect.map(rows => rows[0].count)),
|
|
1077
|
+
mysql: () => Effect.fnUntraced(function* (state, seconds) {
|
|
1078
|
+
const connection = yield* sql.reserve;
|
|
1079
|
+
const [statement, parameters] = sql`
|
|
1080
|
+
DELETE FROM ${tableNameSql}
|
|
1081
|
+
WHERE state = ${state} AND updated_at <= ${secondsAgo(seconds)}
|
|
1082
|
+
LIMIT ${sql.literal(String(sqlCleanupBatchSize))}
|
|
1083
|
+
`.compile();
|
|
1084
|
+
yield* connection.execute(statement, parameters, undefined);
|
|
1085
|
+
const rows = yield* connection.executeValues("SELECT ROW_COUNT()", []);
|
|
1086
|
+
return Number(rows[0][0]);
|
|
1087
|
+
}, Effect.scoped),
|
|
1088
|
+
mssql: () => (state, seconds) => sql`
|
|
1089
|
+
DELETE TOP (${sql.literal(String(sqlCleanupBatchSize))}) FROM ${tableNameSql}
|
|
1090
|
+
OUTPUT DELETED.sequence
|
|
1091
|
+
WHERE state = ${state} AND updated_at <= ${secondsAgo(seconds)}
|
|
1092
|
+
`.pipe(Effect.map(rows => rows.length)),
|
|
1093
|
+
// sqlite
|
|
1094
|
+
orElse: () => (state, seconds) => sql`
|
|
1095
|
+
DELETE FROM ${tableNameSql}
|
|
1096
|
+
WHERE sequence IN (
|
|
1097
|
+
SELECT sequence FROM ${tableNameSql}
|
|
1098
|
+
WHERE state = ${state} AND updated_at <= ${secondsAgo(seconds)}
|
|
1099
|
+
LIMIT ${sql.literal(String(sqlCleanupBatchSize))}
|
|
1100
|
+
)
|
|
1101
|
+
RETURNING 1 AS deleted
|
|
1102
|
+
`.pipe(Effect.map(rows => rows.length))
|
|
1103
|
+
});
|
|
1104
|
+
const cleanupState = (state, timeToLive) => cleanupBatch(state, Duration.toSeconds(timeToLive)).pipe(Effect.repeat({
|
|
1105
|
+
while: deletedCount => deletedCount === sqlCleanupBatchSize,
|
|
1106
|
+
schedule: Schedule.spaced(Duration.millis(10))
|
|
1107
|
+
}));
|
|
693
1108
|
return PersistedQueueStore.of({
|
|
694
1109
|
offer: ({
|
|
695
1110
|
element,
|
|
@@ -698,38 +1113,76 @@ export const makeStoreSql = /*#__PURE__*/Effect.fnUntraced(function* (options) {
|
|
|
698
1113
|
}) => Effect.catchCause(Effect.suspend(() => offer(id, name, JSON.stringify(element))), cause => Effect.fail(new PersistedQueueError({
|
|
699
1114
|
message: "Failed to offer element to persisted queue",
|
|
700
1115
|
cause
|
|
1116
|
+
}))).pipe(Effect.tap(() => Effect.sync(() => {
|
|
1117
|
+
queueStates.peek(name)?.nudge.openUnsafe();
|
|
701
1118
|
}))),
|
|
702
|
-
take:
|
|
703
|
-
maxAttempts
|
|
704
|
-
name
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
}) => {
|
|
714
|
-
takers.current++;
|
|
715
|
-
if (takers.current === 1) {
|
|
716
|
-
pollLatch.openUnsafe();
|
|
717
|
-
}
|
|
718
|
-
return Effect.tap(restore(Queue.take(queue)), () => Effect.sync(() => {
|
|
719
|
-
takers.current--;
|
|
720
|
-
if (takers.current === 0) {
|
|
721
|
-
pollLatch.closeUnsafe();
|
|
722
|
-
takenLatch.openUnsafe();
|
|
723
|
-
} else if (Queue.sizeUnsafe(queue) === 0) {
|
|
724
|
-
takenLatch.openUnsafe();
|
|
1119
|
+
take: options => {
|
|
1120
|
+
queueStates.get(options.name).maxAttempts = options.maxAttempts;
|
|
1121
|
+
const loop = Effect.uninterruptibleMask(restore => RcMap.get(mailboxes, options.name).pipe(Effect.flatMap(({
|
|
1122
|
+
pollLatch,
|
|
1123
|
+
queue,
|
|
1124
|
+
takenLatch,
|
|
1125
|
+
takers
|
|
1126
|
+
}) => {
|
|
1127
|
+
takers.current++;
|
|
1128
|
+
if (takers.current === 1) {
|
|
1129
|
+
pollLatch.openUnsafe();
|
|
725
1130
|
}
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
1131
|
+
// onExit so the decrement also runs when a waiting take is
|
|
1132
|
+
// interrupted, otherwise the poller keeps fetching for a phantom
|
|
1133
|
+
// taker
|
|
1134
|
+
return Effect.onExit(restore(Queue.take(queue)), () => Effect.sync(() => {
|
|
1135
|
+
takers.current--;
|
|
1136
|
+
if (takers.current === 0) {
|
|
1137
|
+
pollLatch.closeUnsafe();
|
|
1138
|
+
takenLatch.openUnsafe();
|
|
1139
|
+
} else if (Queue.sizeUnsafe(queue) === 0) {
|
|
1140
|
+
takenLatch.openUnsafe();
|
|
1141
|
+
}
|
|
1142
|
+
}));
|
|
1143
|
+
}), Effect.scoped, restore, Effect.flatMap(element => {
|
|
1144
|
+
let parsed;
|
|
1145
|
+
try {
|
|
1146
|
+
parsed = JSON.parse(element.element);
|
|
1147
|
+
} catch (defect) {
|
|
1148
|
+
// a row that cannot be parsed will never succeed, so dead-letter
|
|
1149
|
+
// it and take the next element
|
|
1150
|
+
return Effect.andThen(fail(element.sequence, Cause.die(defect)), loop);
|
|
1151
|
+
}
|
|
1152
|
+
return Effect.as(Effect.addFinalizer(exit => {
|
|
1153
|
+
if (exit._tag === "Success") {
|
|
1154
|
+
return complete(element.sequence);
|
|
1155
|
+
}
|
|
1156
|
+
const dead = deadLetterFromCause(exit.cause);
|
|
1157
|
+
if (dead !== undefined) {
|
|
1158
|
+
return fail(element.sequence, dead.cause);
|
|
1159
|
+
}
|
|
1160
|
+
if (Cause.hasInterruptsOnly(exit.cause)) {
|
|
1161
|
+
return interrupt([element.sequence]);
|
|
1162
|
+
}
|
|
1163
|
+
if (element.attempts >= options.maxAttempts) {
|
|
1164
|
+
return fail(element.sequence, exit.cause);
|
|
1165
|
+
}
|
|
1166
|
+
return Effect.flatMap(options.retryDelay(element.attempts), delay => retry(element.sequence, delay, exit.cause));
|
|
1167
|
+
}), {
|
|
1168
|
+
id: element.id,
|
|
1169
|
+
attempts: element.attempts,
|
|
1170
|
+
element: parsed
|
|
1171
|
+
});
|
|
1172
|
+
})));
|
|
1173
|
+
return loop;
|
|
1174
|
+
},
|
|
1175
|
+
cleanup: ({
|
|
1176
|
+
failedTimeToLive,
|
|
1177
|
+
timeToLive
|
|
1178
|
+
}) => Effect.gen(function* () {
|
|
1179
|
+
yield* cleanupState("completed", timeToLive);
|
|
1180
|
+
if (failedTimeToLive !== undefined) {
|
|
1181
|
+
yield* cleanupState("failed", failedTimeToLive);
|
|
1182
|
+
}
|
|
1183
|
+
}).pipe(Effect.catchCause(cause => Effect.fail(new PersistedQueueError({
|
|
1184
|
+
message: "Failed to clean up persisted queue",
|
|
1185
|
+
cause
|
|
733
1186
|
}))))
|
|
734
1187
|
});
|
|
735
1188
|
});
|
|
@@ -764,7 +1217,7 @@ const sqlMigrations = tableName => Migrator.fromRecord({
|
|
|
764
1217
|
created_at TIMESTAMP NOT NULL,
|
|
765
1218
|
updated_at TIMESTAMP NOT NULL
|
|
766
1219
|
)`,
|
|
767
|
-
mssql: () => sql`IF NOT EXISTS (SELECT * FROM sysobjects WHERE name=${
|
|
1220
|
+
mssql: () => sql`IF NOT EXISTS (SELECT * FROM sysobjects WHERE name=${tableName} AND xtype='U')
|
|
768
1221
|
CREATE TABLE ${tableNameSql} (
|
|
769
1222
|
sequence INT IDENTITY(1,1) PRIMARY KEY,
|
|
770
1223
|
id NVARCHAR(36) NOT NULL,
|
|
@@ -795,13 +1248,13 @@ const sqlMigrations = tableName => Migrator.fromRecord({
|
|
|
795
1248
|
});
|
|
796
1249
|
yield* sql.onDialectOrElse({
|
|
797
1250
|
mssql: () => sql`IF NOT EXISTS (SELECT * FROM sys.indexes WHERE name = N'idx_${tableName}_id')
|
|
798
|
-
CREATE UNIQUE INDEX idx_${
|
|
1251
|
+
CREATE UNIQUE INDEX ${sql(`idx_${tableName}_id`)} ON ${tableNameSql} (id, queue_name)`,
|
|
799
1252
|
mysql: () => sql`CREATE UNIQUE INDEX ${sql(`idx_${tableName}_id`)} ON ${tableNameSql} (id, queue_name)`.pipe(Effect.ignore),
|
|
800
1253
|
orElse: () => sql`CREATE UNIQUE INDEX IF NOT EXISTS ${sql(`idx_${tableName}_id`)} ON ${tableNameSql} (id, queue_name)`
|
|
801
1254
|
});
|
|
802
1255
|
yield* sql.onDialectOrElse({
|
|
803
1256
|
mssql: () => sql`IF NOT EXISTS (SELECT * FROM sys.indexes WHERE name = N'idx_${tableName}_take')
|
|
804
|
-
CREATE INDEX idx_${
|
|
1257
|
+
CREATE INDEX ${sql(`idx_${tableName}_take`)} ON ${tableNameSql} (queue_name, completed, attempts, acquired_at)`,
|
|
805
1258
|
mysql: () => sql`CREATE INDEX ${sql(`idx_${tableName}_take`)} ON ${tableNameSql} (queue_name, completed, attempts, acquired_at)`.pipe(Effect.ignore),
|
|
806
1259
|
orElse: () => sql`CREATE INDEX IF NOT EXISTS ${sql(`idx_${tableName}_take`)} ON ${tableNameSql} (queue_name, completed, attempts, acquired_at)`
|
|
807
1260
|
});
|
|
@@ -811,9 +1264,121 @@ const sqlMigrations = tableName => Migrator.fromRecord({
|
|
|
811
1264
|
mysql: () => sql`CREATE INDEX ${sql(`idx_${tableName}_update`)} ON ${tableNameSql} (sequence, acquired_by)`.pipe(Effect.ignore),
|
|
812
1265
|
orElse: () => sql`CREATE INDEX IF NOT EXISTS ${sql(`idx_${tableName}_update`)} ON ${tableNameSql} (sequence, acquired_by)`
|
|
813
1266
|
});
|
|
1267
|
+
}),
|
|
1268
|
+
"0002_upgrade_schema": Effect.gen(function* () {
|
|
1269
|
+
const sql = (yield* SqlClient.SqlClient).withoutTransforms();
|
|
1270
|
+
const tableNameSql = sql(tableName);
|
|
1271
|
+
const takeIndex = sql(`idx_${tableName}_take`);
|
|
1272
|
+
yield* sql.onDialectOrElse({
|
|
1273
|
+
pg: () => Effect.gen(function* () {
|
|
1274
|
+
yield* sql`DROP INDEX IF EXISTS ${takeIndex}`;
|
|
1275
|
+
yield* sql`ALTER TABLE ${tableNameSql}
|
|
1276
|
+
ADD COLUMN state VARCHAR(10),
|
|
1277
|
+
ADD COLUMN visible_at TIMESTAMP`;
|
|
1278
|
+
yield* sql`UPDATE ${tableNameSql}
|
|
1279
|
+
SET state = CASE WHEN completed THEN 'completed' ELSE 'pending' END,
|
|
1280
|
+
visible_at = updated_at`;
|
|
1281
|
+
yield* sql`ALTER TABLE ${tableNameSql}
|
|
1282
|
+
ALTER COLUMN sequence TYPE BIGINT,
|
|
1283
|
+
ALTER COLUMN id TYPE VARCHAR(255),
|
|
1284
|
+
ALTER COLUMN queue_name TYPE VARCHAR(255),
|
|
1285
|
+
ALTER COLUMN state SET NOT NULL,
|
|
1286
|
+
ALTER COLUMN visible_at SET NOT NULL,
|
|
1287
|
+
DROP COLUMN completed`;
|
|
1288
|
+
}),
|
|
1289
|
+
mysql: () => Effect.gen(function* () {
|
|
1290
|
+
yield* sql`DROP INDEX ${takeIndex} ON ${tableNameSql}`;
|
|
1291
|
+
yield* sql`ALTER TABLE ${tableNameSql}
|
|
1292
|
+
MODIFY COLUMN id VARCHAR(255) NOT NULL,
|
|
1293
|
+
MODIFY COLUMN queue_name VARCHAR(255) NOT NULL,
|
|
1294
|
+
MODIFY COLUMN element MEDIUMTEXT NOT NULL,
|
|
1295
|
+
MODIFY COLUMN last_failure MEDIUMTEXT NULL,
|
|
1296
|
+
ADD COLUMN state VARCHAR(10) NULL,
|
|
1297
|
+
ADD COLUMN visible_at DATETIME NULL`;
|
|
1298
|
+
yield* sql`UPDATE ${tableNameSql}
|
|
1299
|
+
SET state = CASE WHEN completed THEN 'completed' ELSE 'pending' END,
|
|
1300
|
+
visible_at = updated_at`;
|
|
1301
|
+
yield* sql`ALTER TABLE ${tableNameSql}
|
|
1302
|
+
MODIFY COLUMN state VARCHAR(10) NOT NULL,
|
|
1303
|
+
MODIFY COLUMN visible_at DATETIME NOT NULL,
|
|
1304
|
+
DROP COLUMN completed`;
|
|
1305
|
+
}),
|
|
1306
|
+
mssql: () => Effect.gen(function* () {
|
|
1307
|
+
const upgradedTableName = `${tableName}_upgrade`;
|
|
1308
|
+
const upgradedTable = sql(upgradedTableName);
|
|
1309
|
+
yield* sql`CREATE TABLE ${upgradedTable} (
|
|
1310
|
+
sequence BIGINT IDENTITY(1,1) PRIMARY KEY,
|
|
1311
|
+
id NVARCHAR(255) NOT NULL,
|
|
1312
|
+
queue_name NVARCHAR(255) NOT NULL,
|
|
1313
|
+
element NVARCHAR(MAX) NOT NULL,
|
|
1314
|
+
state NVARCHAR(10) NOT NULL,
|
|
1315
|
+
attempts INT NOT NULL DEFAULT 0,
|
|
1316
|
+
last_failure NVARCHAR(MAX) NULL,
|
|
1317
|
+
visible_at DATETIME2 NOT NULL,
|
|
1318
|
+
acquired_at DATETIME2 NULL,
|
|
1319
|
+
acquired_by UNIQUEIDENTIFIER NULL,
|
|
1320
|
+
created_at DATETIME2 NOT NULL,
|
|
1321
|
+
updated_at DATETIME2 NOT NULL
|
|
1322
|
+
)`;
|
|
1323
|
+
yield* sql`SET IDENTITY_INSERT ${upgradedTable} ON;
|
|
1324
|
+
INSERT INTO ${upgradedTable}
|
|
1325
|
+
(sequence, id, queue_name, element, state, attempts, last_failure, visible_at,
|
|
1326
|
+
acquired_at, acquired_by, created_at, updated_at)
|
|
1327
|
+
SELECT sequence, id, queue_name, element,
|
|
1328
|
+
CASE WHEN completed = 1 THEN 'completed' ELSE 'pending' END,
|
|
1329
|
+
attempts, last_failure, updated_at, acquired_at, acquired_by, created_at, updated_at
|
|
1330
|
+
FROM ${tableNameSql};
|
|
1331
|
+
SET IDENTITY_INSERT ${upgradedTable} OFF`;
|
|
1332
|
+
yield* sql`DROP TABLE ${tableNameSql}`;
|
|
1333
|
+
yield* sql`EXEC sp_rename ${upgradedTableName}, ${tableName}`;
|
|
1334
|
+
yield* sql`CREATE UNIQUE INDEX ${sql(`idx_${tableName}_id`)} ON ${tableNameSql} (id, queue_name)`;
|
|
1335
|
+
yield* sql`CREATE INDEX ${sql(`idx_${tableName}_update`)} ON ${tableNameSql} (sequence, acquired_by)`;
|
|
1336
|
+
}),
|
|
1337
|
+
// sqlite rebuilds the table because altering or dropping constrained
|
|
1338
|
+
// columns is not portable across supported SQLite versions.
|
|
1339
|
+
orElse: () => Effect.gen(function* () {
|
|
1340
|
+
const upgradedTableName = `${tableName}_upgrade`;
|
|
1341
|
+
const upgradedTable = sql(upgradedTableName);
|
|
1342
|
+
yield* sql`DROP INDEX IF EXISTS ${takeIndex}`;
|
|
1343
|
+
yield* sql`CREATE TABLE ${upgradedTable} (
|
|
1344
|
+
sequence INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
1345
|
+
id TEXT NOT NULL,
|
|
1346
|
+
queue_name TEXT NOT NULL,
|
|
1347
|
+
element TEXT NOT NULL,
|
|
1348
|
+
state TEXT NOT NULL,
|
|
1349
|
+
attempts INTEGER NOT NULL DEFAULT 0,
|
|
1350
|
+
last_failure TEXT NULL,
|
|
1351
|
+
visible_at DATETIME NOT NULL,
|
|
1352
|
+
acquired_at DATETIME NULL,
|
|
1353
|
+
acquired_by TEXT NULL,
|
|
1354
|
+
created_at DATETIME NOT NULL,
|
|
1355
|
+
updated_at DATETIME NOT NULL
|
|
1356
|
+
)`;
|
|
1357
|
+
yield* sql`INSERT INTO ${upgradedTable}
|
|
1358
|
+
(sequence, id, queue_name, element, state, attempts, last_failure, visible_at,
|
|
1359
|
+
acquired_at, acquired_by, created_at, updated_at)
|
|
1360
|
+
SELECT sequence, id, queue_name, element,
|
|
1361
|
+
CASE WHEN completed THEN 'completed' ELSE 'pending' END,
|
|
1362
|
+
attempts, last_failure, updated_at, acquired_at, acquired_by, created_at, updated_at
|
|
1363
|
+
FROM ${tableNameSql}`;
|
|
1364
|
+
yield* sql`DROP TABLE ${tableNameSql}`;
|
|
1365
|
+
yield* sql`ALTER TABLE ${upgradedTable} RENAME TO ${tableNameSql}`;
|
|
1366
|
+
yield* sql`CREATE UNIQUE INDEX ${sql(`idx_${tableName}_id`)} ON ${tableNameSql} (id, queue_name)`;
|
|
1367
|
+
yield* sql`CREATE INDEX ${sql(`idx_${tableName}_update`)} ON ${tableNameSql} (sequence, acquired_by)`;
|
|
1368
|
+
})
|
|
1369
|
+
});
|
|
1370
|
+
// partial index where supported, so pollers never scan completed rows
|
|
1371
|
+
yield* sql.onDialectOrElse({
|
|
1372
|
+
mssql: () => sql`CREATE INDEX ${takeIndex} ON ${tableNameSql} (queue_name, visible_at)
|
|
1373
|
+
WHERE state = 'pending'`,
|
|
1374
|
+
mysql: () => sql`CREATE INDEX ${takeIndex} ON ${tableNameSql} (queue_name, state, visible_at)`,
|
|
1375
|
+
pg: () => sql`CREATE INDEX ${takeIndex} ON ${tableNameSql} (queue_name, visible_at)
|
|
1376
|
+
WHERE state = 'pending'`,
|
|
1377
|
+
orElse: () => sql`CREATE INDEX ${takeIndex} ON ${tableNameSql} (queue_name, visible_at)
|
|
1378
|
+
WHERE state = 'pending'`
|
|
1379
|
+
});
|
|
814
1380
|
})
|
|
815
1381
|
});
|
|
816
|
-
class QueueKey extends Data.Class {}
|
|
817
1382
|
/**
|
|
818
1383
|
* Provides a SQL-backed `PersistedQueueStore` using `makeStoreSql`.
|
|
819
1384
|
*
|