@clayroach/effect 3.19.14-source-capture.8 → 3.19.14-source-trace.2
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/SourceLocation/package.json +6 -0
- package/dist/cjs/Effect.js +2 -28
- package/dist/cjs/Effect.js.map +1 -1
- package/dist/cjs/FiberRef.js +12 -1
- package/dist/cjs/FiberRef.js.map +1 -1
- package/dist/cjs/Layer.js +2 -24
- package/dist/cjs/Layer.js.map +1 -1
- package/dist/cjs/RuntimeFlags.js +1 -29
- package/dist/cjs/RuntimeFlags.js.map +1 -1
- package/dist/cjs/SourceLocation.js +60 -0
- package/dist/cjs/SourceLocation.js.map +1 -0
- package/dist/cjs/Tracer.js +1 -15
- package/dist/cjs/Tracer.js.map +1 -1
- package/dist/cjs/Utils.js +1 -1
- package/dist/cjs/Utils.js.map +1 -1
- package/dist/cjs/index.js +3 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/internal/clock.js +1 -1
- package/dist/cjs/internal/clock.js.map +1 -1
- package/dist/cjs/internal/core.js +17 -50
- package/dist/cjs/internal/core.js.map +1 -1
- package/dist/cjs/internal/effect/circular.js +18 -30
- package/dist/cjs/internal/effect/circular.js.map +1 -1
- package/dist/cjs/internal/fiberRuntime.js +16 -65
- package/dist/cjs/internal/fiberRuntime.js.map +1 -1
- package/dist/cjs/internal/layer/circular.js +1 -5
- package/dist/cjs/internal/layer/circular.js.map +1 -1
- package/dist/cjs/internal/layer.js +1 -3
- package/dist/cjs/internal/layer.js.map +1 -1
- package/dist/cjs/internal/logger.js +25 -2
- package/dist/cjs/internal/logger.js.map +1 -1
- package/dist/cjs/internal/runtimeFlags.js +2 -11
- package/dist/cjs/internal/runtimeFlags.js.map +1 -1
- package/dist/cjs/internal/tracer.js +1 -114
- package/dist/cjs/internal/tracer.js.map +1 -1
- package/dist/dts/Config.d.ts +2 -2
- package/dist/dts/Config.d.ts.map +1 -1
- package/dist/dts/Effect.d.ts +8 -29
- package/dist/dts/Effect.d.ts.map +1 -1
- package/dist/dts/FiberRef.d.ts +12 -0
- package/dist/dts/FiberRef.d.ts.map +1 -1
- package/dist/dts/Layer.d.ts +0 -22
- package/dist/dts/Layer.d.ts.map +1 -1
- package/dist/dts/RuntimeFlags.d.ts +0 -28
- package/dist/dts/RuntimeFlags.d.ts.map +1 -1
- package/dist/dts/SourceLocation.d.ts +88 -0
- package/dist/dts/SourceLocation.d.ts.map +1 -0
- package/dist/dts/Tracer.d.ts +0 -15
- package/dist/dts/Tracer.d.ts.map +1 -1
- package/dist/dts/index.d.ts +6 -0
- package/dist/dts/index.d.ts.map +1 -1
- package/dist/dts/internal/core.d.ts.map +1 -1
- package/dist/dts/internal/layer.d.ts.map +1 -1
- package/dist/dts/internal/runtimeFlags.d.ts.map +1 -1
- package/dist/esm/Effect.js +0 -26
- package/dist/esm/Effect.js.map +1 -1
- package/dist/esm/FiberRef.js +11 -0
- package/dist/esm/FiberRef.js.map +1 -1
- package/dist/esm/Layer.js +0 -22
- package/dist/esm/Layer.js.map +1 -1
- package/dist/esm/RuntimeFlags.js +0 -28
- package/dist/esm/RuntimeFlags.js.map +1 -1
- package/dist/esm/SourceLocation.js +51 -0
- package/dist/esm/SourceLocation.js.map +1 -0
- package/dist/esm/Tracer.js +0 -14
- package/dist/esm/Tracer.js.map +1 -1
- package/dist/esm/Utils.js +1 -1
- package/dist/esm/Utils.js.map +1 -1
- package/dist/esm/index.js +6 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/internal/clock.js +1 -1
- package/dist/esm/internal/clock.js.map +1 -1
- package/dist/esm/internal/core.js +12 -45
- package/dist/esm/internal/core.js.map +1 -1
- package/dist/esm/internal/effect/circular.js +18 -30
- package/dist/esm/internal/effect/circular.js.map +1 -1
- package/dist/esm/internal/fiberRuntime.js +13 -60
- package/dist/esm/internal/fiberRuntime.js.map +1 -1
- package/dist/esm/internal/layer/circular.js +0 -4
- package/dist/esm/internal/layer/circular.js.map +1 -1
- package/dist/esm/internal/layer.js +0 -2
- package/dist/esm/internal/layer.js.map +1 -1
- package/dist/esm/internal/logger.js +25 -2
- package/dist/esm/internal/logger.js.map +1 -1
- package/dist/esm/internal/runtimeFlags.js +1 -9
- package/dist/esm/internal/runtimeFlags.js.map +1 -1
- package/dist/esm/internal/tracer.js +0 -111
- package/dist/esm/internal/tracer.js.map +1 -1
- package/package.json +12 -1
- package/src/Arbitrary.ts +1101 -0
- package/src/Array.ts +3589 -0
- package/src/BigDecimal.ts +1349 -0
- package/src/BigInt.ts +643 -0
- package/src/Boolean.ts +287 -0
- package/src/Brand.ts +360 -0
- package/src/Cache.ts +281 -0
- package/src/Cause.ts +1555 -0
- package/src/Channel.ts +2355 -0
- package/src/ChildExecutorDecision.ts +146 -0
- package/src/Chunk.ts +1495 -0
- package/src/Clock.ts +111 -0
- package/src/Config.ts +542 -0
- package/src/ConfigError.ts +270 -0
- package/src/ConfigProvider.ts +333 -0
- package/src/ConfigProviderPathPatch.ts +100 -0
- package/src/Console.ts +226 -0
- package/src/Context.ts +585 -0
- package/src/Cron.ts +706 -0
- package/src/Data.ts +596 -0
- package/src/DateTime.ts +1686 -0
- package/src/DefaultServices.ts +34 -0
- package/src/Deferred.ts +301 -0
- package/src/Differ.ts +450 -0
- package/src/Duration.ts +1000 -0
- package/src/Effect.ts +14817 -0
- package/src/Effectable.ts +107 -0
- package/src/Either.ts +1040 -0
- package/src/Encoding.ts +195 -0
- package/src/Equal.ts +98 -0
- package/src/Equivalence.ts +235 -0
- package/src/ExecutionPlan.ts +308 -0
- package/src/ExecutionStrategy.ts +119 -0
- package/src/Exit.ts +467 -0
- package/src/FastCheck.ts +9 -0
- package/src/Fiber.ts +744 -0
- package/src/FiberHandle.ts +540 -0
- package/src/FiberId.ts +195 -0
- package/src/FiberMap.ts +656 -0
- package/src/FiberRef.ts +444 -0
- package/src/FiberRefs.ts +204 -0
- package/src/FiberRefsPatch.ts +105 -0
- package/src/FiberSet.ts +491 -0
- package/src/FiberStatus.ts +108 -0
- package/src/Function.ts +1222 -0
- package/src/GlobalValue.ts +53 -0
- package/src/Graph.ts +3732 -0
- package/src/GroupBy.ts +103 -0
- package/src/HKT.ts +45 -0
- package/src/Hash.ts +195 -0
- package/src/HashMap.ts +519 -0
- package/src/HashRing.ts +317 -0
- package/src/HashSet.ts +2346 -0
- package/src/Inspectable.ts +287 -0
- package/src/Iterable.ts +1119 -0
- package/src/JSONSchema.ts +1044 -0
- package/src/KeyedPool.ts +167 -0
- package/src/Layer.ts +1228 -0
- package/src/LayerMap.ts +436 -0
- package/src/List.ts +977 -0
- package/src/LogLevel.ts +285 -0
- package/src/LogSpan.ts +25 -0
- package/src/Logger.ts +702 -0
- package/src/Mailbox.ts +268 -0
- package/src/ManagedRuntime.ts +180 -0
- package/src/Match.ts +1477 -0
- package/src/MergeDecision.ts +95 -0
- package/src/MergeState.ts +172 -0
- package/src/MergeStrategy.ts +107 -0
- package/src/Metric.ts +780 -0
- package/src/MetricBoundaries.ts +69 -0
- package/src/MetricHook.ts +151 -0
- package/src/MetricKey.ts +224 -0
- package/src/MetricKeyType.ts +262 -0
- package/src/MetricLabel.ts +47 -0
- package/src/MetricPair.ts +71 -0
- package/src/MetricPolling.ts +148 -0
- package/src/MetricRegistry.ts +48 -0
- package/src/MetricState.ts +257 -0
- package/src/Micro.ts +4405 -0
- package/src/ModuleVersion.ts +18 -0
- package/src/MutableHashMap.ts +411 -0
- package/src/MutableHashSet.ts +706 -0
- package/src/MutableList.ts +297 -0
- package/src/MutableQueue.ts +227 -0
- package/src/MutableRef.ts +202 -0
- package/src/NonEmptyIterable.ts +32 -0
- package/src/Number.ts +1071 -0
- package/src/Option.ts +2170 -0
- package/src/Order.ts +373 -0
- package/src/Ordering.ts +111 -0
- package/src/ParseResult.ts +2031 -0
- package/src/PartitionedSemaphore.ts +200 -0
- package/src/Pipeable.ts +566 -0
- package/src/Pool.ts +204 -0
- package/src/Predicate.ts +1405 -0
- package/src/Pretty.ts +205 -0
- package/src/PrimaryKey.ts +23 -0
- package/src/PubSub.ts +182 -0
- package/src/Queue.ts +644 -0
- package/src/Random.ts +204 -0
- package/src/RateLimiter.ts +138 -0
- package/src/RcMap.ts +141 -0
- package/src/RcRef.ts +122 -0
- package/src/Readable.ts +93 -0
- package/src/Record.ts +1274 -0
- package/src/RedBlackTree.ts +421 -0
- package/src/Redacted.ts +144 -0
- package/src/Ref.ts +180 -0
- package/src/RegExp.ts +38 -0
- package/src/Reloadable.ts +127 -0
- package/src/Request.ts +347 -0
- package/src/RequestBlock.ts +118 -0
- package/src/RequestResolver.ts +366 -0
- package/src/Resource.ts +119 -0
- package/src/Runtime.ts +383 -0
- package/src/RuntimeFlags.ts +336 -0
- package/src/RuntimeFlagsPatch.ts +183 -0
- package/src/STM.ts +2045 -0
- package/src/Schedule.ts +2219 -0
- package/src/ScheduleDecision.ts +62 -0
- package/src/ScheduleInterval.ts +151 -0
- package/src/ScheduleIntervals.ts +122 -0
- package/src/Scheduler.ts +353 -0
- package/src/Schema.ts +10914 -0
- package/src/SchemaAST.ts +3043 -0
- package/src/Scope.ts +204 -0
- package/src/ScopedCache.ts +151 -0
- package/src/ScopedRef.ts +117 -0
- package/src/Secret.ts +88 -0
- package/src/SingleProducerAsyncInput.ts +67 -0
- package/src/Sink.ts +1461 -0
- package/src/SortedMap.ts +287 -0
- package/src/SortedSet.ts +390 -0
- package/src/SourceLocation.ts +108 -0
- package/src/Stream.ts +6468 -0
- package/src/StreamEmit.ts +136 -0
- package/src/StreamHaltStrategy.ts +123 -0
- package/src/Streamable.ts +45 -0
- package/src/String.ts +778 -0
- package/src/Struct.ts +243 -0
- package/src/Subscribable.ts +100 -0
- package/src/SubscriptionRef.ts +298 -0
- package/src/Supervisor.ts +240 -0
- package/src/Symbol.ts +29 -0
- package/src/SynchronizedRef.ts +270 -0
- package/src/TArray.ts +495 -0
- package/src/TDeferred.ts +100 -0
- package/src/TMap.ts +515 -0
- package/src/TPriorityQueue.ts +223 -0
- package/src/TPubSub.ts +200 -0
- package/src/TQueue.ts +432 -0
- package/src/TRandom.ts +129 -0
- package/src/TReentrantLock.ts +224 -0
- package/src/TRef.ts +178 -0
- package/src/TSemaphore.ts +129 -0
- package/src/TSet.ts +365 -0
- package/src/TSubscriptionRef.ts +192 -0
- package/src/Take.ts +258 -0
- package/src/TestAnnotation.ts +158 -0
- package/src/TestAnnotationMap.ts +119 -0
- package/src/TestAnnotations.ts +117 -0
- package/src/TestClock.ts +556 -0
- package/src/TestConfig.ts +47 -0
- package/src/TestContext.ts +36 -0
- package/src/TestLive.ts +53 -0
- package/src/TestServices.ts +390 -0
- package/src/TestSized.ts +55 -0
- package/src/Tracer.ts +182 -0
- package/src/Trie.ts +840 -0
- package/src/Tuple.ts +305 -0
- package/src/Types.ts +353 -0
- package/src/Unify.ts +113 -0
- package/src/UpstreamPullRequest.ts +117 -0
- package/src/UpstreamPullStrategy.ts +121 -0
- package/src/Utils.ts +809 -0
- package/src/index.ts +1568 -0
- package/src/internal/array.ts +8 -0
- package/src/internal/blockedRequests.ts +520 -0
- package/src/internal/cache.ts +733 -0
- package/src/internal/cause.ts +1050 -0
- package/src/internal/channel/channelExecutor.ts +1200 -0
- package/src/internal/channel/channelState.ts +134 -0
- package/src/internal/channel/childExecutorDecision.ts +96 -0
- package/src/internal/channel/continuation.ts +200 -0
- package/src/internal/channel/mergeDecision.ts +113 -0
- package/src/internal/channel/mergeState.ts +120 -0
- package/src/internal/channel/mergeStrategy.ts +72 -0
- package/src/internal/channel/singleProducerAsyncInput.ts +259 -0
- package/src/internal/channel/subexecutor.ts +229 -0
- package/src/internal/channel/upstreamPullRequest.ts +84 -0
- package/src/internal/channel/upstreamPullStrategy.ts +87 -0
- package/src/internal/channel.ts +2603 -0
- package/src/internal/clock.ts +95 -0
- package/src/internal/completedRequestMap.ts +9 -0
- package/src/internal/concurrency.ts +54 -0
- package/src/internal/config.ts +716 -0
- package/src/internal/configError.ts +304 -0
- package/src/internal/configProvider/pathPatch.ts +97 -0
- package/src/internal/configProvider.ts +799 -0
- package/src/internal/console.ts +153 -0
- package/src/internal/context.ts +337 -0
- package/src/internal/core-effect.ts +2293 -0
- package/src/internal/core-stream.ts +998 -0
- package/src/internal/core.ts +3189 -0
- package/src/internal/data.ts +36 -0
- package/src/internal/dataSource.ts +327 -0
- package/src/internal/dateTime.ts +1277 -0
- package/src/internal/defaultServices/console.ts +100 -0
- package/src/internal/defaultServices.ts +163 -0
- package/src/internal/deferred.ts +46 -0
- package/src/internal/differ/chunkPatch.ts +211 -0
- package/src/internal/differ/contextPatch.ts +232 -0
- package/src/internal/differ/hashMapPatch.ts +220 -0
- package/src/internal/differ/hashSetPatch.ts +176 -0
- package/src/internal/differ/orPatch.ts +311 -0
- package/src/internal/differ/readonlyArrayPatch.ts +210 -0
- package/src/internal/differ.ts +200 -0
- package/src/internal/doNotation.ts +80 -0
- package/src/internal/effect/circular.ts +895 -0
- package/src/internal/effectable.ts +131 -0
- package/src/internal/either.ts +110 -0
- package/src/internal/encoding/base64.ts +286 -0
- package/src/internal/encoding/base64Url.ts +29 -0
- package/src/internal/encoding/common.ts +51 -0
- package/src/internal/encoding/hex.ts +315 -0
- package/src/internal/errors.ts +7 -0
- package/src/internal/executionPlan.ts +114 -0
- package/src/internal/executionStrategy.ts +74 -0
- package/src/internal/fiber.ts +388 -0
- package/src/internal/fiberId.ts +267 -0
- package/src/internal/fiberMessage.ts +82 -0
- package/src/internal/fiberRefs/patch.ts +144 -0
- package/src/internal/fiberRefs.ts +297 -0
- package/src/internal/fiberRuntime.ts +3842 -0
- package/src/internal/fiberScope.ts +71 -0
- package/src/internal/fiberStatus.ts +119 -0
- package/src/internal/groupBy.ts +530 -0
- package/src/internal/hashMap/array.ts +49 -0
- package/src/internal/hashMap/bitwise.ts +32 -0
- package/src/internal/hashMap/config.ts +14 -0
- package/src/internal/hashMap/keySet.ts +8 -0
- package/src/internal/hashMap/node.ts +391 -0
- package/src/internal/hashMap.ts +586 -0
- package/src/internal/hashSet.ts +323 -0
- package/src/internal/keyedPool.ts +244 -0
- package/src/internal/layer/circular.ts +214 -0
- package/src/internal/layer.ts +1483 -0
- package/src/internal/logSpan.ts +20 -0
- package/src/internal/logger-circular.ts +24 -0
- package/src/internal/logger.ts +522 -0
- package/src/internal/mailbox.ts +561 -0
- package/src/internal/managedRuntime/circular.ts +6 -0
- package/src/internal/managedRuntime.ts +134 -0
- package/src/internal/matcher.ts +652 -0
- package/src/internal/metric/boundaries.ts +75 -0
- package/src/internal/metric/hook.ts +483 -0
- package/src/internal/metric/key.ts +167 -0
- package/src/internal/metric/keyType.ts +238 -0
- package/src/internal/metric/label.ts +41 -0
- package/src/internal/metric/pair.ts +48 -0
- package/src/internal/metric/polling.ts +149 -0
- package/src/internal/metric/registry.ts +187 -0
- package/src/internal/metric/state.ts +290 -0
- package/src/internal/metric.ts +577 -0
- package/src/internal/opCodes/cause.ts +35 -0
- package/src/internal/opCodes/channel.ts +83 -0
- package/src/internal/opCodes/channelChildExecutorDecision.ts +17 -0
- package/src/internal/opCodes/channelMergeDecision.ts +11 -0
- package/src/internal/opCodes/channelMergeState.ts +17 -0
- package/src/internal/opCodes/channelMergeStrategy.ts +11 -0
- package/src/internal/opCodes/channelState.ts +23 -0
- package/src/internal/opCodes/channelUpstreamPullRequest.ts +11 -0
- package/src/internal/opCodes/channelUpstreamPullStrategy.ts +11 -0
- package/src/internal/opCodes/config.ts +65 -0
- package/src/internal/opCodes/configError.ts +35 -0
- package/src/internal/opCodes/continuation.ts +11 -0
- package/src/internal/opCodes/deferred.ts +11 -0
- package/src/internal/opCodes/effect.ts +89 -0
- package/src/internal/opCodes/layer.ts +59 -0
- package/src/internal/opCodes/streamHaltStrategy.ts +23 -0
- package/src/internal/option.ts +80 -0
- package/src/internal/pool.ts +432 -0
- package/src/internal/pubsub.ts +1762 -0
- package/src/internal/query.ts +204 -0
- package/src/internal/queue.ts +766 -0
- package/src/internal/random.ts +161 -0
- package/src/internal/rateLimiter.ts +93 -0
- package/src/internal/rcMap.ts +285 -0
- package/src/internal/rcRef.ts +192 -0
- package/src/internal/redBlackTree/iterator.ts +200 -0
- package/src/internal/redBlackTree/node.ts +68 -0
- package/src/internal/redBlackTree.ts +1245 -0
- package/src/internal/redacted.ts +73 -0
- package/src/internal/ref.ts +171 -0
- package/src/internal/reloadable.ts +140 -0
- package/src/internal/request.ts +177 -0
- package/src/internal/resource.ts +76 -0
- package/src/internal/ringBuffer.ts +68 -0
- package/src/internal/runtime.ts +558 -0
- package/src/internal/runtimeFlags.ts +178 -0
- package/src/internal/runtimeFlagsPatch.ts +103 -0
- package/src/internal/schedule/decision.ts +47 -0
- package/src/internal/schedule/interval.ts +101 -0
- package/src/internal/schedule/intervals.ts +180 -0
- package/src/internal/schedule.ts +2199 -0
- package/src/internal/schema/errors.ts +191 -0
- package/src/internal/schema/schemaId.ts +106 -0
- package/src/internal/schema/util.ts +50 -0
- package/src/internal/scopedCache.ts +644 -0
- package/src/internal/scopedRef.ts +118 -0
- package/src/internal/secret.ts +89 -0
- package/src/internal/singleShotGen.ts +35 -0
- package/src/internal/sink.ts +2120 -0
- package/src/internal/stack.ts +10 -0
- package/src/internal/stm/core.ts +817 -0
- package/src/internal/stm/entry.ts +59 -0
- package/src/internal/stm/journal.ts +123 -0
- package/src/internal/stm/opCodes/stm.ts +71 -0
- package/src/internal/stm/opCodes/stmState.ts +17 -0
- package/src/internal/stm/opCodes/strategy.ts +17 -0
- package/src/internal/stm/opCodes/tExit.ts +29 -0
- package/src/internal/stm/opCodes/tryCommit.ts +11 -0
- package/src/internal/stm/stm.ts +1453 -0
- package/src/internal/stm/stmState.ts +136 -0
- package/src/internal/stm/tArray.ts +550 -0
- package/src/internal/stm/tDeferred.ts +81 -0
- package/src/internal/stm/tExit.ts +190 -0
- package/src/internal/stm/tMap.ts +824 -0
- package/src/internal/stm/tPriorityQueue.ts +267 -0
- package/src/internal/stm/tPubSub.ts +551 -0
- package/src/internal/stm/tQueue.ts +393 -0
- package/src/internal/stm/tRandom.ts +140 -0
- package/src/internal/stm/tReentrantLock.ts +352 -0
- package/src/internal/stm/tRef.ts +195 -0
- package/src/internal/stm/tSemaphore.ts +113 -0
- package/src/internal/stm/tSet.ts +259 -0
- package/src/internal/stm/tSubscriptionRef.ts +286 -0
- package/src/internal/stm/tryCommit.ts +34 -0
- package/src/internal/stm/txnId.ts +14 -0
- package/src/internal/stm/versioned.ts +4 -0
- package/src/internal/stream/debounceState.ts +57 -0
- package/src/internal/stream/emit.ts +123 -0
- package/src/internal/stream/haltStrategy.ts +94 -0
- package/src/internal/stream/handoff.ts +187 -0
- package/src/internal/stream/handoffSignal.ts +59 -0
- package/src/internal/stream/pull.ts +34 -0
- package/src/internal/stream/sinkEndReason.ts +30 -0
- package/src/internal/stream/zipAllState.ts +88 -0
- package/src/internal/stream/zipChunksState.ts +56 -0
- package/src/internal/stream.ts +8801 -0
- package/src/internal/string-utils.ts +107 -0
- package/src/internal/subscriptionRef.ts +138 -0
- package/src/internal/supervisor/patch.ts +190 -0
- package/src/internal/supervisor.ts +303 -0
- package/src/internal/synchronizedRef.ts +114 -0
- package/src/internal/take.ts +199 -0
- package/src/internal/testing/sleep.ts +27 -0
- package/src/internal/testing/suspendedWarningData.ts +85 -0
- package/src/internal/testing/warningData.ts +94 -0
- package/src/internal/tracer.ts +150 -0
- package/src/internal/trie.ts +722 -0
- package/src/internal/version.ts +7 -0
|
@@ -0,0 +1,3842 @@
|
|
|
1
|
+
import * as RA from "../Array.js"
|
|
2
|
+
import * as Boolean from "../Boolean.js"
|
|
3
|
+
import type * as Cause from "../Cause.js"
|
|
4
|
+
import * as Chunk from "../Chunk.js"
|
|
5
|
+
import type * as Clock from "../Clock.js"
|
|
6
|
+
import type { ConfigProvider } from "../ConfigProvider.js"
|
|
7
|
+
import * as Context from "../Context.js"
|
|
8
|
+
import type { DefaultServices } from "../DefaultServices.js"
|
|
9
|
+
import type * as Duration from "../Duration.js"
|
|
10
|
+
import type * as Effect from "../Effect.js"
|
|
11
|
+
import * as Effectable from "../Effectable.js"
|
|
12
|
+
import type * as Either from "../Either.js"
|
|
13
|
+
import * as ExecutionStrategy from "../ExecutionStrategy.js"
|
|
14
|
+
import type * as Exit from "../Exit.js"
|
|
15
|
+
import type * as Fiber from "../Fiber.js"
|
|
16
|
+
import * as FiberId from "../FiberId.js"
|
|
17
|
+
import type * as FiberRef from "../FiberRef.js"
|
|
18
|
+
import * as FiberRefs from "../FiberRefs.js"
|
|
19
|
+
import * as FiberRefsPatch from "../FiberRefsPatch.js"
|
|
20
|
+
import * as FiberStatus from "../FiberStatus.js"
|
|
21
|
+
import type { LazyArg } from "../Function.js"
|
|
22
|
+
import { dual, identity, pipe } from "../Function.js"
|
|
23
|
+
import { globalValue } from "../GlobalValue.js"
|
|
24
|
+
import * as HashMap from "../HashMap.js"
|
|
25
|
+
import * as HashSet from "../HashSet.js"
|
|
26
|
+
import * as Inspectable from "../Inspectable.js"
|
|
27
|
+
import type { Logger } from "../Logger.js"
|
|
28
|
+
import * as LogLevel from "../LogLevel.js"
|
|
29
|
+
import type * as MetricLabel from "../MetricLabel.js"
|
|
30
|
+
import * as Micro from "../Micro.js"
|
|
31
|
+
import * as MRef from "../MutableRef.js"
|
|
32
|
+
import * as Option from "../Option.js"
|
|
33
|
+
import { pipeArguments } from "../Pipeable.js"
|
|
34
|
+
import * as Predicate from "../Predicate.js"
|
|
35
|
+
import type * as Random from "../Random.js"
|
|
36
|
+
import * as Ref from "../Ref.js"
|
|
37
|
+
import type { Entry, Request } from "../Request.js"
|
|
38
|
+
import type * as RequestBlock from "../RequestBlock.js"
|
|
39
|
+
import type * as RuntimeFlags from "../RuntimeFlags.js"
|
|
40
|
+
import * as RuntimeFlagsPatch from "../RuntimeFlagsPatch.js"
|
|
41
|
+
import { currentScheduler, type Scheduler } from "../Scheduler.js"
|
|
42
|
+
import type * as Scope from "../Scope.js"
|
|
43
|
+
import type * as Supervisor from "../Supervisor.js"
|
|
44
|
+
import type * as Tracer from "../Tracer.js"
|
|
45
|
+
import type { Concurrency, NoExcessProperties, NoInfer } from "../Types.js"
|
|
46
|
+
import { internalCall, yieldWrapGet } from "../Utils.js"
|
|
47
|
+
import * as RequestBlock_ from "./blockedRequests.js"
|
|
48
|
+
import * as internalCause from "./cause.js"
|
|
49
|
+
import * as clock from "./clock.js"
|
|
50
|
+
import { currentRequestMap } from "./completedRequestMap.js"
|
|
51
|
+
import * as concurrency from "./concurrency.js"
|
|
52
|
+
import { configProviderTag } from "./configProvider.js"
|
|
53
|
+
import * as internalEffect from "./core-effect.js"
|
|
54
|
+
import * as core from "./core.js"
|
|
55
|
+
import * as defaultServices from "./defaultServices.js"
|
|
56
|
+
import { consoleTag } from "./defaultServices/console.js"
|
|
57
|
+
import * as executionStrategy from "./executionStrategy.js"
|
|
58
|
+
import * as internalFiber from "./fiber.js"
|
|
59
|
+
import * as FiberMessage from "./fiberMessage.js"
|
|
60
|
+
import * as fiberRefs from "./fiberRefs.js"
|
|
61
|
+
import * as fiberScope from "./fiberScope.js"
|
|
62
|
+
import * as internalLogger from "./logger.js"
|
|
63
|
+
import * as metric from "./metric.js"
|
|
64
|
+
import * as metricBoundaries from "./metric/boundaries.js"
|
|
65
|
+
import * as metricLabel from "./metric/label.js"
|
|
66
|
+
import * as OpCodes from "./opCodes/effect.js"
|
|
67
|
+
import { randomTag } from "./random.js"
|
|
68
|
+
import { complete } from "./request.js"
|
|
69
|
+
import * as runtimeFlags_ from "./runtimeFlags.js"
|
|
70
|
+
import { OpSupervision } from "./runtimeFlags.js"
|
|
71
|
+
import * as supervisor from "./supervisor.js"
|
|
72
|
+
import * as SupervisorPatch from "./supervisor/patch.js"
|
|
73
|
+
import * as tracer from "./tracer.js"
|
|
74
|
+
import * as version from "./version.js"
|
|
75
|
+
|
|
76
|
+
/** @internal */
|
|
77
|
+
export const fiberStarted = metric.counter("effect_fiber_started", { incremental: true })
|
|
78
|
+
/** @internal */
|
|
79
|
+
export const fiberActive = metric.counter("effect_fiber_active")
|
|
80
|
+
/** @internal */
|
|
81
|
+
export const fiberSuccesses = metric.counter("effect_fiber_successes", { incremental: true })
|
|
82
|
+
/** @internal */
|
|
83
|
+
export const fiberFailures = metric.counter("effect_fiber_failures", { incremental: true })
|
|
84
|
+
/** @internal */
|
|
85
|
+
export const fiberLifetimes = metric.tagged(
|
|
86
|
+
metric.histogram(
|
|
87
|
+
"effect_fiber_lifetimes",
|
|
88
|
+
metricBoundaries.exponential({
|
|
89
|
+
start: 0.5,
|
|
90
|
+
factor: 2,
|
|
91
|
+
count: 35
|
|
92
|
+
})
|
|
93
|
+
),
|
|
94
|
+
"time_unit",
|
|
95
|
+
"milliseconds"
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
/** @internal */
|
|
99
|
+
type EvaluationSignal =
|
|
100
|
+
| EvaluationSignalContinue
|
|
101
|
+
| EvaluationSignalDone
|
|
102
|
+
| EvaluationSignalYieldNow
|
|
103
|
+
|
|
104
|
+
/** @internal */
|
|
105
|
+
const EvaluationSignalContinue = "Continue" as const
|
|
106
|
+
|
|
107
|
+
/** @internal */
|
|
108
|
+
type EvaluationSignalContinue = typeof EvaluationSignalContinue
|
|
109
|
+
|
|
110
|
+
/** @internal */
|
|
111
|
+
const EvaluationSignalDone = "Done" as const
|
|
112
|
+
|
|
113
|
+
/** @internal */
|
|
114
|
+
type EvaluationSignalDone = typeof EvaluationSignalDone
|
|
115
|
+
|
|
116
|
+
/** @internal */
|
|
117
|
+
const EvaluationSignalYieldNow = "Yield" as const
|
|
118
|
+
|
|
119
|
+
/** @internal */
|
|
120
|
+
type EvaluationSignalYieldNow = typeof EvaluationSignalYieldNow
|
|
121
|
+
|
|
122
|
+
const runtimeFiberVariance = {
|
|
123
|
+
/* c8 ignore next */
|
|
124
|
+
_E: (_: never) => _,
|
|
125
|
+
/* c8 ignore next */
|
|
126
|
+
_A: (_: never) => _
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const absurd = (_: never): never => {
|
|
130
|
+
throw new Error(
|
|
131
|
+
`BUG: FiberRuntime - ${
|
|
132
|
+
Inspectable.toStringUnknown(_)
|
|
133
|
+
} - please report an issue at https://github.com/Effect-TS/effect/issues`
|
|
134
|
+
)
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const YieldedOp = Symbol.for("effect/internal/fiberRuntime/YieldedOp")
|
|
138
|
+
type YieldedOp = typeof YieldedOp
|
|
139
|
+
const yieldedOpChannel: {
|
|
140
|
+
currentOp: core.Primitive | null
|
|
141
|
+
} = globalValue("effect/internal/fiberRuntime/yieldedOpChannel", () => ({
|
|
142
|
+
currentOp: null
|
|
143
|
+
}))
|
|
144
|
+
|
|
145
|
+
const contOpSuccess = {
|
|
146
|
+
[OpCodes.OP_ON_SUCCESS]: (
|
|
147
|
+
_: FiberRuntime<any, any>,
|
|
148
|
+
cont: core.OnSuccess,
|
|
149
|
+
value: unknown
|
|
150
|
+
) => {
|
|
151
|
+
return internalCall(() => cont.effect_instruction_i1(value))
|
|
152
|
+
},
|
|
153
|
+
["OnStep"]: (
|
|
154
|
+
_: FiberRuntime<any, any>,
|
|
155
|
+
_cont: core.OnStep,
|
|
156
|
+
value: unknown
|
|
157
|
+
) => {
|
|
158
|
+
return core.exitSucceed(core.exitSucceed(value))
|
|
159
|
+
},
|
|
160
|
+
[OpCodes.OP_ON_SUCCESS_AND_FAILURE]: (
|
|
161
|
+
_: FiberRuntime<any, any>,
|
|
162
|
+
cont: core.OnSuccessAndFailure,
|
|
163
|
+
value: unknown
|
|
164
|
+
) => {
|
|
165
|
+
return internalCall(() => cont.effect_instruction_i2(value))
|
|
166
|
+
},
|
|
167
|
+
[OpCodes.OP_REVERT_FLAGS]: (
|
|
168
|
+
self: FiberRuntime<any, any>,
|
|
169
|
+
cont: core.RevertFlags,
|
|
170
|
+
value: unknown
|
|
171
|
+
) => {
|
|
172
|
+
self.patchRuntimeFlags(self.currentRuntimeFlags, cont.patch)
|
|
173
|
+
if (runtimeFlags_.interruptible(self.currentRuntimeFlags) && self.isInterrupted()) {
|
|
174
|
+
return core.exitFailCause(self.getInterruptedCause())
|
|
175
|
+
} else {
|
|
176
|
+
return core.exitSucceed(value)
|
|
177
|
+
}
|
|
178
|
+
},
|
|
179
|
+
[OpCodes.OP_WHILE]: (
|
|
180
|
+
self: FiberRuntime<any, any>,
|
|
181
|
+
cont: core.While,
|
|
182
|
+
value: unknown
|
|
183
|
+
) => {
|
|
184
|
+
internalCall(() => cont.effect_instruction_i2(value))
|
|
185
|
+
if (internalCall(() => cont.effect_instruction_i0())) {
|
|
186
|
+
self.pushStack(cont)
|
|
187
|
+
return internalCall(() => cont.effect_instruction_i1())
|
|
188
|
+
} else {
|
|
189
|
+
return core.void
|
|
190
|
+
}
|
|
191
|
+
},
|
|
192
|
+
[OpCodes.OP_ITERATOR]: (
|
|
193
|
+
self: FiberRuntime<any, any>,
|
|
194
|
+
cont: core.FromIterator,
|
|
195
|
+
value: unknown
|
|
196
|
+
) => {
|
|
197
|
+
while (true) {
|
|
198
|
+
const state = internalCall(() => cont.effect_instruction_i0.next(value))
|
|
199
|
+
if (state.done) {
|
|
200
|
+
return core.exitSucceed(state.value)
|
|
201
|
+
}
|
|
202
|
+
const primitive = yieldWrapGet(state.value)
|
|
203
|
+
if (!core.exitIsExit(primitive)) {
|
|
204
|
+
self.pushStack(cont)
|
|
205
|
+
return primitive
|
|
206
|
+
} else if (primitive._tag === "Failure") {
|
|
207
|
+
return primitive
|
|
208
|
+
}
|
|
209
|
+
value = primitive.value
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
const drainQueueWhileRunningTable = {
|
|
215
|
+
[FiberMessage.OP_INTERRUPT_SIGNAL]: (
|
|
216
|
+
self: FiberRuntime<any, any>,
|
|
217
|
+
runtimeFlags: RuntimeFlags.RuntimeFlags,
|
|
218
|
+
cur: Effect.Effect<any, any, any>,
|
|
219
|
+
message: FiberMessage.FiberMessage & { _tag: FiberMessage.OP_INTERRUPT_SIGNAL }
|
|
220
|
+
) => {
|
|
221
|
+
self.processNewInterruptSignal(message.cause)
|
|
222
|
+
return runtimeFlags_.interruptible(runtimeFlags) ? core.exitFailCause(message.cause) : cur
|
|
223
|
+
},
|
|
224
|
+
[FiberMessage.OP_RESUME]: (
|
|
225
|
+
_self: FiberRuntime<any, any>,
|
|
226
|
+
_runtimeFlags: RuntimeFlags.RuntimeFlags,
|
|
227
|
+
_cur: Effect.Effect<any, any, any>,
|
|
228
|
+
_message: FiberMessage.FiberMessage
|
|
229
|
+
) => {
|
|
230
|
+
throw new Error("It is illegal to have multiple concurrent run loops in a single fiber")
|
|
231
|
+
},
|
|
232
|
+
[FiberMessage.OP_STATEFUL]: (
|
|
233
|
+
self: FiberRuntime<any, any>,
|
|
234
|
+
runtimeFlags: RuntimeFlags.RuntimeFlags,
|
|
235
|
+
cur: Effect.Effect<any, any, any>,
|
|
236
|
+
message: FiberMessage.FiberMessage & { _tag: FiberMessage.OP_STATEFUL }
|
|
237
|
+
) => {
|
|
238
|
+
message.onFiber(self, FiberStatus.running(runtimeFlags))
|
|
239
|
+
return cur
|
|
240
|
+
},
|
|
241
|
+
[FiberMessage.OP_YIELD_NOW]: (
|
|
242
|
+
_self: FiberRuntime<any, any>,
|
|
243
|
+
_runtimeFlags: RuntimeFlags.RuntimeFlags,
|
|
244
|
+
cur: Effect.Effect<any, any, any>,
|
|
245
|
+
_message: FiberMessage.FiberMessage & { _tag: FiberMessage.OP_YIELD_NOW }
|
|
246
|
+
) => {
|
|
247
|
+
return core.flatMap(core.yieldNow(), () => cur)
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* Executes all requests, submitting requests to each data source in parallel.
|
|
253
|
+
*/
|
|
254
|
+
const runBlockedRequests = (self: RequestBlock.RequestBlock) =>
|
|
255
|
+
core.forEachSequentialDiscard(
|
|
256
|
+
RequestBlock_.flatten(self),
|
|
257
|
+
(requestsByRequestResolver) =>
|
|
258
|
+
forEachConcurrentDiscard(
|
|
259
|
+
RequestBlock_.sequentialCollectionToChunk(requestsByRequestResolver),
|
|
260
|
+
([dataSource, sequential]) => {
|
|
261
|
+
const map = new Map<Request<any, any>, Entry<any>>()
|
|
262
|
+
const arr: Array<Array<Entry<any>>> = []
|
|
263
|
+
for (const block of sequential) {
|
|
264
|
+
arr.push(Chunk.toReadonlyArray(block) as any)
|
|
265
|
+
for (const entry of block) {
|
|
266
|
+
map.set(entry.request as Request<any, any>, entry)
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
const flat = arr.flat()
|
|
270
|
+
return core.fiberRefLocally(
|
|
271
|
+
invokeWithInterrupt(dataSource.runAll(arr), flat, () =>
|
|
272
|
+
flat.forEach((entry) => {
|
|
273
|
+
entry.listeners.interrupted = true
|
|
274
|
+
})),
|
|
275
|
+
currentRequestMap,
|
|
276
|
+
map
|
|
277
|
+
)
|
|
278
|
+
},
|
|
279
|
+
false,
|
|
280
|
+
false
|
|
281
|
+
)
|
|
282
|
+
)
|
|
283
|
+
|
|
284
|
+
/** @internal */
|
|
285
|
+
export interface Snapshot {
|
|
286
|
+
refs: FiberRefs.FiberRefs
|
|
287
|
+
flags: RuntimeFlags.RuntimeFlags
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
const _version = version.getCurrentVersion()
|
|
291
|
+
|
|
292
|
+
/** @internal */
|
|
293
|
+
export class FiberRuntime<in out A, in out E = never> extends Effectable.Class<A, E>
|
|
294
|
+
implements Fiber.RuntimeFiber<A, E>
|
|
295
|
+
{
|
|
296
|
+
readonly [internalFiber.FiberTypeId] = internalFiber.fiberVariance
|
|
297
|
+
readonly [internalFiber.RuntimeFiberTypeId] = runtimeFiberVariance
|
|
298
|
+
private _fiberRefs: FiberRefs.FiberRefs
|
|
299
|
+
private _fiberId: FiberId.Runtime
|
|
300
|
+
private _queue = new Array<FiberMessage.FiberMessage>()
|
|
301
|
+
private _children: Set<FiberRuntime<any, any>> | null = null
|
|
302
|
+
private _observers = new Array<(exit: Exit.Exit<A, E>) => void>()
|
|
303
|
+
private _running = false
|
|
304
|
+
private _stack: Array<core.Continuation> = []
|
|
305
|
+
private _asyncInterruptor: ((effect: Effect.Effect<any, any, any>) => any) | null = null
|
|
306
|
+
private _asyncBlockingOn: FiberId.FiberId | null = null
|
|
307
|
+
private _exitValue: Exit.Exit<A, E> | null = null
|
|
308
|
+
private _steps: Array<Snapshot> = []
|
|
309
|
+
private _isYielding = false
|
|
310
|
+
|
|
311
|
+
public currentRuntimeFlags: RuntimeFlags.RuntimeFlags
|
|
312
|
+
public currentOpCount: number = 0
|
|
313
|
+
public currentSupervisor!: Supervisor.Supervisor<any>
|
|
314
|
+
public currentScheduler!: Scheduler
|
|
315
|
+
public currentTracer!: Tracer.Tracer
|
|
316
|
+
public currentSpan!: Tracer.AnySpan | undefined
|
|
317
|
+
public currentContext!: Context.Context<never>
|
|
318
|
+
public currentDefaultServices!: Context.Context<DefaultServices>
|
|
319
|
+
|
|
320
|
+
constructor(
|
|
321
|
+
fiberId: FiberId.Runtime,
|
|
322
|
+
fiberRefs0: FiberRefs.FiberRefs,
|
|
323
|
+
runtimeFlags0: RuntimeFlags.RuntimeFlags
|
|
324
|
+
) {
|
|
325
|
+
super()
|
|
326
|
+
this.currentRuntimeFlags = runtimeFlags0
|
|
327
|
+
this._fiberId = fiberId
|
|
328
|
+
this._fiberRefs = fiberRefs0
|
|
329
|
+
if (runtimeFlags_.runtimeMetrics(runtimeFlags0)) {
|
|
330
|
+
const tags = this.getFiberRef(core.currentMetricLabels)
|
|
331
|
+
fiberStarted.unsafeUpdate(1, tags)
|
|
332
|
+
fiberActive.unsafeUpdate(1, tags)
|
|
333
|
+
}
|
|
334
|
+
this.refreshRefCache()
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
commit(): Effect.Effect<A, E, never> {
|
|
338
|
+
return internalFiber.join(this)
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
/**
|
|
342
|
+
* The identity of the fiber.
|
|
343
|
+
*/
|
|
344
|
+
id(): FiberId.Runtime {
|
|
345
|
+
return this._fiberId
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
/**
|
|
349
|
+
* Begins execution of the effect associated with this fiber on in the
|
|
350
|
+
* background. This can be called to "kick off" execution of a fiber after
|
|
351
|
+
* it has been created.
|
|
352
|
+
*/
|
|
353
|
+
resume<A, E>(effect: Effect.Effect<A, E, any>): void {
|
|
354
|
+
this.tell(FiberMessage.resume(effect))
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
/**
|
|
358
|
+
* The status of the fiber.
|
|
359
|
+
*/
|
|
360
|
+
get status(): Effect.Effect<FiberStatus.FiberStatus> {
|
|
361
|
+
return this.ask((_, status) => status)
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
/**
|
|
365
|
+
* Gets the fiber runtime flags.
|
|
366
|
+
*/
|
|
367
|
+
get runtimeFlags(): Effect.Effect<RuntimeFlags.RuntimeFlags> {
|
|
368
|
+
return this.ask((state, status) => {
|
|
369
|
+
if (FiberStatus.isDone(status)) {
|
|
370
|
+
return state.currentRuntimeFlags
|
|
371
|
+
}
|
|
372
|
+
return status.runtimeFlags
|
|
373
|
+
})
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
/**
|
|
377
|
+
* Returns the current `FiberScope` for the fiber.
|
|
378
|
+
*/
|
|
379
|
+
scope(): fiberScope.FiberScope {
|
|
380
|
+
return fiberScope.unsafeMake(this)
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
/**
|
|
384
|
+
* Retrieves the immediate children of the fiber.
|
|
385
|
+
*/
|
|
386
|
+
get children(): Effect.Effect<Array<Fiber.RuntimeFiber<any, any>>> {
|
|
387
|
+
return this.ask((fiber) => Array.from(fiber.getChildren()))
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
/**
|
|
391
|
+
* Gets the fiber's set of children.
|
|
392
|
+
*/
|
|
393
|
+
getChildren(): Set<FiberRuntime<any, any>> {
|
|
394
|
+
if (this._children === null) {
|
|
395
|
+
this._children = new Set()
|
|
396
|
+
}
|
|
397
|
+
return this._children
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
/**
|
|
401
|
+
* Retrieves the interrupted cause of the fiber, which will be `Cause.empty`
|
|
402
|
+
* if the fiber has not been interrupted.
|
|
403
|
+
*
|
|
404
|
+
* **NOTE**: This method is safe to invoke on any fiber, but if not invoked
|
|
405
|
+
* on this fiber, then values derived from the fiber's state (including the
|
|
406
|
+
* log annotations and log level) may not be up-to-date.
|
|
407
|
+
*/
|
|
408
|
+
getInterruptedCause() {
|
|
409
|
+
return this.getFiberRef(core.currentInterruptedCause)
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
/**
|
|
413
|
+
* Retrieves the whole set of fiber refs.
|
|
414
|
+
*/
|
|
415
|
+
fiberRefs(): Effect.Effect<FiberRefs.FiberRefs> {
|
|
416
|
+
return this.ask((fiber) => fiber.getFiberRefs())
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
/**
|
|
420
|
+
* Returns an effect that will contain information computed from the fiber
|
|
421
|
+
* state and status while running on the fiber.
|
|
422
|
+
*
|
|
423
|
+
* This allows the outside world to interact safely with mutable fiber state
|
|
424
|
+
* without locks or immutable data.
|
|
425
|
+
*/
|
|
426
|
+
ask<Z>(
|
|
427
|
+
f: (runtime: FiberRuntime<any, any>, status: FiberStatus.FiberStatus) => Z
|
|
428
|
+
): Effect.Effect<Z> {
|
|
429
|
+
return core.suspend(() => {
|
|
430
|
+
const deferred = core.deferredUnsafeMake<Z>(this._fiberId)
|
|
431
|
+
this.tell(
|
|
432
|
+
FiberMessage.stateful((fiber, status) => {
|
|
433
|
+
core.deferredUnsafeDone(deferred, core.sync(() => f(fiber, status)))
|
|
434
|
+
})
|
|
435
|
+
)
|
|
436
|
+
return core.deferredAwait(deferred)
|
|
437
|
+
})
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
/**
|
|
441
|
+
* Adds a message to be processed by the fiber on the fiber.
|
|
442
|
+
*/
|
|
443
|
+
tell(message: FiberMessage.FiberMessage): void {
|
|
444
|
+
this._queue.push(message)
|
|
445
|
+
if (!this._running) {
|
|
446
|
+
this._running = true
|
|
447
|
+
this.drainQueueLaterOnExecutor()
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
get await(): Effect.Effect<Exit.Exit<A, E>> {
|
|
452
|
+
return core.async((resume) => {
|
|
453
|
+
const cb = (exit: Exit.Exit<A, E>) => resume(core.succeed(exit))
|
|
454
|
+
this.tell(
|
|
455
|
+
FiberMessage.stateful((fiber, _) => {
|
|
456
|
+
if (fiber._exitValue !== null) {
|
|
457
|
+
cb(this._exitValue!)
|
|
458
|
+
} else {
|
|
459
|
+
fiber.addObserver(cb)
|
|
460
|
+
}
|
|
461
|
+
})
|
|
462
|
+
)
|
|
463
|
+
return core.sync(() =>
|
|
464
|
+
this.tell(
|
|
465
|
+
FiberMessage.stateful((fiber, _) => {
|
|
466
|
+
fiber.removeObserver(cb)
|
|
467
|
+
})
|
|
468
|
+
)
|
|
469
|
+
)
|
|
470
|
+
}, this.id())
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
get inheritAll(): Effect.Effect<void> {
|
|
474
|
+
return core.withFiberRuntime((parentFiber, parentStatus) => {
|
|
475
|
+
const parentFiberId = parentFiber.id()
|
|
476
|
+
const parentFiberRefs = parentFiber.getFiberRefs()
|
|
477
|
+
const parentRuntimeFlags = parentStatus.runtimeFlags
|
|
478
|
+
const childFiberRefs = this.getFiberRefs()
|
|
479
|
+
const updatedFiberRefs = fiberRefs.joinAs(parentFiberRefs, parentFiberId, childFiberRefs)
|
|
480
|
+
|
|
481
|
+
parentFiber.setFiberRefs(updatedFiberRefs)
|
|
482
|
+
|
|
483
|
+
const updatedRuntimeFlags = parentFiber.getFiberRef(currentRuntimeFlags)
|
|
484
|
+
|
|
485
|
+
const patch = pipe(
|
|
486
|
+
runtimeFlags_.diff(parentRuntimeFlags, updatedRuntimeFlags),
|
|
487
|
+
// Do not inherit WindDown or Interruption!
|
|
488
|
+
RuntimeFlagsPatch.exclude(runtimeFlags_.Interruption),
|
|
489
|
+
RuntimeFlagsPatch.exclude(runtimeFlags_.WindDown)
|
|
490
|
+
)
|
|
491
|
+
|
|
492
|
+
return core.updateRuntimeFlags(patch)
|
|
493
|
+
})
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
/**
|
|
497
|
+
* Tentatively observes the fiber, but returns immediately if it is not
|
|
498
|
+
* already done.
|
|
499
|
+
*/
|
|
500
|
+
get poll(): Effect.Effect<Option.Option<Exit.Exit<A, E>>> {
|
|
501
|
+
return core.sync(() => Option.fromNullable(this._exitValue))
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
/**
|
|
505
|
+
* Unsafely observes the fiber, but returns immediately if it is not
|
|
506
|
+
* already done.
|
|
507
|
+
*/
|
|
508
|
+
unsafePoll(): Exit.Exit<A, E> | null {
|
|
509
|
+
return this._exitValue
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
/**
|
|
513
|
+
* In the background, interrupts the fiber as if interrupted from the specified fiber.
|
|
514
|
+
*/
|
|
515
|
+
interruptAsFork(fiberId: FiberId.FiberId): Effect.Effect<void> {
|
|
516
|
+
return core.sync(() => this.tell(FiberMessage.interruptSignal(internalCause.interrupt(fiberId))))
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
/**
|
|
520
|
+
* In the background, interrupts the fiber as if interrupted from the specified fiber.
|
|
521
|
+
*/
|
|
522
|
+
unsafeInterruptAsFork(fiberId: FiberId.FiberId) {
|
|
523
|
+
this.tell(FiberMessage.interruptSignal(internalCause.interrupt(fiberId)))
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
/**
|
|
527
|
+
* Adds an observer to the list of observers.
|
|
528
|
+
*
|
|
529
|
+
* **NOTE**: This method must be invoked by the fiber itself.
|
|
530
|
+
*/
|
|
531
|
+
addObserver(observer: (exit: Exit.Exit<A, E>) => void): void {
|
|
532
|
+
if (this._exitValue !== null) {
|
|
533
|
+
observer(this._exitValue!)
|
|
534
|
+
} else {
|
|
535
|
+
this._observers.push(observer)
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
/**
|
|
540
|
+
* Removes the specified observer from the list of observers that will be
|
|
541
|
+
* notified when the fiber exits.
|
|
542
|
+
*
|
|
543
|
+
* **NOTE**: This method must be invoked by the fiber itself.
|
|
544
|
+
*/
|
|
545
|
+
removeObserver(observer: (exit: Exit.Exit<A, E>) => void): void {
|
|
546
|
+
this._observers = this._observers.filter((o) => o !== observer)
|
|
547
|
+
}
|
|
548
|
+
/**
|
|
549
|
+
* Retrieves all fiber refs of the fiber.
|
|
550
|
+
*
|
|
551
|
+
* **NOTE**: This method is safe to invoke on any fiber, but if not invoked
|
|
552
|
+
* on this fiber, then values derived from the fiber's state (including the
|
|
553
|
+
* log annotations and log level) may not be up-to-date.
|
|
554
|
+
*/
|
|
555
|
+
getFiberRefs(): FiberRefs.FiberRefs {
|
|
556
|
+
this.setFiberRef(currentRuntimeFlags, this.currentRuntimeFlags)
|
|
557
|
+
return this._fiberRefs
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
/**
|
|
561
|
+
* Deletes the specified fiber ref.
|
|
562
|
+
*
|
|
563
|
+
* **NOTE**: This method must be invoked by the fiber itself.
|
|
564
|
+
*/
|
|
565
|
+
unsafeDeleteFiberRef<X>(fiberRef: FiberRef.FiberRef<X>): void {
|
|
566
|
+
this._fiberRefs = fiberRefs.delete_(this._fiberRefs, fiberRef)
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
/**
|
|
570
|
+
* Retrieves the state of the fiber ref, or else its initial value.
|
|
571
|
+
*
|
|
572
|
+
* **NOTE**: This method is safe to invoke on any fiber, but if not invoked
|
|
573
|
+
* on this fiber, then values derived from the fiber's state (including the
|
|
574
|
+
* log annotations and log level) may not be up-to-date.
|
|
575
|
+
*/
|
|
576
|
+
getFiberRef<X>(fiberRef: FiberRef.FiberRef<X>): X {
|
|
577
|
+
if (this._fiberRefs.locals.has(fiberRef)) {
|
|
578
|
+
return this._fiberRefs.locals.get(fiberRef)![0][1] as X
|
|
579
|
+
}
|
|
580
|
+
return fiberRef.initial
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
/**
|
|
584
|
+
* Sets the fiber ref to the specified value.
|
|
585
|
+
*
|
|
586
|
+
* **NOTE**: This method must be invoked by the fiber itself.
|
|
587
|
+
*/
|
|
588
|
+
setFiberRef<X>(fiberRef: FiberRef.FiberRef<X>, value: X): void {
|
|
589
|
+
this._fiberRefs = fiberRefs.updateAs(this._fiberRefs, {
|
|
590
|
+
fiberId: this._fiberId,
|
|
591
|
+
fiberRef,
|
|
592
|
+
value
|
|
593
|
+
})
|
|
594
|
+
this.refreshRefCache()
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
refreshRefCache() {
|
|
598
|
+
this.currentDefaultServices = this.getFiberRef(defaultServices.currentServices)
|
|
599
|
+
this.currentTracer = this.currentDefaultServices.unsafeMap.get(tracer.tracerTag.key)
|
|
600
|
+
this.currentSupervisor = this.getFiberRef(currentSupervisor)
|
|
601
|
+
this.currentScheduler = this.getFiberRef(currentScheduler)
|
|
602
|
+
this.currentContext = this.getFiberRef(core.currentContext)
|
|
603
|
+
this.currentSpan = this.currentContext.unsafeMap.get(tracer.spanTag.key)
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
/**
|
|
607
|
+
* Wholesale replaces all fiber refs of this fiber.
|
|
608
|
+
*
|
|
609
|
+
* **NOTE**: This method must be invoked by the fiber itself.
|
|
610
|
+
*/
|
|
611
|
+
setFiberRefs(fiberRefs: FiberRefs.FiberRefs): void {
|
|
612
|
+
this._fiberRefs = fiberRefs
|
|
613
|
+
this.refreshRefCache()
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
/**
|
|
617
|
+
* Adds a reference to the specified fiber inside the children set.
|
|
618
|
+
*
|
|
619
|
+
* **NOTE**: This method must be invoked by the fiber itself.
|
|
620
|
+
*/
|
|
621
|
+
addChild(child: FiberRuntime<any, any>) {
|
|
622
|
+
this.getChildren().add(child)
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
/**
|
|
626
|
+
* Removes a reference to the specified fiber inside the children set.
|
|
627
|
+
*
|
|
628
|
+
* **NOTE**: This method must be invoked by the fiber itself.
|
|
629
|
+
*/
|
|
630
|
+
removeChild(child: FiberRuntime<any, any>) {
|
|
631
|
+
this.getChildren().delete(child)
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
/**
|
|
635
|
+
* Transfers all children of this fiber that are currently running to the
|
|
636
|
+
* specified fiber scope.
|
|
637
|
+
*
|
|
638
|
+
* **NOTE**: This method must be invoked by the fiber itself after it has
|
|
639
|
+
* evaluated the effects but prior to exiting.
|
|
640
|
+
*/
|
|
641
|
+
transferChildren(scope: fiberScope.FiberScope) {
|
|
642
|
+
const children = this._children
|
|
643
|
+
// Clear the children of the current fiber
|
|
644
|
+
this._children = null
|
|
645
|
+
if (children !== null && children.size > 0) {
|
|
646
|
+
for (const child of children) {
|
|
647
|
+
// If the child is still running, add it to the scope
|
|
648
|
+
if (child._exitValue === null) {
|
|
649
|
+
scope.add(this.currentRuntimeFlags, child)
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
/**
|
|
656
|
+
* On the current thread, executes all messages in the fiber's inbox. This
|
|
657
|
+
* method may return before all work is done, in the event the fiber executes
|
|
658
|
+
* an asynchronous operation.
|
|
659
|
+
*
|
|
660
|
+
* **NOTE**: This method must be invoked by the fiber itself.
|
|
661
|
+
*/
|
|
662
|
+
drainQueueOnCurrentThread() {
|
|
663
|
+
let recurse = true
|
|
664
|
+
while (recurse) {
|
|
665
|
+
let evaluationSignal: EvaluationSignal = EvaluationSignalContinue
|
|
666
|
+
const prev = (globalThis as any)[internalFiber.currentFiberURI]
|
|
667
|
+
;(globalThis as any)[internalFiber.currentFiberURI] = this
|
|
668
|
+
try {
|
|
669
|
+
while (evaluationSignal === EvaluationSignalContinue) {
|
|
670
|
+
evaluationSignal = this._queue.length === 0 ?
|
|
671
|
+
EvaluationSignalDone :
|
|
672
|
+
this.evaluateMessageWhileSuspended(this._queue.splice(0, 1)[0]!)
|
|
673
|
+
}
|
|
674
|
+
} finally {
|
|
675
|
+
this._running = false
|
|
676
|
+
;(globalThis as any)[internalFiber.currentFiberURI] = prev
|
|
677
|
+
}
|
|
678
|
+
// Maybe someone added something to the queue between us checking, and us
|
|
679
|
+
// giving up the drain. If so, we need to restart the draining, but only
|
|
680
|
+
// if we beat everyone else to the restart:
|
|
681
|
+
if (this._queue.length > 0 && !this._running) {
|
|
682
|
+
this._running = true
|
|
683
|
+
if (evaluationSignal === EvaluationSignalYieldNow) {
|
|
684
|
+
this.drainQueueLaterOnExecutor()
|
|
685
|
+
recurse = false
|
|
686
|
+
} else {
|
|
687
|
+
recurse = true
|
|
688
|
+
}
|
|
689
|
+
} else {
|
|
690
|
+
recurse = false
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
/**
|
|
696
|
+
* Schedules the execution of all messages in the fiber's inbox.
|
|
697
|
+
*
|
|
698
|
+
* This method will return immediately after the scheduling
|
|
699
|
+
* operation is completed, but potentially before such messages have been
|
|
700
|
+
* executed.
|
|
701
|
+
*
|
|
702
|
+
* **NOTE**: This method must be invoked by the fiber itself.
|
|
703
|
+
*/
|
|
704
|
+
drainQueueLaterOnExecutor() {
|
|
705
|
+
this.currentScheduler.scheduleTask(
|
|
706
|
+
this.run,
|
|
707
|
+
this.getFiberRef(core.currentSchedulingPriority)
|
|
708
|
+
)
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
/**
|
|
712
|
+
* Drains the fiber's message queue while the fiber is actively running,
|
|
713
|
+
* returning the next effect to execute, which may be the input effect if no
|
|
714
|
+
* additional effect needs to be executed.
|
|
715
|
+
*
|
|
716
|
+
* **NOTE**: This method must be invoked by the fiber itself.
|
|
717
|
+
*/
|
|
718
|
+
drainQueueWhileRunning(
|
|
719
|
+
runtimeFlags: RuntimeFlags.RuntimeFlags,
|
|
720
|
+
cur0: Effect.Effect<any, any, any>
|
|
721
|
+
) {
|
|
722
|
+
let cur = cur0
|
|
723
|
+
while (this._queue.length > 0) {
|
|
724
|
+
const message = this._queue.splice(0, 1)[0]
|
|
725
|
+
// @ts-expect-error
|
|
726
|
+
cur = drainQueueWhileRunningTable[message._tag](this, runtimeFlags, cur, message)
|
|
727
|
+
}
|
|
728
|
+
return cur
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
/**
|
|
732
|
+
* Determines if the fiber is interrupted.
|
|
733
|
+
*
|
|
734
|
+
* **NOTE**: This method is safe to invoke on any fiber, but if not invoked
|
|
735
|
+
* on this fiber, then values derived from the fiber's state (including the
|
|
736
|
+
* log annotations and log level) may not be up-to-date.
|
|
737
|
+
*/
|
|
738
|
+
isInterrupted(): boolean {
|
|
739
|
+
return !internalCause.isEmpty(this.getFiberRef(core.currentInterruptedCause))
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
/**
|
|
743
|
+
* Adds an interruptor to the set of interruptors that are interrupting this
|
|
744
|
+
* fiber.
|
|
745
|
+
*
|
|
746
|
+
* **NOTE**: This method must be invoked by the fiber itself.
|
|
747
|
+
*/
|
|
748
|
+
addInterruptedCause(cause: Cause.Cause<never>) {
|
|
749
|
+
const oldSC = this.getFiberRef(core.currentInterruptedCause)
|
|
750
|
+
this.setFiberRef(core.currentInterruptedCause, internalCause.sequential(oldSC, cause))
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
/**
|
|
754
|
+
* Processes a new incoming interrupt signal.
|
|
755
|
+
*
|
|
756
|
+
* **NOTE**: This method must be invoked by the fiber itself.
|
|
757
|
+
*/
|
|
758
|
+
processNewInterruptSignal(cause: Cause.Cause<never>): void {
|
|
759
|
+
this.addInterruptedCause(cause)
|
|
760
|
+
this.sendInterruptSignalToAllChildren()
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
/**
|
|
764
|
+
* Interrupts all children of the current fiber, returning an effect that will
|
|
765
|
+
* await the exit of the children. This method will return null if the fiber
|
|
766
|
+
* has no children.
|
|
767
|
+
*
|
|
768
|
+
* **NOTE**: This method must be invoked by the fiber itself.
|
|
769
|
+
*/
|
|
770
|
+
sendInterruptSignalToAllChildren(): boolean {
|
|
771
|
+
if (this._children === null || this._children.size === 0) {
|
|
772
|
+
return false
|
|
773
|
+
}
|
|
774
|
+
let told = false
|
|
775
|
+
for (const child of this._children) {
|
|
776
|
+
child.tell(FiberMessage.interruptSignal(internalCause.interrupt(this.id())))
|
|
777
|
+
told = true
|
|
778
|
+
}
|
|
779
|
+
return told
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
/**
|
|
783
|
+
* Interrupts all children of the current fiber, returning an effect that will
|
|
784
|
+
* await the exit of the children. This method will return null if the fiber
|
|
785
|
+
* has no children.
|
|
786
|
+
*
|
|
787
|
+
* **NOTE**: This method must be invoked by the fiber itself.
|
|
788
|
+
*/
|
|
789
|
+
interruptAllChildren() {
|
|
790
|
+
if (this.sendInterruptSignalToAllChildren()) {
|
|
791
|
+
const it = this._children!.values()
|
|
792
|
+
this._children = null
|
|
793
|
+
let isDone = false
|
|
794
|
+
const body = () => {
|
|
795
|
+
const next = it.next()
|
|
796
|
+
if (!next.done) {
|
|
797
|
+
return core.asVoid(next.value.await)
|
|
798
|
+
} else {
|
|
799
|
+
return core.sync(() => {
|
|
800
|
+
isDone = true
|
|
801
|
+
})
|
|
802
|
+
}
|
|
803
|
+
}
|
|
804
|
+
return core.whileLoop({
|
|
805
|
+
while: () => !isDone,
|
|
806
|
+
body,
|
|
807
|
+
step: () => {
|
|
808
|
+
//
|
|
809
|
+
}
|
|
810
|
+
})
|
|
811
|
+
}
|
|
812
|
+
return null
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
reportExitValue(exit: Exit.Exit<A, E>) {
|
|
816
|
+
if (runtimeFlags_.runtimeMetrics(this.currentRuntimeFlags)) {
|
|
817
|
+
const tags = this.getFiberRef(core.currentMetricLabels)
|
|
818
|
+
const startTimeMillis = this.id().startTimeMillis
|
|
819
|
+
const endTimeMillis = Date.now()
|
|
820
|
+
fiberLifetimes.unsafeUpdate(endTimeMillis - startTimeMillis, tags)
|
|
821
|
+
fiberActive.unsafeUpdate(-1, tags)
|
|
822
|
+
switch (exit._tag) {
|
|
823
|
+
case OpCodes.OP_SUCCESS: {
|
|
824
|
+
fiberSuccesses.unsafeUpdate(1, tags)
|
|
825
|
+
break
|
|
826
|
+
}
|
|
827
|
+
case OpCodes.OP_FAILURE: {
|
|
828
|
+
fiberFailures.unsafeUpdate(1, tags)
|
|
829
|
+
break
|
|
830
|
+
}
|
|
831
|
+
}
|
|
832
|
+
}
|
|
833
|
+
if (exit._tag === "Failure") {
|
|
834
|
+
const level = this.getFiberRef(core.currentUnhandledErrorLogLevel)
|
|
835
|
+
if (!internalCause.isInterruptedOnly(exit.cause) && level._tag === "Some") {
|
|
836
|
+
this.log("Fiber terminated with an unhandled error", exit.cause, level)
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
setExitValue(exit: Exit.Exit<A, E>) {
|
|
842
|
+
this._exitValue = exit
|
|
843
|
+
this.reportExitValue(exit)
|
|
844
|
+
for (let i = this._observers.length - 1; i >= 0; i--) {
|
|
845
|
+
this._observers[i](exit)
|
|
846
|
+
}
|
|
847
|
+
this._observers = []
|
|
848
|
+
}
|
|
849
|
+
|
|
850
|
+
getLoggers() {
|
|
851
|
+
return this.getFiberRef(currentLoggers)
|
|
852
|
+
}
|
|
853
|
+
|
|
854
|
+
log(
|
|
855
|
+
message: unknown,
|
|
856
|
+
cause: Cause.Cause<any>,
|
|
857
|
+
overrideLogLevel: Option.Option<LogLevel.LogLevel>
|
|
858
|
+
): void {
|
|
859
|
+
const logLevel = Option.isSome(overrideLogLevel) ?
|
|
860
|
+
overrideLogLevel.value :
|
|
861
|
+
this.getFiberRef(core.currentLogLevel)
|
|
862
|
+
const minimumLogLevel = this.getFiberRef(currentMinimumLogLevel)
|
|
863
|
+
if (LogLevel.greaterThan(minimumLogLevel, logLevel)) {
|
|
864
|
+
return
|
|
865
|
+
}
|
|
866
|
+
const spans = this.getFiberRef(core.currentLogSpan)
|
|
867
|
+
const annotations = this.getFiberRef(core.currentLogAnnotations)
|
|
868
|
+
const loggers = this.getLoggers()
|
|
869
|
+
const contextMap = this.getFiberRefs()
|
|
870
|
+
if (HashSet.size(loggers) > 0) {
|
|
871
|
+
const clockService = Context.get(this.getFiberRef(defaultServices.currentServices), clock.clockTag)
|
|
872
|
+
const date = new Date(clockService.unsafeCurrentTimeMillis())
|
|
873
|
+
Inspectable.withRedactableContext(contextMap, () => {
|
|
874
|
+
for (const logger of loggers) {
|
|
875
|
+
logger.log({
|
|
876
|
+
fiberId: this.id(),
|
|
877
|
+
logLevel,
|
|
878
|
+
message,
|
|
879
|
+
cause,
|
|
880
|
+
context: contextMap,
|
|
881
|
+
spans,
|
|
882
|
+
annotations,
|
|
883
|
+
date
|
|
884
|
+
})
|
|
885
|
+
}
|
|
886
|
+
})
|
|
887
|
+
}
|
|
888
|
+
}
|
|
889
|
+
|
|
890
|
+
/**
|
|
891
|
+
* Evaluates a single message on the current thread, while the fiber is
|
|
892
|
+
* suspended. This method should only be called while evaluation of the
|
|
893
|
+
* fiber's effect is suspended due to an asynchronous operation.
|
|
894
|
+
*
|
|
895
|
+
* **NOTE**: This method must be invoked by the fiber itself.
|
|
896
|
+
*/
|
|
897
|
+
evaluateMessageWhileSuspended(message: FiberMessage.FiberMessage): EvaluationSignal {
|
|
898
|
+
switch (message._tag) {
|
|
899
|
+
case FiberMessage.OP_YIELD_NOW: {
|
|
900
|
+
return EvaluationSignalYieldNow
|
|
901
|
+
}
|
|
902
|
+
case FiberMessage.OP_INTERRUPT_SIGNAL: {
|
|
903
|
+
this.processNewInterruptSignal(message.cause)
|
|
904
|
+
if (this._asyncInterruptor !== null) {
|
|
905
|
+
this._asyncInterruptor(core.exitFailCause(message.cause))
|
|
906
|
+
this._asyncInterruptor = null
|
|
907
|
+
}
|
|
908
|
+
return EvaluationSignalContinue
|
|
909
|
+
}
|
|
910
|
+
case FiberMessage.OP_RESUME: {
|
|
911
|
+
this._asyncInterruptor = null
|
|
912
|
+
this._asyncBlockingOn = null
|
|
913
|
+
this.evaluateEffect(message.effect)
|
|
914
|
+
return EvaluationSignalContinue
|
|
915
|
+
}
|
|
916
|
+
case FiberMessage.OP_STATEFUL: {
|
|
917
|
+
message.onFiber(
|
|
918
|
+
this,
|
|
919
|
+
this._exitValue !== null ?
|
|
920
|
+
FiberStatus.done :
|
|
921
|
+
FiberStatus.suspended(this.currentRuntimeFlags, this._asyncBlockingOn!)
|
|
922
|
+
)
|
|
923
|
+
return EvaluationSignalContinue
|
|
924
|
+
}
|
|
925
|
+
default: {
|
|
926
|
+
return absurd(message)
|
|
927
|
+
}
|
|
928
|
+
}
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
/**
|
|
932
|
+
* Evaluates an effect until completion, potentially asynchronously.
|
|
933
|
+
*
|
|
934
|
+
* **NOTE**: This method must be invoked by the fiber itself.
|
|
935
|
+
*/
|
|
936
|
+
evaluateEffect(effect0: Effect.Effect<any, any, any>) {
|
|
937
|
+
this.currentSupervisor.onResume(this)
|
|
938
|
+
try {
|
|
939
|
+
let effect: Effect.Effect<any, any, any> | null =
|
|
940
|
+
runtimeFlags_.interruptible(this.currentRuntimeFlags) && this.isInterrupted() ?
|
|
941
|
+
core.exitFailCause(this.getInterruptedCause()) :
|
|
942
|
+
effect0
|
|
943
|
+
while (effect !== null) {
|
|
944
|
+
const eff: Effect.Effect<any, any, any> = effect
|
|
945
|
+
const exit = this.runLoop(eff)
|
|
946
|
+
if (exit === YieldedOp) {
|
|
947
|
+
const op = yieldedOpChannel.currentOp!
|
|
948
|
+
yieldedOpChannel.currentOp = null
|
|
949
|
+
if (op._op === OpCodes.OP_YIELD) {
|
|
950
|
+
if (runtimeFlags_.cooperativeYielding(this.currentRuntimeFlags)) {
|
|
951
|
+
this.tell(FiberMessage.yieldNow())
|
|
952
|
+
this.tell(FiberMessage.resume(core.exitVoid))
|
|
953
|
+
effect = null
|
|
954
|
+
} else {
|
|
955
|
+
effect = core.exitVoid
|
|
956
|
+
}
|
|
957
|
+
} else if (op._op === OpCodes.OP_ASYNC) {
|
|
958
|
+
// Terminate this evaluation, async resumption will continue evaluation:
|
|
959
|
+
effect = null
|
|
960
|
+
}
|
|
961
|
+
} else {
|
|
962
|
+
this.currentRuntimeFlags = pipe(this.currentRuntimeFlags, runtimeFlags_.enable(runtimeFlags_.WindDown))
|
|
963
|
+
const interruption = this.interruptAllChildren()
|
|
964
|
+
if (interruption !== null) {
|
|
965
|
+
effect = core.flatMap(interruption, () => exit)
|
|
966
|
+
} else {
|
|
967
|
+
if (this._queue.length === 0) {
|
|
968
|
+
// No more messages to process, so we will allow the fiber to end life:
|
|
969
|
+
this.setExitValue(exit)
|
|
970
|
+
} else {
|
|
971
|
+
// There are messages, possibly added by the final op executed by
|
|
972
|
+
// the fiber. To be safe, we should execute those now before we
|
|
973
|
+
// allow the fiber to end life:
|
|
974
|
+
this.tell(FiberMessage.resume(exit))
|
|
975
|
+
}
|
|
976
|
+
effect = null
|
|
977
|
+
}
|
|
978
|
+
}
|
|
979
|
+
}
|
|
980
|
+
} finally {
|
|
981
|
+
this.currentSupervisor.onSuspend(this)
|
|
982
|
+
}
|
|
983
|
+
}
|
|
984
|
+
|
|
985
|
+
/**
|
|
986
|
+
* Begins execution of the effect associated with this fiber on the current
|
|
987
|
+
* thread. This can be called to "kick off" execution of a fiber after it has
|
|
988
|
+
* been created, in hopes that the effect can be executed synchronously.
|
|
989
|
+
*
|
|
990
|
+
* This is not the normal way of starting a fiber, but it is useful when the
|
|
991
|
+
* express goal of executing the fiber is to synchronously produce its exit.
|
|
992
|
+
*/
|
|
993
|
+
start<R>(effect: Effect.Effect<A, E, R>): void {
|
|
994
|
+
if (!this._running) {
|
|
995
|
+
this._running = true
|
|
996
|
+
const prev = (globalThis as any)[internalFiber.currentFiberURI]
|
|
997
|
+
;(globalThis as any)[internalFiber.currentFiberURI] = this
|
|
998
|
+
try {
|
|
999
|
+
this.evaluateEffect(effect)
|
|
1000
|
+
} finally {
|
|
1001
|
+
this._running = false
|
|
1002
|
+
;(globalThis as any)[internalFiber.currentFiberURI] = prev
|
|
1003
|
+
// Because we're special casing `start`, we have to be responsible
|
|
1004
|
+
// for spinning up the fiber if there were new messages added to
|
|
1005
|
+
// the queue between the completion of the effect and the transition
|
|
1006
|
+
// to the not running state.
|
|
1007
|
+
if (this._queue.length > 0) {
|
|
1008
|
+
this.drainQueueLaterOnExecutor()
|
|
1009
|
+
}
|
|
1010
|
+
}
|
|
1011
|
+
} else {
|
|
1012
|
+
this.tell(FiberMessage.resume(effect))
|
|
1013
|
+
}
|
|
1014
|
+
}
|
|
1015
|
+
|
|
1016
|
+
/**
|
|
1017
|
+
* Begins execution of the effect associated with this fiber on in the
|
|
1018
|
+
* background, and on the correct thread pool. This can be called to "kick
|
|
1019
|
+
* off" execution of a fiber after it has been created, in hopes that the
|
|
1020
|
+
* effect can be executed synchronously.
|
|
1021
|
+
*/
|
|
1022
|
+
startFork<R>(effect: Effect.Effect<A, E, R>): void {
|
|
1023
|
+
this.tell(FiberMessage.resume(effect))
|
|
1024
|
+
}
|
|
1025
|
+
|
|
1026
|
+
/**
|
|
1027
|
+
* Takes the current runtime flags, patches them to return the new runtime
|
|
1028
|
+
* flags, and then makes any changes necessary to fiber state based on the
|
|
1029
|
+
* specified patch.
|
|
1030
|
+
*
|
|
1031
|
+
* **NOTE**: This method must be invoked by the fiber itself.
|
|
1032
|
+
*/
|
|
1033
|
+
patchRuntimeFlags(oldRuntimeFlags: RuntimeFlags.RuntimeFlags, patch: RuntimeFlagsPatch.RuntimeFlagsPatch) {
|
|
1034
|
+
const newRuntimeFlags = runtimeFlags_.patch(oldRuntimeFlags, patch)
|
|
1035
|
+
;(globalThis as any)[internalFiber.currentFiberURI] = this
|
|
1036
|
+
this.currentRuntimeFlags = newRuntimeFlags
|
|
1037
|
+
return newRuntimeFlags
|
|
1038
|
+
}
|
|
1039
|
+
|
|
1040
|
+
/**
|
|
1041
|
+
* Initiates an asynchronous operation, by building a callback that will
|
|
1042
|
+
* resume execution, and then feeding that callback to the registration
|
|
1043
|
+
* function, handling error cases and repeated resumptions appropriately.
|
|
1044
|
+
*
|
|
1045
|
+
* **NOTE**: This method must be invoked by the fiber itself.
|
|
1046
|
+
*/
|
|
1047
|
+
initiateAsync(
|
|
1048
|
+
runtimeFlags: RuntimeFlags.RuntimeFlags,
|
|
1049
|
+
asyncRegister: (resume: (effect: Effect.Effect<any, any, any>) => void) => void
|
|
1050
|
+
) {
|
|
1051
|
+
let alreadyCalled = false
|
|
1052
|
+
const callback = (effect: Effect.Effect<any, any, any>) => {
|
|
1053
|
+
if (!alreadyCalled) {
|
|
1054
|
+
alreadyCalled = true
|
|
1055
|
+
this.tell(FiberMessage.resume(effect))
|
|
1056
|
+
}
|
|
1057
|
+
}
|
|
1058
|
+
if (runtimeFlags_.interruptible(runtimeFlags)) {
|
|
1059
|
+
this._asyncInterruptor = callback
|
|
1060
|
+
}
|
|
1061
|
+
try {
|
|
1062
|
+
asyncRegister(callback)
|
|
1063
|
+
} catch (e) {
|
|
1064
|
+
callback(core.failCause(internalCause.die(e)))
|
|
1065
|
+
}
|
|
1066
|
+
}
|
|
1067
|
+
|
|
1068
|
+
pushStack(cont: core.Continuation) {
|
|
1069
|
+
this._stack.push(cont)
|
|
1070
|
+
if (cont._op === "OnStep") {
|
|
1071
|
+
this._steps.push({ refs: this.getFiberRefs(), flags: this.currentRuntimeFlags })
|
|
1072
|
+
}
|
|
1073
|
+
}
|
|
1074
|
+
|
|
1075
|
+
popStack() {
|
|
1076
|
+
const item = this._stack.pop()
|
|
1077
|
+
if (item) {
|
|
1078
|
+
if (item._op === "OnStep") {
|
|
1079
|
+
this._steps.pop()
|
|
1080
|
+
}
|
|
1081
|
+
return item
|
|
1082
|
+
}
|
|
1083
|
+
return
|
|
1084
|
+
}
|
|
1085
|
+
|
|
1086
|
+
getNextSuccessCont() {
|
|
1087
|
+
let frame = this.popStack()
|
|
1088
|
+
while (frame) {
|
|
1089
|
+
if (frame._op !== OpCodes.OP_ON_FAILURE) {
|
|
1090
|
+
return frame
|
|
1091
|
+
}
|
|
1092
|
+
frame = this.popStack()
|
|
1093
|
+
}
|
|
1094
|
+
}
|
|
1095
|
+
|
|
1096
|
+
getNextFailCont() {
|
|
1097
|
+
let frame = this.popStack()
|
|
1098
|
+
while (frame) {
|
|
1099
|
+
if (frame._op !== OpCodes.OP_ON_SUCCESS && frame._op !== OpCodes.OP_WHILE && frame._op !== OpCodes.OP_ITERATOR) {
|
|
1100
|
+
return frame
|
|
1101
|
+
}
|
|
1102
|
+
frame = this.popStack()
|
|
1103
|
+
}
|
|
1104
|
+
}
|
|
1105
|
+
|
|
1106
|
+
[OpCodes.OP_TAG](op: core.Primitive & { _op: OpCodes.OP_SYNC }) {
|
|
1107
|
+
return core.sync(() => Context.unsafeGet(this.currentContext, op as unknown as Context.Tag<any, any>))
|
|
1108
|
+
}
|
|
1109
|
+
|
|
1110
|
+
["Left"](op: core.Primitive & { _op: "Left" }) {
|
|
1111
|
+
return core.fail(op.left)
|
|
1112
|
+
}
|
|
1113
|
+
|
|
1114
|
+
["None"](_: core.Primitive & { _op: "None" }) {
|
|
1115
|
+
return core.fail(new core.NoSuchElementException())
|
|
1116
|
+
}
|
|
1117
|
+
|
|
1118
|
+
["Right"](op: core.Primitive & { _op: "Right" }) {
|
|
1119
|
+
return core.exitSucceed(op.right)
|
|
1120
|
+
}
|
|
1121
|
+
|
|
1122
|
+
["Some"](op: core.Primitive & { _op: "Some" }) {
|
|
1123
|
+
return core.exitSucceed(op.value)
|
|
1124
|
+
}
|
|
1125
|
+
|
|
1126
|
+
["Micro"](op: Micro.Micro<any, any, never> & { _op: "Micro" }) {
|
|
1127
|
+
return core.unsafeAsync<any, any>((microResume) => {
|
|
1128
|
+
let resume = microResume
|
|
1129
|
+
const fiber = Micro.runFork(Micro.provideContext(op, this.currentContext))
|
|
1130
|
+
fiber.addObserver((exit) => {
|
|
1131
|
+
if (exit._tag === "Success") {
|
|
1132
|
+
return resume(core.exitSucceed(exit.value))
|
|
1133
|
+
}
|
|
1134
|
+
switch (exit.cause._tag) {
|
|
1135
|
+
case "Interrupt": {
|
|
1136
|
+
return resume(core.exitFailCause(internalCause.interrupt(FiberId.none)))
|
|
1137
|
+
}
|
|
1138
|
+
case "Fail": {
|
|
1139
|
+
return resume(core.fail(exit.cause.error))
|
|
1140
|
+
}
|
|
1141
|
+
case "Die": {
|
|
1142
|
+
return resume(core.die(exit.cause.defect))
|
|
1143
|
+
}
|
|
1144
|
+
}
|
|
1145
|
+
})
|
|
1146
|
+
return core.unsafeAsync<void>((abortResume) => {
|
|
1147
|
+
resume = (_: any) => {
|
|
1148
|
+
abortResume(core.void)
|
|
1149
|
+
}
|
|
1150
|
+
fiber.unsafeInterrupt()
|
|
1151
|
+
})
|
|
1152
|
+
})
|
|
1153
|
+
}
|
|
1154
|
+
|
|
1155
|
+
[OpCodes.OP_SYNC](op: core.Primitive & { _op: OpCodes.OP_SYNC }) {
|
|
1156
|
+
const value = internalCall(() => op.effect_instruction_i0())
|
|
1157
|
+
const cont = this.getNextSuccessCont()
|
|
1158
|
+
if (cont !== undefined) {
|
|
1159
|
+
if (!(cont._op in contOpSuccess)) {
|
|
1160
|
+
// @ts-expect-error
|
|
1161
|
+
absurd(cont)
|
|
1162
|
+
}
|
|
1163
|
+
// @ts-expect-error
|
|
1164
|
+
return contOpSuccess[cont._op](this, cont, value)
|
|
1165
|
+
} else {
|
|
1166
|
+
yieldedOpChannel.currentOp = core.exitSucceed(value) as any
|
|
1167
|
+
return YieldedOp
|
|
1168
|
+
}
|
|
1169
|
+
}
|
|
1170
|
+
|
|
1171
|
+
[OpCodes.OP_SUCCESS](op: core.Primitive & { _op: OpCodes.OP_SUCCESS }) {
|
|
1172
|
+
const oldCur = op
|
|
1173
|
+
const cont = this.getNextSuccessCont()
|
|
1174
|
+
if (cont !== undefined) {
|
|
1175
|
+
if (!(cont._op in contOpSuccess)) {
|
|
1176
|
+
// @ts-expect-error
|
|
1177
|
+
absurd(cont)
|
|
1178
|
+
}
|
|
1179
|
+
// @ts-expect-error
|
|
1180
|
+
return contOpSuccess[cont._op](this, cont, oldCur.effect_instruction_i0)
|
|
1181
|
+
} else {
|
|
1182
|
+
yieldedOpChannel.currentOp = oldCur
|
|
1183
|
+
return YieldedOp
|
|
1184
|
+
}
|
|
1185
|
+
}
|
|
1186
|
+
|
|
1187
|
+
[OpCodes.OP_FAILURE](op: core.Primitive & { _op: OpCodes.OP_FAILURE }) {
|
|
1188
|
+
const cause = op.effect_instruction_i0
|
|
1189
|
+
const cont = this.getNextFailCont()
|
|
1190
|
+
if (cont !== undefined) {
|
|
1191
|
+
switch (cont._op) {
|
|
1192
|
+
case OpCodes.OP_ON_FAILURE:
|
|
1193
|
+
case OpCodes.OP_ON_SUCCESS_AND_FAILURE: {
|
|
1194
|
+
if (!(runtimeFlags_.interruptible(this.currentRuntimeFlags) && this.isInterrupted())) {
|
|
1195
|
+
return internalCall(() => cont.effect_instruction_i1(cause))
|
|
1196
|
+
} else {
|
|
1197
|
+
return core.exitFailCause(internalCause.stripFailures(cause))
|
|
1198
|
+
}
|
|
1199
|
+
}
|
|
1200
|
+
case "OnStep": {
|
|
1201
|
+
if (!(runtimeFlags_.interruptible(this.currentRuntimeFlags) && this.isInterrupted())) {
|
|
1202
|
+
return core.exitSucceed(core.exitFailCause(cause))
|
|
1203
|
+
} else {
|
|
1204
|
+
return core.exitFailCause(internalCause.stripFailures(cause))
|
|
1205
|
+
}
|
|
1206
|
+
}
|
|
1207
|
+
case OpCodes.OP_REVERT_FLAGS: {
|
|
1208
|
+
this.patchRuntimeFlags(this.currentRuntimeFlags, cont.patch)
|
|
1209
|
+
if (runtimeFlags_.interruptible(this.currentRuntimeFlags) && this.isInterrupted()) {
|
|
1210
|
+
return core.exitFailCause(internalCause.sequential(cause, this.getInterruptedCause()))
|
|
1211
|
+
} else {
|
|
1212
|
+
return core.exitFailCause(cause)
|
|
1213
|
+
}
|
|
1214
|
+
}
|
|
1215
|
+
default: {
|
|
1216
|
+
absurd(cont)
|
|
1217
|
+
}
|
|
1218
|
+
}
|
|
1219
|
+
} else {
|
|
1220
|
+
yieldedOpChannel.currentOp = core.exitFailCause(cause) as any
|
|
1221
|
+
return YieldedOp
|
|
1222
|
+
}
|
|
1223
|
+
}
|
|
1224
|
+
|
|
1225
|
+
[OpCodes.OP_WITH_RUNTIME](op: core.Primitive & { _op: OpCodes.OP_WITH_RUNTIME }) {
|
|
1226
|
+
return internalCall(() =>
|
|
1227
|
+
op.effect_instruction_i0(
|
|
1228
|
+
this as FiberRuntime<unknown, unknown>,
|
|
1229
|
+
FiberStatus.running(this.currentRuntimeFlags) as FiberStatus.Running
|
|
1230
|
+
)
|
|
1231
|
+
)
|
|
1232
|
+
}
|
|
1233
|
+
|
|
1234
|
+
["Blocked"](op: core.Primitive & { _op: "Blocked" }) {
|
|
1235
|
+
const refs = this.getFiberRefs()
|
|
1236
|
+
const flags = this.currentRuntimeFlags
|
|
1237
|
+
if (this._steps.length > 0) {
|
|
1238
|
+
const frames: Array<core.Continuation> = []
|
|
1239
|
+
const snap = this._steps[this._steps.length - 1]
|
|
1240
|
+
let frame = this.popStack()
|
|
1241
|
+
while (frame && frame._op !== "OnStep") {
|
|
1242
|
+
frames.push(frame)
|
|
1243
|
+
frame = this.popStack()
|
|
1244
|
+
}
|
|
1245
|
+
this.setFiberRefs(snap.refs)
|
|
1246
|
+
this.currentRuntimeFlags = snap.flags
|
|
1247
|
+
const patchRefs = FiberRefsPatch.diff(snap.refs, refs)
|
|
1248
|
+
const patchFlags = runtimeFlags_.diff(snap.flags, flags)
|
|
1249
|
+
return core.exitSucceed(core.blocked(
|
|
1250
|
+
op.effect_instruction_i0,
|
|
1251
|
+
core.withFiberRuntime<unknown, unknown>((newFiber) => {
|
|
1252
|
+
while (frames.length > 0) {
|
|
1253
|
+
newFiber.pushStack(frames.pop()!)
|
|
1254
|
+
}
|
|
1255
|
+
newFiber.setFiberRefs(
|
|
1256
|
+
FiberRefsPatch.patch(newFiber.id(), newFiber.getFiberRefs())(patchRefs)
|
|
1257
|
+
)
|
|
1258
|
+
newFiber.currentRuntimeFlags = runtimeFlags_.patch(patchFlags)(newFiber.currentRuntimeFlags)
|
|
1259
|
+
return op.effect_instruction_i1
|
|
1260
|
+
})
|
|
1261
|
+
))
|
|
1262
|
+
}
|
|
1263
|
+
return core.uninterruptibleMask((restore) =>
|
|
1264
|
+
core.flatMap(
|
|
1265
|
+
forkDaemon(core.runRequestBlock(op.effect_instruction_i0)),
|
|
1266
|
+
() => restore(op.effect_instruction_i1)
|
|
1267
|
+
)
|
|
1268
|
+
)
|
|
1269
|
+
}
|
|
1270
|
+
|
|
1271
|
+
["RunBlocked"](op: core.Primitive & { _op: "RunBlocked" }) {
|
|
1272
|
+
return runBlockedRequests(op.effect_instruction_i0)
|
|
1273
|
+
}
|
|
1274
|
+
|
|
1275
|
+
[OpCodes.OP_UPDATE_RUNTIME_FLAGS](op: core.Primitive & { _op: OpCodes.OP_UPDATE_RUNTIME_FLAGS }) {
|
|
1276
|
+
const updateFlags = op.effect_instruction_i0
|
|
1277
|
+
const oldRuntimeFlags = this.currentRuntimeFlags
|
|
1278
|
+
const newRuntimeFlags = runtimeFlags_.patch(oldRuntimeFlags, updateFlags)
|
|
1279
|
+
// One more chance to short circuit: if we're immediately going
|
|
1280
|
+
// to interrupt. Interruption will cause immediate reversion of
|
|
1281
|
+
// the flag, so as long as we "peek ahead", there's no need to
|
|
1282
|
+
// set them to begin with.
|
|
1283
|
+
if (runtimeFlags_.interruptible(newRuntimeFlags) && this.isInterrupted()) {
|
|
1284
|
+
return core.exitFailCause(this.getInterruptedCause())
|
|
1285
|
+
} else {
|
|
1286
|
+
// Impossible to short circuit, so record the changes
|
|
1287
|
+
this.patchRuntimeFlags(this.currentRuntimeFlags, updateFlags)
|
|
1288
|
+
if (op.effect_instruction_i1) {
|
|
1289
|
+
// Since we updated the flags, we need to revert them
|
|
1290
|
+
const revertFlags = runtimeFlags_.diff(newRuntimeFlags, oldRuntimeFlags)
|
|
1291
|
+
this.pushStack(new core.RevertFlags(revertFlags, op))
|
|
1292
|
+
return internalCall(() => op.effect_instruction_i1!(oldRuntimeFlags))
|
|
1293
|
+
} else {
|
|
1294
|
+
return core.exitVoid
|
|
1295
|
+
}
|
|
1296
|
+
}
|
|
1297
|
+
}
|
|
1298
|
+
|
|
1299
|
+
[OpCodes.OP_ON_SUCCESS](op: core.Primitive & { _op: OpCodes.OP_ON_SUCCESS }) {
|
|
1300
|
+
this.pushStack(op)
|
|
1301
|
+
return op.effect_instruction_i0
|
|
1302
|
+
}
|
|
1303
|
+
|
|
1304
|
+
["OnStep"](op: core.Primitive & { _op: "OnStep" }) {
|
|
1305
|
+
this.pushStack(op)
|
|
1306
|
+
return op.effect_instruction_i0
|
|
1307
|
+
}
|
|
1308
|
+
|
|
1309
|
+
[OpCodes.OP_ON_FAILURE](op: core.Primitive & { _op: OpCodes.OP_ON_FAILURE }) {
|
|
1310
|
+
this.pushStack(op)
|
|
1311
|
+
return op.effect_instruction_i0
|
|
1312
|
+
}
|
|
1313
|
+
|
|
1314
|
+
[OpCodes.OP_ON_SUCCESS_AND_FAILURE](op: core.Primitive & { _op: OpCodes.OP_ON_SUCCESS_AND_FAILURE }) {
|
|
1315
|
+
this.pushStack(op)
|
|
1316
|
+
return op.effect_instruction_i0
|
|
1317
|
+
}
|
|
1318
|
+
|
|
1319
|
+
[OpCodes.OP_ASYNC](op: core.Primitive & { _op: OpCodes.OP_ASYNC }) {
|
|
1320
|
+
this._asyncBlockingOn = op.effect_instruction_i1
|
|
1321
|
+
this.initiateAsync(this.currentRuntimeFlags, op.effect_instruction_i0)
|
|
1322
|
+
yieldedOpChannel.currentOp = op
|
|
1323
|
+
return YieldedOp
|
|
1324
|
+
}
|
|
1325
|
+
|
|
1326
|
+
[OpCodes.OP_YIELD](op: core.Primitive & { op: OpCodes.OP_YIELD }) {
|
|
1327
|
+
this._isYielding = false
|
|
1328
|
+
yieldedOpChannel.currentOp = op
|
|
1329
|
+
return YieldedOp
|
|
1330
|
+
}
|
|
1331
|
+
|
|
1332
|
+
[OpCodes.OP_WHILE](op: core.Primitive & { _op: OpCodes.OP_WHILE }) {
|
|
1333
|
+
const check = op.effect_instruction_i0
|
|
1334
|
+
const body = op.effect_instruction_i1
|
|
1335
|
+
if (check()) {
|
|
1336
|
+
this.pushStack(op)
|
|
1337
|
+
return body()
|
|
1338
|
+
} else {
|
|
1339
|
+
return core.exitVoid
|
|
1340
|
+
}
|
|
1341
|
+
}
|
|
1342
|
+
|
|
1343
|
+
[OpCodes.OP_ITERATOR](op: core.Primitive & { _op: OpCodes.OP_ITERATOR }) {
|
|
1344
|
+
return contOpSuccess[OpCodes.OP_ITERATOR](this, op, undefined)
|
|
1345
|
+
}
|
|
1346
|
+
|
|
1347
|
+
[OpCodes.OP_COMMIT](op: core.Primitive & { _op: OpCodes.OP_COMMIT }) {
|
|
1348
|
+
return internalCall(() => op.commit())
|
|
1349
|
+
}
|
|
1350
|
+
|
|
1351
|
+
/**
|
|
1352
|
+
* The main run-loop for evaluating effects.
|
|
1353
|
+
*
|
|
1354
|
+
* **NOTE**: This method must be invoked by the fiber itself.
|
|
1355
|
+
*/
|
|
1356
|
+
runLoop(effect0: Effect.Effect<any, any, any>): Exit.Exit<any, any> | YieldedOp {
|
|
1357
|
+
let cur: Effect.Effect<any, any, any> | YieldedOp = effect0
|
|
1358
|
+
this.currentOpCount = 0
|
|
1359
|
+
|
|
1360
|
+
while (true) {
|
|
1361
|
+
if ((this.currentRuntimeFlags & OpSupervision) !== 0) {
|
|
1362
|
+
this.currentSupervisor.onEffect(this, cur)
|
|
1363
|
+
}
|
|
1364
|
+
if (this._queue.length > 0) {
|
|
1365
|
+
cur = this.drainQueueWhileRunning(this.currentRuntimeFlags, cur)
|
|
1366
|
+
}
|
|
1367
|
+
if (!this._isYielding) {
|
|
1368
|
+
this.currentOpCount += 1
|
|
1369
|
+
const shouldYield = this.currentScheduler.shouldYield(this)
|
|
1370
|
+
if (shouldYield !== false) {
|
|
1371
|
+
this._isYielding = true
|
|
1372
|
+
this.currentOpCount = 0
|
|
1373
|
+
const oldCur = cur
|
|
1374
|
+
cur = core.flatMap(core.yieldNow({ priority: shouldYield }), () => oldCur)
|
|
1375
|
+
}
|
|
1376
|
+
}
|
|
1377
|
+
try {
|
|
1378
|
+
// @ts-expect-error
|
|
1379
|
+
cur = this.currentTracer.context(
|
|
1380
|
+
() => {
|
|
1381
|
+
if (_version !== (cur as core.Primitive)[core.EffectTypeId]._V) {
|
|
1382
|
+
const level = this.getFiberRef(core.currentVersionMismatchErrorLogLevel)
|
|
1383
|
+
if (level._tag === "Some") {
|
|
1384
|
+
const effectVersion = (cur as core.Primitive)[core.EffectTypeId]._V
|
|
1385
|
+
this.log(
|
|
1386
|
+
`Executing an Effect versioned ${effectVersion} with a Runtime of version ${version.getCurrentVersion()}, you may want to dedupe the effect dependencies, you can use the language service plugin to detect this at compile time: https://github.com/Effect-TS/language-service`,
|
|
1387
|
+
internalCause.empty,
|
|
1388
|
+
level
|
|
1389
|
+
)
|
|
1390
|
+
}
|
|
1391
|
+
}
|
|
1392
|
+
// @ts-expect-error
|
|
1393
|
+
return this[(cur as core.Primitive)._op](cur as core.Primitive)
|
|
1394
|
+
},
|
|
1395
|
+
this
|
|
1396
|
+
)
|
|
1397
|
+
|
|
1398
|
+
if (cur === YieldedOp) {
|
|
1399
|
+
const op = yieldedOpChannel.currentOp!
|
|
1400
|
+
if (
|
|
1401
|
+
op._op === OpCodes.OP_YIELD ||
|
|
1402
|
+
op._op === OpCodes.OP_ASYNC
|
|
1403
|
+
) {
|
|
1404
|
+
return YieldedOp
|
|
1405
|
+
}
|
|
1406
|
+
|
|
1407
|
+
yieldedOpChannel.currentOp = null
|
|
1408
|
+
return (
|
|
1409
|
+
op._op === OpCodes.OP_SUCCESS ||
|
|
1410
|
+
op._op === OpCodes.OP_FAILURE
|
|
1411
|
+
) ?
|
|
1412
|
+
op as unknown as Exit.Exit<A, E> :
|
|
1413
|
+
core.exitFailCause(internalCause.die(op))
|
|
1414
|
+
}
|
|
1415
|
+
} catch (e) {
|
|
1416
|
+
if (cur !== YieldedOp && !Predicate.hasProperty(cur, "_op") || !((cur as core.Primitive)._op in this)) {
|
|
1417
|
+
cur = core.dieMessage(`Not a valid effect: ${Inspectable.toStringUnknown(cur)}`)
|
|
1418
|
+
} else if (core.isInterruptedException(e)) {
|
|
1419
|
+
cur = core.exitFailCause(
|
|
1420
|
+
internalCause.sequential(internalCause.die(e), internalCause.interrupt(FiberId.none))
|
|
1421
|
+
)
|
|
1422
|
+
} else {
|
|
1423
|
+
cur = core.die(e)
|
|
1424
|
+
}
|
|
1425
|
+
}
|
|
1426
|
+
}
|
|
1427
|
+
}
|
|
1428
|
+
|
|
1429
|
+
run = () => {
|
|
1430
|
+
this.drainQueueOnCurrentThread()
|
|
1431
|
+
}
|
|
1432
|
+
}
|
|
1433
|
+
|
|
1434
|
+
// circular with Logger
|
|
1435
|
+
|
|
1436
|
+
/** @internal */
|
|
1437
|
+
export const currentMinimumLogLevel: FiberRef.FiberRef<LogLevel.LogLevel> = globalValue(
|
|
1438
|
+
"effect/FiberRef/currentMinimumLogLevel",
|
|
1439
|
+
() => core.fiberRefUnsafeMake<LogLevel.LogLevel>(LogLevel.fromLiteral("Info"))
|
|
1440
|
+
)
|
|
1441
|
+
|
|
1442
|
+
/** @internal */
|
|
1443
|
+
export const loggerWithConsoleLog = <M, O>(self: Logger<M, O>): Logger<M, void> =>
|
|
1444
|
+
internalLogger.makeLogger((opts) => {
|
|
1445
|
+
const services = FiberRefs.getOrDefault(opts.context, defaultServices.currentServices)
|
|
1446
|
+
Context.get(services, consoleTag).unsafe.log(self.log(opts))
|
|
1447
|
+
})
|
|
1448
|
+
|
|
1449
|
+
/** @internal */
|
|
1450
|
+
export const loggerWithLeveledLog = <M, O>(self: Logger<M, O>): Logger<M, void> =>
|
|
1451
|
+
internalLogger.makeLogger((opts) => {
|
|
1452
|
+
const services = FiberRefs.getOrDefault(opts.context, defaultServices.currentServices)
|
|
1453
|
+
const unsafeLogger = Context.get(services, consoleTag).unsafe
|
|
1454
|
+
switch (opts.logLevel._tag) {
|
|
1455
|
+
case "Debug":
|
|
1456
|
+
return unsafeLogger.debug(self.log(opts))
|
|
1457
|
+
case "Info":
|
|
1458
|
+
return unsafeLogger.info(self.log(opts))
|
|
1459
|
+
case "Trace":
|
|
1460
|
+
return unsafeLogger.trace(self.log(opts))
|
|
1461
|
+
case "Warning":
|
|
1462
|
+
return unsafeLogger.warn(self.log(opts))
|
|
1463
|
+
case "Error":
|
|
1464
|
+
case "Fatal":
|
|
1465
|
+
return unsafeLogger.error(self.log(opts))
|
|
1466
|
+
default:
|
|
1467
|
+
return unsafeLogger.log(self.log(opts))
|
|
1468
|
+
}
|
|
1469
|
+
})
|
|
1470
|
+
|
|
1471
|
+
/** @internal */
|
|
1472
|
+
export const loggerWithConsoleError = <M, O>(self: Logger<M, O>): Logger<M, void> =>
|
|
1473
|
+
internalLogger.makeLogger((opts) => {
|
|
1474
|
+
const services = FiberRefs.getOrDefault(opts.context, defaultServices.currentServices)
|
|
1475
|
+
Context.get(services, consoleTag).unsafe.error(self.log(opts))
|
|
1476
|
+
})
|
|
1477
|
+
|
|
1478
|
+
/** @internal */
|
|
1479
|
+
export const defaultLogger: Logger<unknown, void> = globalValue(
|
|
1480
|
+
Symbol.for("effect/Logger/defaultLogger"),
|
|
1481
|
+
() => loggerWithConsoleLog(internalLogger.stringLogger)
|
|
1482
|
+
)
|
|
1483
|
+
|
|
1484
|
+
/** @internal */
|
|
1485
|
+
export const jsonLogger: Logger<unknown, void> = globalValue(
|
|
1486
|
+
Symbol.for("effect/Logger/jsonLogger"),
|
|
1487
|
+
() => loggerWithConsoleLog(internalLogger.jsonLogger)
|
|
1488
|
+
)
|
|
1489
|
+
|
|
1490
|
+
/** @internal */
|
|
1491
|
+
export const logFmtLogger: Logger<unknown, void> = globalValue(
|
|
1492
|
+
Symbol.for("effect/Logger/logFmtLogger"),
|
|
1493
|
+
() => loggerWithConsoleLog(internalLogger.logfmtLogger)
|
|
1494
|
+
)
|
|
1495
|
+
|
|
1496
|
+
/** @internal */
|
|
1497
|
+
export const prettyLogger: Logger<unknown, void> = globalValue(
|
|
1498
|
+
Symbol.for("effect/Logger/prettyLogger"),
|
|
1499
|
+
() => internalLogger.prettyLoggerDefault
|
|
1500
|
+
)
|
|
1501
|
+
|
|
1502
|
+
/** @internal */
|
|
1503
|
+
export const structuredLogger: Logger<unknown, void> = globalValue(
|
|
1504
|
+
Symbol.for("effect/Logger/structuredLogger"),
|
|
1505
|
+
() => loggerWithConsoleLog(internalLogger.structuredLogger)
|
|
1506
|
+
)
|
|
1507
|
+
|
|
1508
|
+
/** @internal */
|
|
1509
|
+
export const tracerLogger = globalValue(
|
|
1510
|
+
Symbol.for("effect/Logger/tracerLogger"),
|
|
1511
|
+
() =>
|
|
1512
|
+
internalLogger.makeLogger<unknown, void>(({
|
|
1513
|
+
annotations,
|
|
1514
|
+
cause,
|
|
1515
|
+
context,
|
|
1516
|
+
fiberId,
|
|
1517
|
+
logLevel,
|
|
1518
|
+
message
|
|
1519
|
+
}) => {
|
|
1520
|
+
const span = Context.getOption(
|
|
1521
|
+
fiberRefs.getOrDefault(context, core.currentContext),
|
|
1522
|
+
tracer.spanTag
|
|
1523
|
+
)
|
|
1524
|
+
if (span._tag === "None" || span.value._tag === "ExternalSpan") {
|
|
1525
|
+
return
|
|
1526
|
+
}
|
|
1527
|
+
const clockService = Context.unsafeGet(
|
|
1528
|
+
fiberRefs.getOrDefault(context, defaultServices.currentServices),
|
|
1529
|
+
clock.clockTag
|
|
1530
|
+
)
|
|
1531
|
+
|
|
1532
|
+
const attributes: Record<string, unknown> = {}
|
|
1533
|
+
for (const [key, value] of annotations) {
|
|
1534
|
+
attributes[key] = value
|
|
1535
|
+
}
|
|
1536
|
+
attributes["effect.fiberId"] = FiberId.threadName(fiberId)
|
|
1537
|
+
attributes["effect.logLevel"] = logLevel.label
|
|
1538
|
+
|
|
1539
|
+
if (cause !== null && cause._tag !== "Empty") {
|
|
1540
|
+
attributes["effect.cause"] = internalCause.pretty(cause, { renderErrorCause: true })
|
|
1541
|
+
}
|
|
1542
|
+
|
|
1543
|
+
span.value.event(
|
|
1544
|
+
Inspectable.toStringUnknown(Array.isArray(message) && message.length === 1 ? message[0] : message),
|
|
1545
|
+
clockService.unsafeCurrentTimeNanos(),
|
|
1546
|
+
attributes
|
|
1547
|
+
)
|
|
1548
|
+
})
|
|
1549
|
+
)
|
|
1550
|
+
|
|
1551
|
+
/** @internal */
|
|
1552
|
+
export const loggerWithSpanAnnotations = <Message, Output>(self: Logger<Message, Output>): Logger<Message, Output> =>
|
|
1553
|
+
internalLogger.mapInputOptions(self, (options: Logger.Options<Message>) => {
|
|
1554
|
+
const span = Option.flatMap(fiberRefs.get(options.context, core.currentContext), Context.getOption(tracer.spanTag))
|
|
1555
|
+
if (span._tag === "None") {
|
|
1556
|
+
return options
|
|
1557
|
+
}
|
|
1558
|
+
return {
|
|
1559
|
+
...options,
|
|
1560
|
+
annotations: pipe(
|
|
1561
|
+
options.annotations,
|
|
1562
|
+
HashMap.set("effect.traceId", span.value.traceId as unknown),
|
|
1563
|
+
HashMap.set("effect.spanId", span.value.spanId as unknown),
|
|
1564
|
+
span.value._tag === "Span" ? HashMap.set("effect.spanName", span.value.name as unknown) : identity
|
|
1565
|
+
)
|
|
1566
|
+
}
|
|
1567
|
+
})
|
|
1568
|
+
|
|
1569
|
+
/** @internal */
|
|
1570
|
+
export const currentLoggers: FiberRef.FiberRef<
|
|
1571
|
+
HashSet.HashSet<Logger<unknown, any>>
|
|
1572
|
+
> = globalValue(
|
|
1573
|
+
Symbol.for("effect/FiberRef/currentLoggers"),
|
|
1574
|
+
() => core.fiberRefUnsafeMakeHashSet(HashSet.make(defaultLogger, tracerLogger))
|
|
1575
|
+
)
|
|
1576
|
+
|
|
1577
|
+
/** @internal */
|
|
1578
|
+
export const batchedLogger = dual<
|
|
1579
|
+
<Output, R>(
|
|
1580
|
+
window: Duration.DurationInput,
|
|
1581
|
+
f: (messages: Array<NoInfer<Output>>) => Effect.Effect<void, never, R>
|
|
1582
|
+
) => <Message>(
|
|
1583
|
+
self: Logger<Message, Output>
|
|
1584
|
+
) => Effect.Effect<Logger<Message, void>, never, Scope.Scope | R>,
|
|
1585
|
+
<Message, Output, R>(
|
|
1586
|
+
self: Logger<Message, Output>,
|
|
1587
|
+
window: Duration.DurationInput,
|
|
1588
|
+
f: (messages: Array<NoInfer<Output>>) => Effect.Effect<void, never, R>
|
|
1589
|
+
) => Effect.Effect<Logger<Message, void>, never, Scope.Scope | R>
|
|
1590
|
+
>(3, <Message, Output, R>(
|
|
1591
|
+
self: Logger<Message, Output>,
|
|
1592
|
+
window: Duration.DurationInput,
|
|
1593
|
+
f: (messages: Array<NoInfer<Output>>) => Effect.Effect<void, never, R>
|
|
1594
|
+
): Effect.Effect<Logger<Message, void>, never, Scope.Scope | R> =>
|
|
1595
|
+
core.flatMap(scope, (scope) => {
|
|
1596
|
+
let buffer: Array<Output> = []
|
|
1597
|
+
const flush = core.suspend(() => {
|
|
1598
|
+
if (buffer.length === 0) {
|
|
1599
|
+
return core.void
|
|
1600
|
+
}
|
|
1601
|
+
const arr = buffer
|
|
1602
|
+
buffer = []
|
|
1603
|
+
return f(arr)
|
|
1604
|
+
})
|
|
1605
|
+
|
|
1606
|
+
return core.uninterruptibleMask((restore) =>
|
|
1607
|
+
pipe(
|
|
1608
|
+
internalEffect.sleep(window),
|
|
1609
|
+
core.zipRight(flush),
|
|
1610
|
+
internalEffect.forever,
|
|
1611
|
+
restore,
|
|
1612
|
+
forkDaemon,
|
|
1613
|
+
core.flatMap((fiber) => core.scopeAddFinalizer(scope, core.interruptFiber(fiber))),
|
|
1614
|
+
core.zipRight(addFinalizer(() => flush)),
|
|
1615
|
+
core.as(
|
|
1616
|
+
internalLogger.makeLogger((options) => {
|
|
1617
|
+
buffer.push(self.log(options))
|
|
1618
|
+
})
|
|
1619
|
+
)
|
|
1620
|
+
)
|
|
1621
|
+
)
|
|
1622
|
+
}))
|
|
1623
|
+
|
|
1624
|
+
export const annotateLogsScoped: {
|
|
1625
|
+
(key: string, value: unknown): Effect.Effect<void, never, Scope.Scope>
|
|
1626
|
+
(values: Record<string, unknown>): Effect.Effect<void, never, Scope.Scope>
|
|
1627
|
+
} = function() {
|
|
1628
|
+
if (typeof arguments[0] === "string") {
|
|
1629
|
+
return fiberRefLocallyScopedWith(
|
|
1630
|
+
core.currentLogAnnotations,
|
|
1631
|
+
HashMap.set(arguments[0], arguments[1])
|
|
1632
|
+
)
|
|
1633
|
+
}
|
|
1634
|
+
const entries = Object.entries(arguments[0])
|
|
1635
|
+
return fiberRefLocallyScopedWith(
|
|
1636
|
+
core.currentLogAnnotations,
|
|
1637
|
+
HashMap.mutate((annotations) => {
|
|
1638
|
+
for (let i = 0; i < entries.length; i++) {
|
|
1639
|
+
const [key, value] = entries[i]
|
|
1640
|
+
HashMap.set(annotations, key, value)
|
|
1641
|
+
}
|
|
1642
|
+
return annotations
|
|
1643
|
+
})
|
|
1644
|
+
)
|
|
1645
|
+
}
|
|
1646
|
+
|
|
1647
|
+
/** @internal */
|
|
1648
|
+
export const whenLogLevel = dual<
|
|
1649
|
+
(
|
|
1650
|
+
level: LogLevel.LogLevel | LogLevel.Literal
|
|
1651
|
+
) => <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<Option.Option<A>, E, R>,
|
|
1652
|
+
<A, E, R>(
|
|
1653
|
+
effect: Effect.Effect<A, E, R>,
|
|
1654
|
+
level: LogLevel.LogLevel | LogLevel.Literal
|
|
1655
|
+
) => Effect.Effect<Option.Option<A>, E, R>
|
|
1656
|
+
>(2, (effect, level) => {
|
|
1657
|
+
const requiredLogLevel = typeof level === "string" ? LogLevel.fromLiteral(level) : level
|
|
1658
|
+
|
|
1659
|
+
return core.withFiberRuntime((fiberState) => {
|
|
1660
|
+
const minimumLogLevel = fiberState.getFiberRef(currentMinimumLogLevel)
|
|
1661
|
+
|
|
1662
|
+
// Imitate the behaviour of `FiberRuntime.log`
|
|
1663
|
+
if (LogLevel.greaterThan(minimumLogLevel, requiredLogLevel)) {
|
|
1664
|
+
return core.succeed(Option.none())
|
|
1665
|
+
}
|
|
1666
|
+
|
|
1667
|
+
return core.map(effect, Option.some)
|
|
1668
|
+
})
|
|
1669
|
+
})
|
|
1670
|
+
|
|
1671
|
+
// circular with Effect
|
|
1672
|
+
|
|
1673
|
+
/* @internal */
|
|
1674
|
+
export const acquireRelease: {
|
|
1675
|
+
<A, X, R2>(
|
|
1676
|
+
release: (a: A, exit: Exit.Exit<unknown, unknown>) => Effect.Effect<X, never, R2>
|
|
1677
|
+
): <E, R>(acquire: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R2 | R | Scope.Scope>
|
|
1678
|
+
<A, E, R, X, R2>(
|
|
1679
|
+
acquire: Effect.Effect<A, E, R>,
|
|
1680
|
+
release: (a: A, exit: Exit.Exit<unknown, unknown>) => Effect.Effect<X, never, R2>
|
|
1681
|
+
): Effect.Effect<A, E, R2 | R | Scope.Scope>
|
|
1682
|
+
} = dual((args) => core.isEffect(args[0]), (acquire, release) =>
|
|
1683
|
+
core.uninterruptible(
|
|
1684
|
+
core.tap(acquire, (a) => addFinalizer((exit) => release(a, exit)))
|
|
1685
|
+
))
|
|
1686
|
+
|
|
1687
|
+
/* @internal */
|
|
1688
|
+
export const acquireReleaseInterruptible: {
|
|
1689
|
+
<X, R2>(
|
|
1690
|
+
release: (exit: Exit.Exit<unknown, unknown>) => Effect.Effect<X, never, R2>
|
|
1691
|
+
): <A, E, R>(acquire: Effect.Effect<A, E, R>) => Effect.Effect<A, E, Scope.Scope | R2 | R>
|
|
1692
|
+
<A, E, R, X, R2>(
|
|
1693
|
+
acquire: Effect.Effect<A, E, R>,
|
|
1694
|
+
release: (exit: Exit.Exit<unknown, unknown>) => Effect.Effect<X, never, R2>
|
|
1695
|
+
): Effect.Effect<A, E, Scope.Scope | R2 | R>
|
|
1696
|
+
} = dual((args) => core.isEffect(args[0]), (acquire, release) =>
|
|
1697
|
+
ensuring(
|
|
1698
|
+
acquire,
|
|
1699
|
+
addFinalizer((exit) => release(exit))
|
|
1700
|
+
))
|
|
1701
|
+
|
|
1702
|
+
/* @internal */
|
|
1703
|
+
export const addFinalizer = <X, R>(
|
|
1704
|
+
finalizer: (exit: Exit.Exit<unknown, unknown>) => Effect.Effect<X, never, R>
|
|
1705
|
+
): Effect.Effect<void, never, R | Scope.Scope> =>
|
|
1706
|
+
core.withFiberRuntime(
|
|
1707
|
+
(runtime) => {
|
|
1708
|
+
const acquireRefs = runtime.getFiberRefs()
|
|
1709
|
+
const acquireFlags = runtimeFlags_.disable(runtime.currentRuntimeFlags, runtimeFlags_.Interruption)
|
|
1710
|
+
return core.flatMap(scope, (scope) =>
|
|
1711
|
+
core.scopeAddFinalizerExit(scope, (exit) =>
|
|
1712
|
+
core.withFiberRuntime((runtimeFinalizer) => {
|
|
1713
|
+
const preRefs = runtimeFinalizer.getFiberRefs()
|
|
1714
|
+
const preFlags = runtimeFinalizer.currentRuntimeFlags
|
|
1715
|
+
const patchRefs = FiberRefsPatch.diff(preRefs, acquireRefs)
|
|
1716
|
+
const patchFlags = runtimeFlags_.diff(preFlags, acquireFlags)
|
|
1717
|
+
const inverseRefs = FiberRefsPatch.diff(acquireRefs, preRefs)
|
|
1718
|
+
runtimeFinalizer.setFiberRefs(
|
|
1719
|
+
FiberRefsPatch.patch(patchRefs, runtimeFinalizer.id(), acquireRefs)
|
|
1720
|
+
)
|
|
1721
|
+
|
|
1722
|
+
return ensuring(
|
|
1723
|
+
core.withRuntimeFlags(finalizer(exit) as Effect.Effect<X>, patchFlags),
|
|
1724
|
+
core.sync(() => {
|
|
1725
|
+
runtimeFinalizer.setFiberRefs(
|
|
1726
|
+
FiberRefsPatch.patch(inverseRefs, runtimeFinalizer.id(), runtimeFinalizer.getFiberRefs())
|
|
1727
|
+
)
|
|
1728
|
+
})
|
|
1729
|
+
)
|
|
1730
|
+
})))
|
|
1731
|
+
}
|
|
1732
|
+
)
|
|
1733
|
+
|
|
1734
|
+
/* @internal */
|
|
1735
|
+
export const daemonChildren = <A, E, R>(self: Effect.Effect<A, E, R>): Effect.Effect<A, E, R> => {
|
|
1736
|
+
const forkScope = core.fiberRefLocally(core.currentForkScopeOverride, Option.some(fiberScope.globalScope))
|
|
1737
|
+
return forkScope(self)
|
|
1738
|
+
}
|
|
1739
|
+
|
|
1740
|
+
/** @internal */
|
|
1741
|
+
const _existsParFound = Symbol.for("effect/Effect/existsPar/found")
|
|
1742
|
+
|
|
1743
|
+
/* @internal */
|
|
1744
|
+
export const exists: {
|
|
1745
|
+
<A, E, R>(predicate: (a: A, i: number) => Effect.Effect<boolean, E, R>, options?: {
|
|
1746
|
+
readonly concurrency?: Concurrency | undefined
|
|
1747
|
+
readonly batching?: boolean | "inherit" | undefined
|
|
1748
|
+
readonly concurrentFinalizers?: boolean | undefined
|
|
1749
|
+
}): (elements: Iterable<A>) => Effect.Effect<boolean, E, R>
|
|
1750
|
+
<A, E, R>(elements: Iterable<A>, predicate: (a: A, i: number) => Effect.Effect<boolean, E, R>, options?: {
|
|
1751
|
+
readonly concurrency?: Concurrency | undefined
|
|
1752
|
+
readonly batching?: boolean | "inherit" | undefined
|
|
1753
|
+
readonly concurrentFinalizers?: boolean | undefined
|
|
1754
|
+
}): Effect.Effect<boolean, E, R>
|
|
1755
|
+
} = dual(
|
|
1756
|
+
(args) => Predicate.isIterable(args[0]) && !core.isEffect(args[0]),
|
|
1757
|
+
<A, E, R>(elements: Iterable<A>, predicate: (a: A, i: number) => Effect.Effect<boolean, E, R>, options?: {
|
|
1758
|
+
readonly concurrency?: Concurrency | undefined
|
|
1759
|
+
readonly batching?: boolean | "inherit" | undefined
|
|
1760
|
+
}) =>
|
|
1761
|
+
concurrency.matchSimple(
|
|
1762
|
+
options?.concurrency,
|
|
1763
|
+
() => core.suspend(() => existsLoop(elements[Symbol.iterator](), 0, predicate)),
|
|
1764
|
+
() =>
|
|
1765
|
+
core.matchEffect(
|
|
1766
|
+
forEach(
|
|
1767
|
+
elements,
|
|
1768
|
+
(a, i) => core.if_(predicate(a, i), { onTrue: () => core.fail(_existsParFound), onFalse: () => core.void }),
|
|
1769
|
+
options
|
|
1770
|
+
),
|
|
1771
|
+
{
|
|
1772
|
+
onFailure: (e) => e === _existsParFound ? core.succeed(true) : core.fail(e),
|
|
1773
|
+
onSuccess: () => core.succeed(false)
|
|
1774
|
+
}
|
|
1775
|
+
)
|
|
1776
|
+
)
|
|
1777
|
+
)
|
|
1778
|
+
|
|
1779
|
+
const existsLoop = <A, E, R>(
|
|
1780
|
+
iterator: Iterator<A>,
|
|
1781
|
+
index: number,
|
|
1782
|
+
f: (a: A, i: number) => Effect.Effect<boolean, E, R>
|
|
1783
|
+
): Effect.Effect<boolean, E, R> => {
|
|
1784
|
+
const next = iterator.next()
|
|
1785
|
+
if (next.done) {
|
|
1786
|
+
return core.succeed(false)
|
|
1787
|
+
}
|
|
1788
|
+
return core.flatMap(
|
|
1789
|
+
f(next.value, index),
|
|
1790
|
+
(b) => b ? core.succeed(b) : existsLoop(iterator, index + 1, f)
|
|
1791
|
+
)
|
|
1792
|
+
}
|
|
1793
|
+
|
|
1794
|
+
/* @internal */
|
|
1795
|
+
export const filter = dual<
|
|
1796
|
+
<A, E, R>(
|
|
1797
|
+
predicate: (a: NoInfer<A>, i: number) => Effect.Effect<boolean, E, R>,
|
|
1798
|
+
options?: {
|
|
1799
|
+
readonly concurrency?: Concurrency | undefined
|
|
1800
|
+
readonly batching?: boolean | "inherit" | undefined
|
|
1801
|
+
readonly negate?: boolean | undefined
|
|
1802
|
+
readonly concurrentFinalizers?: boolean | undefined
|
|
1803
|
+
}
|
|
1804
|
+
) => (elements: Iterable<A>) => Effect.Effect<Array<A>, E, R>,
|
|
1805
|
+
<A, E, R>(elements: Iterable<A>, predicate: (a: NoInfer<A>, i: number) => Effect.Effect<boolean, E, R>, options?: {
|
|
1806
|
+
readonly concurrency?: Concurrency | undefined
|
|
1807
|
+
readonly batching?: boolean | "inherit" | undefined
|
|
1808
|
+
readonly negate?: boolean | undefined
|
|
1809
|
+
readonly concurrentFinalizers?: boolean | undefined
|
|
1810
|
+
}) => Effect.Effect<Array<A>, E, R>
|
|
1811
|
+
>(
|
|
1812
|
+
(args) => Predicate.isIterable(args[0]) && !core.isEffect(args[0]),
|
|
1813
|
+
<A, E, R>(elements: Iterable<A>, predicate: (a: NoInfer<A>, i: number) => Effect.Effect<boolean, E, R>, options?: {
|
|
1814
|
+
readonly concurrency?: Concurrency | undefined
|
|
1815
|
+
readonly batching?: boolean | "inherit" | undefined
|
|
1816
|
+
readonly negate?: boolean | undefined
|
|
1817
|
+
readonly concurrentFinalizers?: boolean | undefined
|
|
1818
|
+
}) => {
|
|
1819
|
+
const predicate_ = options?.negate ? (a: A, i: number) => core.map(predicate(a, i), Boolean.not) : predicate
|
|
1820
|
+
return concurrency.matchSimple(
|
|
1821
|
+
options?.concurrency,
|
|
1822
|
+
() =>
|
|
1823
|
+
core.suspend(() =>
|
|
1824
|
+
RA.fromIterable(elements).reduceRight(
|
|
1825
|
+
(effect, a, i) =>
|
|
1826
|
+
core.zipWith(
|
|
1827
|
+
effect,
|
|
1828
|
+
core.suspend(() => predicate_(a, i)),
|
|
1829
|
+
(list, b) => b ? [a, ...list] : list
|
|
1830
|
+
),
|
|
1831
|
+
core.sync(() => new Array<A>()) as Effect.Effect<Array<A>, E, R>
|
|
1832
|
+
)
|
|
1833
|
+
),
|
|
1834
|
+
() =>
|
|
1835
|
+
core.map(
|
|
1836
|
+
forEach(
|
|
1837
|
+
elements,
|
|
1838
|
+
(a, i) => core.map(predicate_(a, i), (b) => (b ? Option.some(a) : Option.none())),
|
|
1839
|
+
options
|
|
1840
|
+
),
|
|
1841
|
+
RA.getSomes
|
|
1842
|
+
)
|
|
1843
|
+
)
|
|
1844
|
+
}
|
|
1845
|
+
)
|
|
1846
|
+
|
|
1847
|
+
// === all
|
|
1848
|
+
|
|
1849
|
+
const allResolveInput = (
|
|
1850
|
+
input: Iterable<Effect.Effect<any, any, any>> | Record<string, Effect.Effect<any, any, any>>
|
|
1851
|
+
): [Iterable<Effect.Effect<any, any, any>>, Option.Option<(as: ReadonlyArray<any>) => any>] => {
|
|
1852
|
+
if (Array.isArray(input) || Predicate.isIterable(input)) {
|
|
1853
|
+
return [input, Option.none()]
|
|
1854
|
+
}
|
|
1855
|
+
const keys = Object.keys(input)
|
|
1856
|
+
const size = keys.length
|
|
1857
|
+
return [
|
|
1858
|
+
keys.map((k) => input[k]),
|
|
1859
|
+
Option.some((values: ReadonlyArray<any>) => {
|
|
1860
|
+
const res = {}
|
|
1861
|
+
for (let i = 0; i < size; i++) {
|
|
1862
|
+
;(res as any)[keys[i]] = values[i]
|
|
1863
|
+
}
|
|
1864
|
+
return res
|
|
1865
|
+
})
|
|
1866
|
+
]
|
|
1867
|
+
}
|
|
1868
|
+
|
|
1869
|
+
const allValidate = (
|
|
1870
|
+
effects: Iterable<Effect.Effect<any, any, any>>,
|
|
1871
|
+
reconcile: Option.Option<(as: ReadonlyArray<any>) => any>,
|
|
1872
|
+
options?: {
|
|
1873
|
+
readonly concurrency?: Concurrency | undefined
|
|
1874
|
+
readonly batching?: boolean | "inherit" | undefined
|
|
1875
|
+
readonly discard?: boolean | undefined
|
|
1876
|
+
readonly mode?: "default" | "validate" | "either" | undefined
|
|
1877
|
+
readonly concurrentFinalizers?: boolean | undefined
|
|
1878
|
+
}
|
|
1879
|
+
) => {
|
|
1880
|
+
const eitherEffects: Array<Effect.Effect<Either.Either<unknown, unknown>, never, unknown>> = []
|
|
1881
|
+
for (const effect of effects) {
|
|
1882
|
+
eitherEffects.push(core.either(effect))
|
|
1883
|
+
}
|
|
1884
|
+
return core.flatMap(
|
|
1885
|
+
forEach(eitherEffects, identity, {
|
|
1886
|
+
concurrency: options?.concurrency,
|
|
1887
|
+
batching: options?.batching,
|
|
1888
|
+
concurrentFinalizers: options?.concurrentFinalizers
|
|
1889
|
+
}),
|
|
1890
|
+
(eithers) => {
|
|
1891
|
+
const none = Option.none()
|
|
1892
|
+
const size = eithers.length
|
|
1893
|
+
const errors: Array<unknown> = new Array(size)
|
|
1894
|
+
const successes: Array<unknown> = new Array(size)
|
|
1895
|
+
let errored = false
|
|
1896
|
+
for (let i = 0; i < size; i++) {
|
|
1897
|
+
const either = eithers[i] as Either.Either<unknown, unknown>
|
|
1898
|
+
if (either._tag === "Left") {
|
|
1899
|
+
errors[i] = Option.some(either.left)
|
|
1900
|
+
errored = true
|
|
1901
|
+
} else {
|
|
1902
|
+
successes[i] = either.right
|
|
1903
|
+
errors[i] = none
|
|
1904
|
+
}
|
|
1905
|
+
}
|
|
1906
|
+
if (errored) {
|
|
1907
|
+
return reconcile._tag === "Some" ?
|
|
1908
|
+
core.fail(reconcile.value(errors)) :
|
|
1909
|
+
core.fail(errors)
|
|
1910
|
+
} else if (options?.discard) {
|
|
1911
|
+
return core.void
|
|
1912
|
+
}
|
|
1913
|
+
return reconcile._tag === "Some" ?
|
|
1914
|
+
core.succeed(reconcile.value(successes)) :
|
|
1915
|
+
core.succeed(successes)
|
|
1916
|
+
}
|
|
1917
|
+
)
|
|
1918
|
+
}
|
|
1919
|
+
|
|
1920
|
+
const allEither = (
|
|
1921
|
+
effects: Iterable<Effect.Effect<any, any, any>>,
|
|
1922
|
+
reconcile: Option.Option<(as: ReadonlyArray<any>) => any>,
|
|
1923
|
+
options?: {
|
|
1924
|
+
readonly concurrency?: Concurrency | undefined
|
|
1925
|
+
readonly batching?: boolean | "inherit" | undefined
|
|
1926
|
+
readonly discard?: boolean | undefined
|
|
1927
|
+
readonly mode?: "default" | "validate" | "either" | undefined
|
|
1928
|
+
readonly concurrentFinalizers?: boolean | undefined
|
|
1929
|
+
}
|
|
1930
|
+
) => {
|
|
1931
|
+
const eitherEffects: Array<Effect.Effect<Either.Either<unknown, unknown>, never, unknown>> = []
|
|
1932
|
+
for (const effect of effects) {
|
|
1933
|
+
eitherEffects.push(core.either(effect))
|
|
1934
|
+
}
|
|
1935
|
+
|
|
1936
|
+
if (options?.discard) {
|
|
1937
|
+
return forEach(eitherEffects, identity, {
|
|
1938
|
+
concurrency: options?.concurrency,
|
|
1939
|
+
batching: options?.batching,
|
|
1940
|
+
discard: true,
|
|
1941
|
+
concurrentFinalizers: options?.concurrentFinalizers
|
|
1942
|
+
})
|
|
1943
|
+
}
|
|
1944
|
+
|
|
1945
|
+
return core.map(
|
|
1946
|
+
forEach(eitherEffects, identity, {
|
|
1947
|
+
concurrency: options?.concurrency,
|
|
1948
|
+
batching: options?.batching,
|
|
1949
|
+
concurrentFinalizers: options?.concurrentFinalizers
|
|
1950
|
+
}),
|
|
1951
|
+
(eithers) =>
|
|
1952
|
+
reconcile._tag === "Some" ?
|
|
1953
|
+
reconcile.value(eithers) :
|
|
1954
|
+
eithers
|
|
1955
|
+
)
|
|
1956
|
+
}
|
|
1957
|
+
|
|
1958
|
+
/* @internal */
|
|
1959
|
+
export const all = <
|
|
1960
|
+
const Arg extends Iterable<Effect.Effect<any, any, any>> | Record<string, Effect.Effect<any, any, any>>,
|
|
1961
|
+
O extends NoExcessProperties<{
|
|
1962
|
+
readonly concurrency?: Concurrency | undefined
|
|
1963
|
+
readonly batching?: boolean | "inherit" | undefined
|
|
1964
|
+
readonly discard?: boolean | undefined
|
|
1965
|
+
readonly mode?: "default" | "validate" | "either" | undefined
|
|
1966
|
+
readonly concurrentFinalizers?: boolean | undefined
|
|
1967
|
+
}, O>
|
|
1968
|
+
>(
|
|
1969
|
+
arg: Arg,
|
|
1970
|
+
options?: O
|
|
1971
|
+
): Effect.All.Return<Arg, O> => {
|
|
1972
|
+
const [effects, reconcile] = allResolveInput(arg)
|
|
1973
|
+
|
|
1974
|
+
if (options?.mode === "validate") {
|
|
1975
|
+
return allValidate(effects, reconcile, options) as any
|
|
1976
|
+
} else if (options?.mode === "either") {
|
|
1977
|
+
return allEither(effects, reconcile, options) as any
|
|
1978
|
+
}
|
|
1979
|
+
|
|
1980
|
+
return options?.discard !== true && reconcile._tag === "Some"
|
|
1981
|
+
? core.map(
|
|
1982
|
+
forEach(effects, identity, options as any),
|
|
1983
|
+
reconcile.value
|
|
1984
|
+
) as any
|
|
1985
|
+
: forEach(effects, identity, options as any) as any
|
|
1986
|
+
}
|
|
1987
|
+
|
|
1988
|
+
/* @internal */
|
|
1989
|
+
export const allWith = <
|
|
1990
|
+
O extends NoExcessProperties<{
|
|
1991
|
+
readonly concurrency?: Concurrency | undefined
|
|
1992
|
+
readonly batching?: boolean | "inherit" | undefined
|
|
1993
|
+
readonly discard?: boolean | undefined
|
|
1994
|
+
readonly mode?: "default" | "validate" | "either" | undefined
|
|
1995
|
+
readonly concurrentFinalizers?: boolean | undefined
|
|
1996
|
+
}, O>
|
|
1997
|
+
>(options?: O) =>
|
|
1998
|
+
<const Arg extends Iterable<Effect.Effect<any, any, any>> | Record<string, Effect.Effect<any, any, any>>>(
|
|
1999
|
+
arg: Arg
|
|
2000
|
+
): Effect.All.Return<Arg, O> => all(arg, options)
|
|
2001
|
+
|
|
2002
|
+
/* @internal */
|
|
2003
|
+
export const allSuccesses = <Eff extends Effect.Effect<any, any, any>>(
|
|
2004
|
+
elements: Iterable<Eff>,
|
|
2005
|
+
options?: {
|
|
2006
|
+
readonly concurrency?: Concurrency | undefined
|
|
2007
|
+
readonly batching?: boolean | "inherit" | undefined
|
|
2008
|
+
readonly concurrentFinalizers?: boolean | undefined
|
|
2009
|
+
}
|
|
2010
|
+
): Effect.Effect<Array<Effect.Effect.Success<Eff>>, never, Effect.Effect.Context<Eff>> =>
|
|
2011
|
+
core.map(
|
|
2012
|
+
all(RA.fromIterable(elements).map(core.exit), options),
|
|
2013
|
+
RA.filterMap((exit) => core.exitIsSuccess(exit) ? Option.some(exit.effect_instruction_i0) : Option.none())
|
|
2014
|
+
)
|
|
2015
|
+
|
|
2016
|
+
/* @internal */
|
|
2017
|
+
export const replicate = dual<
|
|
2018
|
+
(n: number) => <A, E, R>(self: Effect.Effect<A, E, R>) => Array<Effect.Effect<A, E, R>>,
|
|
2019
|
+
<A, E, R>(self: Effect.Effect<A, E, R>, n: number) => Array<Effect.Effect<A, E, R>>
|
|
2020
|
+
>(2, (self, n) => Array.from({ length: n }, () => self))
|
|
2021
|
+
|
|
2022
|
+
/* @internal */
|
|
2023
|
+
export const replicateEffect: {
|
|
2024
|
+
(
|
|
2025
|
+
n: number,
|
|
2026
|
+
options?: {
|
|
2027
|
+
readonly concurrency?: Concurrency | undefined
|
|
2028
|
+
readonly batching?: boolean | "inherit" | undefined
|
|
2029
|
+
readonly discard?: false | undefined
|
|
2030
|
+
readonly concurrentFinalizers?: boolean | undefined
|
|
2031
|
+
}
|
|
2032
|
+
): <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<Array<A>, E, R>
|
|
2033
|
+
(
|
|
2034
|
+
n: number,
|
|
2035
|
+
options: {
|
|
2036
|
+
readonly concurrency?: Concurrency | undefined
|
|
2037
|
+
readonly batching?: boolean | "inherit" | undefined
|
|
2038
|
+
readonly discard: true
|
|
2039
|
+
readonly concurrentFinalizers?: boolean | undefined
|
|
2040
|
+
}
|
|
2041
|
+
): <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<void, E, R>
|
|
2042
|
+
<A, E, R>(
|
|
2043
|
+
self: Effect.Effect<A, E, R>,
|
|
2044
|
+
n: number,
|
|
2045
|
+
options?: {
|
|
2046
|
+
readonly concurrency?: Concurrency | undefined
|
|
2047
|
+
readonly batching?: boolean | "inherit" | undefined
|
|
2048
|
+
readonly discard?: false | undefined
|
|
2049
|
+
readonly concurrentFinalizers?: boolean | undefined
|
|
2050
|
+
}
|
|
2051
|
+
): Effect.Effect<Array<A>, E, R>
|
|
2052
|
+
<A, E, R>(
|
|
2053
|
+
self: Effect.Effect<A, E, R>,
|
|
2054
|
+
n: number,
|
|
2055
|
+
options: {
|
|
2056
|
+
readonly concurrency?: Concurrency | undefined
|
|
2057
|
+
readonly batching?: boolean | "inherit" | undefined
|
|
2058
|
+
readonly discard: true
|
|
2059
|
+
readonly concurrentFinalizers?: boolean | undefined
|
|
2060
|
+
}
|
|
2061
|
+
): Effect.Effect<void, E, R>
|
|
2062
|
+
} = dual(
|
|
2063
|
+
(args) => core.isEffect(args[0]),
|
|
2064
|
+
(self, n, options) => all(replicate(self, n), options)
|
|
2065
|
+
)
|
|
2066
|
+
|
|
2067
|
+
/* @internal */
|
|
2068
|
+
export const forEach: {
|
|
2069
|
+
<B, E, R, S extends Iterable<any>>(
|
|
2070
|
+
f: (a: RA.ReadonlyArray.Infer<S>, i: number) => Effect.Effect<B, E, R>,
|
|
2071
|
+
options?: {
|
|
2072
|
+
readonly concurrency?: Concurrency | undefined
|
|
2073
|
+
readonly batching?: boolean | "inherit" | undefined
|
|
2074
|
+
readonly discard?: false | undefined
|
|
2075
|
+
readonly concurrentFinalizers?: boolean | undefined
|
|
2076
|
+
} | undefined
|
|
2077
|
+
): (
|
|
2078
|
+
self: S
|
|
2079
|
+
) => Effect.Effect<RA.ReadonlyArray.With<S, B>, E, R>
|
|
2080
|
+
<A, B, E, R>(
|
|
2081
|
+
f: (a: A, i: number) => Effect.Effect<B, E, R>,
|
|
2082
|
+
options: {
|
|
2083
|
+
readonly concurrency?: Concurrency | undefined
|
|
2084
|
+
readonly batching?: boolean | "inherit" | undefined
|
|
2085
|
+
readonly discard: true
|
|
2086
|
+
readonly concurrentFinalizers?: boolean | undefined
|
|
2087
|
+
}
|
|
2088
|
+
): (self: Iterable<A>) => Effect.Effect<void, E, R>
|
|
2089
|
+
<A, B, E, R>(
|
|
2090
|
+
self: RA.NonEmptyReadonlyArray<A>,
|
|
2091
|
+
f: (a: A, i: number) => Effect.Effect<B, E, R>,
|
|
2092
|
+
options?: {
|
|
2093
|
+
readonly concurrency?: Concurrency | undefined
|
|
2094
|
+
readonly batching?: boolean | "inherit" | undefined
|
|
2095
|
+
readonly discard?: false | undefined
|
|
2096
|
+
readonly concurrentFinalizers?: boolean | undefined
|
|
2097
|
+
} | undefined
|
|
2098
|
+
): Effect.Effect<RA.NonEmptyArray<B>, E, R>
|
|
2099
|
+
<A, B, E, R>(
|
|
2100
|
+
self: Iterable<A>,
|
|
2101
|
+
f: (a: A, i: number) => Effect.Effect<B, E, R>,
|
|
2102
|
+
options?: {
|
|
2103
|
+
readonly concurrency?: Concurrency | undefined
|
|
2104
|
+
readonly batching?: boolean | "inherit" | undefined
|
|
2105
|
+
readonly discard?: false | undefined
|
|
2106
|
+
readonly concurrentFinalizers?: boolean | undefined
|
|
2107
|
+
} | undefined
|
|
2108
|
+
): Effect.Effect<Array<B>, E, R>
|
|
2109
|
+
<A, B, E, R>(
|
|
2110
|
+
self: Iterable<A>,
|
|
2111
|
+
f: (a: A, i: number) => Effect.Effect<B, E, R>,
|
|
2112
|
+
options: {
|
|
2113
|
+
readonly concurrency?: Concurrency | undefined
|
|
2114
|
+
readonly batching?: boolean | "inherit" | undefined
|
|
2115
|
+
readonly discard: true
|
|
2116
|
+
readonly concurrentFinalizers?: boolean | undefined
|
|
2117
|
+
}
|
|
2118
|
+
): Effect.Effect<void, E, R>
|
|
2119
|
+
} = dual((args) => Predicate.isIterable(args[0]), <A, R, E, B>(
|
|
2120
|
+
self: Iterable<A>,
|
|
2121
|
+
f: (a: A, i: number) => Effect.Effect<B, E, R>,
|
|
2122
|
+
options?: {
|
|
2123
|
+
readonly concurrency?: Concurrency | undefined
|
|
2124
|
+
readonly batching?: boolean | "inherit" | undefined
|
|
2125
|
+
readonly discard?: boolean | undefined
|
|
2126
|
+
readonly concurrentFinalizers?: boolean | undefined
|
|
2127
|
+
}
|
|
2128
|
+
) =>
|
|
2129
|
+
core.withFiberRuntime<A | void, E, R>((r) => {
|
|
2130
|
+
const isRequestBatchingEnabled = options?.batching === true ||
|
|
2131
|
+
(options?.batching === "inherit" && r.getFiberRef(core.currentRequestBatching))
|
|
2132
|
+
|
|
2133
|
+
if (options?.discard) {
|
|
2134
|
+
return concurrency.match(
|
|
2135
|
+
options.concurrency,
|
|
2136
|
+
() =>
|
|
2137
|
+
finalizersMaskInternal(ExecutionStrategy.sequential, options?.concurrentFinalizers)((restore) =>
|
|
2138
|
+
isRequestBatchingEnabled
|
|
2139
|
+
? forEachConcurrentDiscard(self, (a, i) => restore(f(a, i)), true, false, 1)
|
|
2140
|
+
: core.forEachSequentialDiscard(self, (a, i) => restore(f(a, i)))
|
|
2141
|
+
),
|
|
2142
|
+
() =>
|
|
2143
|
+
finalizersMaskInternal(ExecutionStrategy.parallel, options?.concurrentFinalizers)((restore) =>
|
|
2144
|
+
forEachConcurrentDiscard(self, (a, i) => restore(f(a, i)), isRequestBatchingEnabled, false)
|
|
2145
|
+
),
|
|
2146
|
+
(n) =>
|
|
2147
|
+
finalizersMaskInternal(ExecutionStrategy.parallelN(n), options?.concurrentFinalizers)((restore) =>
|
|
2148
|
+
forEachConcurrentDiscard(self, (a, i) => restore(f(a, i)), isRequestBatchingEnabled, false, n)
|
|
2149
|
+
)
|
|
2150
|
+
)
|
|
2151
|
+
}
|
|
2152
|
+
|
|
2153
|
+
return concurrency.match(
|
|
2154
|
+
options?.concurrency,
|
|
2155
|
+
() =>
|
|
2156
|
+
finalizersMaskInternal(ExecutionStrategy.sequential, options?.concurrentFinalizers)((restore) =>
|
|
2157
|
+
isRequestBatchingEnabled
|
|
2158
|
+
? forEachParN(self, 1, (a, i) => restore(f(a, i)), true)
|
|
2159
|
+
: core.forEachSequential(self, (a, i) => restore(f(a, i)))
|
|
2160
|
+
),
|
|
2161
|
+
() =>
|
|
2162
|
+
finalizersMaskInternal(ExecutionStrategy.parallel, options?.concurrentFinalizers)((restore) =>
|
|
2163
|
+
forEachParUnbounded(self, (a, i) => restore(f(a, i)), isRequestBatchingEnabled)
|
|
2164
|
+
),
|
|
2165
|
+
(n) =>
|
|
2166
|
+
finalizersMaskInternal(ExecutionStrategy.parallelN(n), options?.concurrentFinalizers)((restore) =>
|
|
2167
|
+
forEachParN(self, n, (a, i) => restore(f(a, i)), isRequestBatchingEnabled)
|
|
2168
|
+
)
|
|
2169
|
+
)
|
|
2170
|
+
}))
|
|
2171
|
+
|
|
2172
|
+
/* @internal */
|
|
2173
|
+
export const forEachParUnbounded = <A, B, E, R>(
|
|
2174
|
+
self: Iterable<A>,
|
|
2175
|
+
f: (a: A, i: number) => Effect.Effect<B, E, R>,
|
|
2176
|
+
batching: boolean
|
|
2177
|
+
): Effect.Effect<Array<B>, E, R> =>
|
|
2178
|
+
core.suspend(() => {
|
|
2179
|
+
const as = RA.fromIterable(self)
|
|
2180
|
+
const array = new Array<B>(as.length)
|
|
2181
|
+
const fn = (a: A, i: number) => core.flatMap(f(a, i), (b) => core.sync(() => array[i] = b))
|
|
2182
|
+
return core.zipRight(forEachConcurrentDiscard(as, fn, batching, false), core.succeed(array))
|
|
2183
|
+
})
|
|
2184
|
+
|
|
2185
|
+
/** @internal */
|
|
2186
|
+
export const forEachConcurrentDiscard = <A, X, E, R>(
|
|
2187
|
+
self: Iterable<A>,
|
|
2188
|
+
f: (a: A, i: number) => Effect.Effect<X, E, R>,
|
|
2189
|
+
batching: boolean,
|
|
2190
|
+
processAll: boolean,
|
|
2191
|
+
n?: number
|
|
2192
|
+
): Effect.Effect<void, E, R> =>
|
|
2193
|
+
core.uninterruptibleMask((restore) =>
|
|
2194
|
+
core.transplant((graft) =>
|
|
2195
|
+
core.withFiberRuntime<void, E, R>((parent) => {
|
|
2196
|
+
let todos = Array.from(self).reverse()
|
|
2197
|
+
let target = todos.length
|
|
2198
|
+
if (target === 0) {
|
|
2199
|
+
return core.void
|
|
2200
|
+
}
|
|
2201
|
+
let counter = 0
|
|
2202
|
+
let interrupted = false
|
|
2203
|
+
const fibersCount = n ? Math.min(todos.length, n) : todos.length
|
|
2204
|
+
const fibers = new Set<FiberRuntime<Exit.Exit<X, E> | Effect.Blocked<X, E>>>()
|
|
2205
|
+
const results = new Array()
|
|
2206
|
+
const interruptAll = () =>
|
|
2207
|
+
fibers.forEach((fiber) => {
|
|
2208
|
+
fiber.currentScheduler.scheduleTask(() => {
|
|
2209
|
+
fiber.unsafeInterruptAsFork(parent.id())
|
|
2210
|
+
}, 0)
|
|
2211
|
+
})
|
|
2212
|
+
const startOrder = new Array<FiberRuntime<Exit.Exit<X, E> | Effect.Blocked<X, E>>>()
|
|
2213
|
+
const joinOrder = new Array<FiberRuntime<Exit.Exit<X, E> | Effect.Blocked<X, E>>>()
|
|
2214
|
+
const residual = new Array<core.Blocked>()
|
|
2215
|
+
const collectExits = () => {
|
|
2216
|
+
const exits: Array<Exit.Exit<any, E>> = results
|
|
2217
|
+
.filter(({ exit }) => exit._tag === "Failure")
|
|
2218
|
+
.sort((a, b) => a.index < b.index ? -1 : a.index === b.index ? 0 : 1)
|
|
2219
|
+
.map(({ exit }) => exit)
|
|
2220
|
+
if (exits.length === 0) {
|
|
2221
|
+
exits.push(core.exitVoid)
|
|
2222
|
+
}
|
|
2223
|
+
return exits
|
|
2224
|
+
}
|
|
2225
|
+
const runFiber = <A, E, R>(eff: Effect.Effect<A, E, R>, interruptImmediately = false) => {
|
|
2226
|
+
const runnable = core.uninterruptible(graft(eff))
|
|
2227
|
+
const fiber = unsafeForkUnstarted(
|
|
2228
|
+
runnable,
|
|
2229
|
+
parent,
|
|
2230
|
+
parent.currentRuntimeFlags,
|
|
2231
|
+
fiberScope.globalScope
|
|
2232
|
+
)
|
|
2233
|
+
parent.currentScheduler.scheduleTask(() => {
|
|
2234
|
+
if (interruptImmediately) {
|
|
2235
|
+
fiber.unsafeInterruptAsFork(parent.id())
|
|
2236
|
+
}
|
|
2237
|
+
fiber.resume(runnable)
|
|
2238
|
+
}, 0)
|
|
2239
|
+
return fiber
|
|
2240
|
+
}
|
|
2241
|
+
const onInterruptSignal = () => {
|
|
2242
|
+
if (!processAll) {
|
|
2243
|
+
target -= todos.length
|
|
2244
|
+
todos = []
|
|
2245
|
+
}
|
|
2246
|
+
interrupted = true
|
|
2247
|
+
interruptAll()
|
|
2248
|
+
}
|
|
2249
|
+
const stepOrExit = batching ? core.step : core.exit
|
|
2250
|
+
const processingFiber = runFiber(
|
|
2251
|
+
core.async<any, any, any>((resume) => {
|
|
2252
|
+
const pushResult = <X, E>(res: Exit.Exit<X, E> | Effect.Blocked<X, E>, index: number) => {
|
|
2253
|
+
if (res._op === "Blocked") {
|
|
2254
|
+
residual.push(res as core.Blocked)
|
|
2255
|
+
} else {
|
|
2256
|
+
results.push({ index, exit: res })
|
|
2257
|
+
if (res._op === "Failure" && !interrupted) {
|
|
2258
|
+
onInterruptSignal()
|
|
2259
|
+
}
|
|
2260
|
+
}
|
|
2261
|
+
}
|
|
2262
|
+
const next = () => {
|
|
2263
|
+
if (todos.length > 0) {
|
|
2264
|
+
const a = todos.pop()!
|
|
2265
|
+
let index = counter++
|
|
2266
|
+
const returnNextElement = () => {
|
|
2267
|
+
const a = todos.pop()!
|
|
2268
|
+
index = counter++
|
|
2269
|
+
return core.flatMap(core.yieldNow(), () =>
|
|
2270
|
+
core.flatMap(
|
|
2271
|
+
stepOrExit(restore(f(a, index))),
|
|
2272
|
+
onRes
|
|
2273
|
+
))
|
|
2274
|
+
}
|
|
2275
|
+
const onRes = (
|
|
2276
|
+
res: Exit.Exit<X, E> | Effect.Blocked<X, E>
|
|
2277
|
+
): Effect.Effect<Exit.Exit<X, E> | Effect.Blocked<X, E>, never, R> => {
|
|
2278
|
+
if (todos.length > 0) {
|
|
2279
|
+
pushResult(res, index)
|
|
2280
|
+
if (todos.length > 0) {
|
|
2281
|
+
return returnNextElement()
|
|
2282
|
+
}
|
|
2283
|
+
}
|
|
2284
|
+
return core.succeed(res)
|
|
2285
|
+
}
|
|
2286
|
+
const todo = core.flatMap(
|
|
2287
|
+
stepOrExit(restore(f(a, index))),
|
|
2288
|
+
onRes
|
|
2289
|
+
)
|
|
2290
|
+
const fiber = runFiber(todo)
|
|
2291
|
+
startOrder.push(fiber)
|
|
2292
|
+
fibers.add(fiber)
|
|
2293
|
+
if (interrupted) {
|
|
2294
|
+
fiber.currentScheduler.scheduleTask(() => {
|
|
2295
|
+
fiber.unsafeInterruptAsFork(parent.id())
|
|
2296
|
+
}, 0)
|
|
2297
|
+
}
|
|
2298
|
+
fiber.addObserver((wrapped) => {
|
|
2299
|
+
let exit: Exit.Exit<any, any> | core.Blocked
|
|
2300
|
+
if (wrapped._op === "Failure") {
|
|
2301
|
+
exit = wrapped
|
|
2302
|
+
} else {
|
|
2303
|
+
exit = wrapped.effect_instruction_i0 as any
|
|
2304
|
+
}
|
|
2305
|
+
joinOrder.push(fiber)
|
|
2306
|
+
fibers.delete(fiber)
|
|
2307
|
+
pushResult(exit, index)
|
|
2308
|
+
if (results.length === target) {
|
|
2309
|
+
resume(core.succeed(Option.getOrElse(
|
|
2310
|
+
core.exitCollectAll(collectExits(), { parallel: true }),
|
|
2311
|
+
() => core.exitVoid
|
|
2312
|
+
)))
|
|
2313
|
+
} else if (residual.length + results.length === target) {
|
|
2314
|
+
const exits = collectExits()
|
|
2315
|
+
const requests = residual.map((blocked) => blocked.effect_instruction_i0).reduce(RequestBlock_.par)
|
|
2316
|
+
resume(core.succeed(core.blocked(
|
|
2317
|
+
requests,
|
|
2318
|
+
forEachConcurrentDiscard(
|
|
2319
|
+
[
|
|
2320
|
+
Option.getOrElse(
|
|
2321
|
+
core.exitCollectAll(exits, { parallel: true }),
|
|
2322
|
+
() => core.exitVoid
|
|
2323
|
+
),
|
|
2324
|
+
...residual.map((blocked) => blocked.effect_instruction_i1)
|
|
2325
|
+
],
|
|
2326
|
+
(i) => i,
|
|
2327
|
+
batching,
|
|
2328
|
+
true,
|
|
2329
|
+
n
|
|
2330
|
+
)
|
|
2331
|
+
)))
|
|
2332
|
+
} else {
|
|
2333
|
+
next()
|
|
2334
|
+
}
|
|
2335
|
+
})
|
|
2336
|
+
}
|
|
2337
|
+
}
|
|
2338
|
+
for (let i = 0; i < fibersCount; i++) {
|
|
2339
|
+
next()
|
|
2340
|
+
}
|
|
2341
|
+
})
|
|
2342
|
+
)
|
|
2343
|
+
return core.asVoid(
|
|
2344
|
+
core.onExit(
|
|
2345
|
+
core.flatten(restore(internalFiber.join(processingFiber))),
|
|
2346
|
+
core.exitMatch({
|
|
2347
|
+
onFailure: (cause) => {
|
|
2348
|
+
onInterruptSignal()
|
|
2349
|
+
const target = residual.length + 1
|
|
2350
|
+
const concurrency = Math.min(typeof n === "number" ? n : residual.length, residual.length)
|
|
2351
|
+
const toPop = Array.from(residual)
|
|
2352
|
+
return core.async<any, any>((cb) => {
|
|
2353
|
+
const exits: Array<Exit.Exit<any, any>> = []
|
|
2354
|
+
let count = 0
|
|
2355
|
+
let index = 0
|
|
2356
|
+
const check = (index: number, hitNext: boolean) => (exit: Exit.Exit<any, any>) => {
|
|
2357
|
+
exits[index] = exit
|
|
2358
|
+
count++
|
|
2359
|
+
if (count === target) {
|
|
2360
|
+
cb(core.exitSucceed(core.exitFailCause(cause)))
|
|
2361
|
+
}
|
|
2362
|
+
if (toPop.length > 0 && hitNext) {
|
|
2363
|
+
next()
|
|
2364
|
+
}
|
|
2365
|
+
}
|
|
2366
|
+
const next = () => {
|
|
2367
|
+
runFiber(toPop.pop()!, true).addObserver(check(index, true))
|
|
2368
|
+
index++
|
|
2369
|
+
}
|
|
2370
|
+
processingFiber.addObserver(check(index, false))
|
|
2371
|
+
index++
|
|
2372
|
+
for (let i = 0; i < concurrency; i++) {
|
|
2373
|
+
next()
|
|
2374
|
+
}
|
|
2375
|
+
}) as any
|
|
2376
|
+
},
|
|
2377
|
+
onSuccess: () => core.forEachSequential(joinOrder, (f) => f.inheritAll)
|
|
2378
|
+
})
|
|
2379
|
+
)
|
|
2380
|
+
)
|
|
2381
|
+
})
|
|
2382
|
+
)
|
|
2383
|
+
)
|
|
2384
|
+
|
|
2385
|
+
/* @internal */
|
|
2386
|
+
export const forEachParN = <A, B, E, R>(
|
|
2387
|
+
self: Iterable<A>,
|
|
2388
|
+
n: number,
|
|
2389
|
+
f: (a: A, i: number) => Effect.Effect<B, E, R>,
|
|
2390
|
+
batching: boolean
|
|
2391
|
+
): Effect.Effect<Array<B>, E, R> =>
|
|
2392
|
+
core.suspend(() => {
|
|
2393
|
+
const as = RA.fromIterable(self)
|
|
2394
|
+
const array = new Array<B>(as.length)
|
|
2395
|
+
const fn = (a: A, i: number) => core.map(f(a, i), (b) => array[i] = b)
|
|
2396
|
+
return core.zipRight(forEachConcurrentDiscard(as, fn, batching, false, n), core.succeed(array))
|
|
2397
|
+
})
|
|
2398
|
+
|
|
2399
|
+
/* @internal */
|
|
2400
|
+
export const fork = <A, E, R>(self: Effect.Effect<A, E, R>): Effect.Effect<Fiber.RuntimeFiber<A, E>, never, R> =>
|
|
2401
|
+
core.withFiberRuntime((state, status) => core.succeed(unsafeFork(self, state, status.runtimeFlags)))
|
|
2402
|
+
|
|
2403
|
+
/* @internal */
|
|
2404
|
+
export const forkDaemon = <A, E, R>(self: Effect.Effect<A, E, R>): Effect.Effect<Fiber.RuntimeFiber<A, E>, never, R> =>
|
|
2405
|
+
forkWithScopeOverride(self, fiberScope.globalScope)
|
|
2406
|
+
|
|
2407
|
+
/* @internal */
|
|
2408
|
+
export const forkWithErrorHandler = dual<
|
|
2409
|
+
<E, X>(
|
|
2410
|
+
handler: (e: E) => Effect.Effect<X>
|
|
2411
|
+
) => <A, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<Fiber.RuntimeFiber<A, E>, never, R>,
|
|
2412
|
+
<A, E, R, X>(
|
|
2413
|
+
self: Effect.Effect<A, E, R>,
|
|
2414
|
+
handler: (e: E) => Effect.Effect<X>
|
|
2415
|
+
) => Effect.Effect<Fiber.RuntimeFiber<A, E>, never, R>
|
|
2416
|
+
>(2, (self, handler) =>
|
|
2417
|
+
fork(core.onError(self, (cause) => {
|
|
2418
|
+
const either = internalCause.failureOrCause(cause)
|
|
2419
|
+
switch (either._tag) {
|
|
2420
|
+
case "Left":
|
|
2421
|
+
return handler(either.left)
|
|
2422
|
+
case "Right":
|
|
2423
|
+
return core.failCause(either.right)
|
|
2424
|
+
}
|
|
2425
|
+
})))
|
|
2426
|
+
|
|
2427
|
+
/** @internal */
|
|
2428
|
+
export const unsafeFork = <A, E, R, E2, B>(
|
|
2429
|
+
effect: Effect.Effect<A, E, R>,
|
|
2430
|
+
parentFiber: FiberRuntime<B, E2>,
|
|
2431
|
+
parentRuntimeFlags: RuntimeFlags.RuntimeFlags,
|
|
2432
|
+
overrideScope: fiberScope.FiberScope | null = null
|
|
2433
|
+
): FiberRuntime<A, E> => {
|
|
2434
|
+
const childFiber = unsafeMakeChildFiber(effect, parentFiber, parentRuntimeFlags, overrideScope)
|
|
2435
|
+
childFiber.resume(effect)
|
|
2436
|
+
return childFiber
|
|
2437
|
+
}
|
|
2438
|
+
|
|
2439
|
+
/** @internal */
|
|
2440
|
+
export const unsafeForkUnstarted = <A, E, R, E2, B>(
|
|
2441
|
+
effect: Effect.Effect<A, E, R>,
|
|
2442
|
+
parentFiber: FiberRuntime<B, E2>,
|
|
2443
|
+
parentRuntimeFlags: RuntimeFlags.RuntimeFlags,
|
|
2444
|
+
overrideScope: fiberScope.FiberScope | null = null
|
|
2445
|
+
): FiberRuntime<A, E> => {
|
|
2446
|
+
const childFiber = unsafeMakeChildFiber(effect, parentFiber, parentRuntimeFlags, overrideScope)
|
|
2447
|
+
return childFiber
|
|
2448
|
+
}
|
|
2449
|
+
|
|
2450
|
+
/** @internal */
|
|
2451
|
+
export const unsafeMakeChildFiber = <A, E, R, E2, B>(
|
|
2452
|
+
effect: Effect.Effect<A, E, R>,
|
|
2453
|
+
parentFiber: FiberRuntime<B, E2>,
|
|
2454
|
+
parentRuntimeFlags: RuntimeFlags.RuntimeFlags,
|
|
2455
|
+
overrideScope: fiberScope.FiberScope | null = null
|
|
2456
|
+
): FiberRuntime<A, E> => {
|
|
2457
|
+
const childId = FiberId.unsafeMake()
|
|
2458
|
+
const parentFiberRefs = parentFiber.getFiberRefs()
|
|
2459
|
+
const childFiberRefs = fiberRefs.forkAs(parentFiberRefs, childId)
|
|
2460
|
+
const childFiber = new FiberRuntime<A, E>(childId, childFiberRefs, parentRuntimeFlags)
|
|
2461
|
+
const childContext = fiberRefs.getOrDefault(
|
|
2462
|
+
childFiberRefs,
|
|
2463
|
+
core.currentContext as unknown as FiberRef.FiberRef<Context.Context<R>>
|
|
2464
|
+
)
|
|
2465
|
+
const supervisor = childFiber.currentSupervisor
|
|
2466
|
+
|
|
2467
|
+
supervisor.onStart(
|
|
2468
|
+
childContext,
|
|
2469
|
+
effect,
|
|
2470
|
+
Option.some(parentFiber),
|
|
2471
|
+
childFiber
|
|
2472
|
+
)
|
|
2473
|
+
|
|
2474
|
+
childFiber.addObserver((exit) => supervisor.onEnd(exit, childFiber))
|
|
2475
|
+
|
|
2476
|
+
const parentScope = overrideScope !== null ? overrideScope : pipe(
|
|
2477
|
+
parentFiber.getFiberRef(core.currentForkScopeOverride),
|
|
2478
|
+
Option.getOrElse(() => parentFiber.scope())
|
|
2479
|
+
)
|
|
2480
|
+
|
|
2481
|
+
parentScope.add(parentRuntimeFlags, childFiber)
|
|
2482
|
+
|
|
2483
|
+
return childFiber
|
|
2484
|
+
}
|
|
2485
|
+
|
|
2486
|
+
/* @internal */
|
|
2487
|
+
const forkWithScopeOverride = <A, E, R>(
|
|
2488
|
+
self: Effect.Effect<A, E, R>,
|
|
2489
|
+
scopeOverride: fiberScope.FiberScope
|
|
2490
|
+
): Effect.Effect<Fiber.RuntimeFiber<A, E>, never, R> =>
|
|
2491
|
+
core.withFiberRuntime((parentFiber, parentStatus) =>
|
|
2492
|
+
core.succeed(unsafeFork(self, parentFiber, parentStatus.runtimeFlags, scopeOverride))
|
|
2493
|
+
)
|
|
2494
|
+
|
|
2495
|
+
/* @internal */
|
|
2496
|
+
export const mergeAll = dual<
|
|
2497
|
+
<Z, Eff extends Effect.Effect<any, any, any>>(
|
|
2498
|
+
zero: Z,
|
|
2499
|
+
f: (z: Z, a: Effect.Effect.Success<Eff>, i: number) => Z,
|
|
2500
|
+
options?: {
|
|
2501
|
+
readonly concurrency?: Concurrency | undefined
|
|
2502
|
+
readonly batching?: boolean | "inherit" | undefined
|
|
2503
|
+
readonly concurrentFinalizers?: boolean | undefined
|
|
2504
|
+
}
|
|
2505
|
+
) => (elements: Iterable<Eff>) => Effect.Effect<Z, Effect.Effect.Error<Eff>, Effect.Effect.Context<Eff>>,
|
|
2506
|
+
<Eff extends Effect.Effect<any, any, any>, Z>(
|
|
2507
|
+
elements: Iterable<Eff>,
|
|
2508
|
+
zero: Z,
|
|
2509
|
+
f: (z: Z, a: Effect.Effect.Success<Eff>, i: number) => Z,
|
|
2510
|
+
options?: {
|
|
2511
|
+
readonly concurrency?: Concurrency | undefined
|
|
2512
|
+
readonly batching?: boolean | "inherit" | undefined
|
|
2513
|
+
readonly concurrentFinalizers?: boolean | undefined
|
|
2514
|
+
}
|
|
2515
|
+
) => Effect.Effect<Z, Effect.Effect.Error<Eff>, Effect.Effect.Context<Eff>>
|
|
2516
|
+
>(
|
|
2517
|
+
(args) => Predicate.isFunction(args[2]),
|
|
2518
|
+
<A, E, R, Z>(elements: Iterable<Effect.Effect<A, E, R>>, zero: Z, f: (z: Z, a: A, i: number) => Z, options?: {
|
|
2519
|
+
readonly concurrency?: Concurrency | undefined
|
|
2520
|
+
readonly batching?: boolean | "inherit" | undefined
|
|
2521
|
+
readonly concurrentFinalizers?: boolean | undefined
|
|
2522
|
+
}) =>
|
|
2523
|
+
concurrency.matchSimple(
|
|
2524
|
+
options?.concurrency,
|
|
2525
|
+
() =>
|
|
2526
|
+
RA.fromIterable(elements).reduce(
|
|
2527
|
+
(acc, a, i) => core.zipWith(acc, a, (acc, a) => f(acc, a, i)),
|
|
2528
|
+
core.succeed(zero) as Effect.Effect<Z, E, R>
|
|
2529
|
+
),
|
|
2530
|
+
() =>
|
|
2531
|
+
core.flatMap(Ref.make(zero), (acc) =>
|
|
2532
|
+
core.flatMap(
|
|
2533
|
+
forEach(
|
|
2534
|
+
elements,
|
|
2535
|
+
(effect, i) => core.flatMap(effect, (a) => Ref.update(acc, (b) => f(b, a, i))),
|
|
2536
|
+
options
|
|
2537
|
+
),
|
|
2538
|
+
() => Ref.get(acc)
|
|
2539
|
+
))
|
|
2540
|
+
)
|
|
2541
|
+
)
|
|
2542
|
+
|
|
2543
|
+
/* @internal */
|
|
2544
|
+
export const partition = dual<
|
|
2545
|
+
<A, B, E, R>(
|
|
2546
|
+
f: (a: A, i: number) => Effect.Effect<B, E, R>,
|
|
2547
|
+
options?: {
|
|
2548
|
+
readonly concurrency?: Concurrency | undefined
|
|
2549
|
+
readonly batching?: boolean | "inherit" | undefined
|
|
2550
|
+
readonly concurrentFinalizers?: boolean | undefined
|
|
2551
|
+
}
|
|
2552
|
+
) => (elements: Iterable<A>) => Effect.Effect<[excluded: Array<E>, satisfying: Array<B>], never, R>,
|
|
2553
|
+
<A, B, E, R>(
|
|
2554
|
+
elements: Iterable<A>,
|
|
2555
|
+
f: (a: A, i: number) => Effect.Effect<B, E, R>,
|
|
2556
|
+
options?: {
|
|
2557
|
+
readonly concurrency?: Concurrency | undefined
|
|
2558
|
+
readonly batching?: boolean | "inherit" | undefined
|
|
2559
|
+
readonly concurrentFinalizers?: boolean | undefined
|
|
2560
|
+
}
|
|
2561
|
+
) => Effect.Effect<[excluded: Array<E>, satisfying: Array<B>], never, R>
|
|
2562
|
+
>((args) => Predicate.isIterable(args[0]), (elements, f, options) =>
|
|
2563
|
+
pipe(
|
|
2564
|
+
forEach(elements, (a, i) => core.either(f(a, i)), options),
|
|
2565
|
+
core.map((chunk) => core.partitionMap(chunk, identity))
|
|
2566
|
+
))
|
|
2567
|
+
|
|
2568
|
+
/* @internal */
|
|
2569
|
+
export const validateAll = dual<
|
|
2570
|
+
{
|
|
2571
|
+
<A, B, E, R>(
|
|
2572
|
+
f: (a: A, i: number) => Effect.Effect<B, E, R>,
|
|
2573
|
+
options?: {
|
|
2574
|
+
readonly concurrency?: Concurrency | undefined
|
|
2575
|
+
readonly batching?: boolean | "inherit" | undefined
|
|
2576
|
+
readonly discard?: false | undefined
|
|
2577
|
+
readonly concurrentFinalizers?: boolean | undefined
|
|
2578
|
+
}
|
|
2579
|
+
): (elements: Iterable<A>) => Effect.Effect<Array<B>, RA.NonEmptyArray<E>, R>
|
|
2580
|
+
<A, B, E, R>(
|
|
2581
|
+
f: (a: A, i: number) => Effect.Effect<B, E, R>,
|
|
2582
|
+
options: {
|
|
2583
|
+
readonly concurrency?: Concurrency | undefined
|
|
2584
|
+
readonly batching?: boolean | "inherit" | undefined
|
|
2585
|
+
readonly discard: true
|
|
2586
|
+
readonly concurrentFinalizers?: boolean | undefined
|
|
2587
|
+
}
|
|
2588
|
+
): (elements: Iterable<A>) => Effect.Effect<void, RA.NonEmptyArray<E>, R>
|
|
2589
|
+
},
|
|
2590
|
+
{
|
|
2591
|
+
<A, B, E, R>(
|
|
2592
|
+
elements: Iterable<A>,
|
|
2593
|
+
f: (a: A, i: number) => Effect.Effect<B, E, R>,
|
|
2594
|
+
options?: {
|
|
2595
|
+
readonly concurrency?: Concurrency | undefined
|
|
2596
|
+
readonly batching?: boolean | "inherit" | undefined
|
|
2597
|
+
readonly discard?: false | undefined
|
|
2598
|
+
readonly concurrentFinalizers?: boolean | undefined
|
|
2599
|
+
}
|
|
2600
|
+
): Effect.Effect<Array<B>, RA.NonEmptyArray<E>, R>
|
|
2601
|
+
<A, B, E, R>(
|
|
2602
|
+
elements: Iterable<A>,
|
|
2603
|
+
f: (a: A, i: number) => Effect.Effect<B, E, R>,
|
|
2604
|
+
options: {
|
|
2605
|
+
readonly concurrency?: Concurrency | undefined
|
|
2606
|
+
readonly batching?: boolean | "inherit" | undefined
|
|
2607
|
+
readonly discard: true
|
|
2608
|
+
readonly concurrentFinalizers?: boolean | undefined
|
|
2609
|
+
}
|
|
2610
|
+
): Effect.Effect<void, RA.NonEmptyArray<E>, R>
|
|
2611
|
+
}
|
|
2612
|
+
>(
|
|
2613
|
+
(args) => Predicate.isIterable(args[0]),
|
|
2614
|
+
<A, B, E, R>(elements: Iterable<A>, f: (a: A, i: number) => Effect.Effect<B, E, R>, options?: {
|
|
2615
|
+
readonly concurrency?: Concurrency | undefined
|
|
2616
|
+
readonly batching?: boolean | "inherit" | undefined
|
|
2617
|
+
readonly discard?: boolean | undefined
|
|
2618
|
+
readonly concurrentFinalizers?: boolean | undefined
|
|
2619
|
+
}): Effect.Effect<any, RA.NonEmptyArray<E>, R> =>
|
|
2620
|
+
core.flatMap(
|
|
2621
|
+
partition(elements, f, {
|
|
2622
|
+
concurrency: options?.concurrency,
|
|
2623
|
+
batching: options?.batching,
|
|
2624
|
+
concurrentFinalizers: options?.concurrentFinalizers
|
|
2625
|
+
}),
|
|
2626
|
+
([es, bs]) =>
|
|
2627
|
+
RA.isNonEmptyArray(es)
|
|
2628
|
+
? core.fail(es)
|
|
2629
|
+
: options?.discard
|
|
2630
|
+
? core.void
|
|
2631
|
+
: core.succeed(bs)
|
|
2632
|
+
)
|
|
2633
|
+
)
|
|
2634
|
+
|
|
2635
|
+
/* @internal */
|
|
2636
|
+
export const raceAll: <Eff extends Effect.Effect<any, any, any>>(
|
|
2637
|
+
all: Iterable<Eff>
|
|
2638
|
+
) => Effect.Effect<Effect.Effect.Success<Eff>, Effect.Effect.Error<Eff>, Effect.Effect.Context<Eff>> = <
|
|
2639
|
+
A,
|
|
2640
|
+
E,
|
|
2641
|
+
R
|
|
2642
|
+
>(all: Iterable<Effect.Effect<A, E, R>>): Effect.Effect<A, E, R> =>
|
|
2643
|
+
core.withFiberRuntime((state, status) =>
|
|
2644
|
+
core.async<A, E, R>((resume) => {
|
|
2645
|
+
const fibers = new Set<FiberRuntime<A, E>>()
|
|
2646
|
+
let winner: FiberRuntime<A, E> | undefined
|
|
2647
|
+
let failures: Cause.Cause<E> = internalCause.empty
|
|
2648
|
+
const interruptAll = () => {
|
|
2649
|
+
for (const fiber of fibers) {
|
|
2650
|
+
fiber.unsafeInterruptAsFork(state.id())
|
|
2651
|
+
}
|
|
2652
|
+
}
|
|
2653
|
+
let latch = false
|
|
2654
|
+
let empty = true
|
|
2655
|
+
for (const self of all) {
|
|
2656
|
+
empty = false
|
|
2657
|
+
const fiber = unsafeFork(
|
|
2658
|
+
core.interruptible(self),
|
|
2659
|
+
state,
|
|
2660
|
+
status.runtimeFlags
|
|
2661
|
+
)
|
|
2662
|
+
fibers.add(fiber)
|
|
2663
|
+
fiber.addObserver((exit) => {
|
|
2664
|
+
fibers.delete(fiber)
|
|
2665
|
+
if (!winner) {
|
|
2666
|
+
if (exit._tag === "Success") {
|
|
2667
|
+
latch = true
|
|
2668
|
+
winner = fiber
|
|
2669
|
+
failures = internalCause.empty
|
|
2670
|
+
interruptAll()
|
|
2671
|
+
} else {
|
|
2672
|
+
failures = internalCause.parallel(exit.cause, failures)
|
|
2673
|
+
}
|
|
2674
|
+
}
|
|
2675
|
+
if (latch && fibers.size === 0) {
|
|
2676
|
+
resume(
|
|
2677
|
+
winner ? core.zipRight(internalFiber.inheritAll(winner), winner.unsafePoll()!) : core.failCause(failures)
|
|
2678
|
+
)
|
|
2679
|
+
}
|
|
2680
|
+
})
|
|
2681
|
+
if (winner) break
|
|
2682
|
+
}
|
|
2683
|
+
if (empty) {
|
|
2684
|
+
return resume(core.dieSync(() => new core.IllegalArgumentException(`Received an empty collection of effects`)))
|
|
2685
|
+
}
|
|
2686
|
+
latch = true
|
|
2687
|
+
return internalFiber.interruptAllAs(fibers, state.id())
|
|
2688
|
+
})
|
|
2689
|
+
)
|
|
2690
|
+
|
|
2691
|
+
/* @internal */
|
|
2692
|
+
export const reduceEffect = dual<
|
|
2693
|
+
<Z, E, R, Eff extends Effect.Effect<any, any, any>>(
|
|
2694
|
+
zero: Effect.Effect<Z, E, R>,
|
|
2695
|
+
f: (z: NoInfer<Z>, a: Effect.Effect.Success<Eff>, i: number) => Z,
|
|
2696
|
+
options?: {
|
|
2697
|
+
readonly concurrency?: Concurrency | undefined
|
|
2698
|
+
readonly batching?: boolean | "inherit" | undefined
|
|
2699
|
+
readonly concurrentFinalizers?: boolean | undefined
|
|
2700
|
+
}
|
|
2701
|
+
) => (elements: Iterable<Eff>) => Effect.Effect<Z, E | Effect.Effect.Error<Eff>, R | Effect.Effect.Context<Eff>>,
|
|
2702
|
+
<Eff extends Effect.Effect<any, any, any>, Z, E, R>(
|
|
2703
|
+
elements: Iterable<Eff>,
|
|
2704
|
+
zero: Effect.Effect<Z, E, R>,
|
|
2705
|
+
f: (z: NoInfer<Z>, a: Effect.Effect.Success<Eff>, i: number) => Z,
|
|
2706
|
+
options?: {
|
|
2707
|
+
readonly concurrency?: Concurrency | undefined
|
|
2708
|
+
readonly batching?: boolean | "inherit" | undefined
|
|
2709
|
+
readonly concurrentFinalizers?: boolean | undefined
|
|
2710
|
+
}
|
|
2711
|
+
) => Effect.Effect<Z, E | Effect.Effect.Error<Eff>, R | Effect.Effect.Context<Eff>>
|
|
2712
|
+
>((args) => Predicate.isIterable(args[0]) && !core.isEffect(args[0]), <A, E, R, Z>(
|
|
2713
|
+
elements: Iterable<Effect.Effect<A, E, R>>,
|
|
2714
|
+
zero: Effect.Effect<Z, E, R>,
|
|
2715
|
+
f: (z: NoInfer<Z>, a: NoInfer<A>, i: number) => Z,
|
|
2716
|
+
options?: {
|
|
2717
|
+
readonly concurrency?: Concurrency | undefined
|
|
2718
|
+
readonly batching?: boolean | "inherit" | undefined
|
|
2719
|
+
readonly concurrentFinalizers?: boolean | undefined
|
|
2720
|
+
}
|
|
2721
|
+
) =>
|
|
2722
|
+
concurrency.matchSimple(
|
|
2723
|
+
options?.concurrency,
|
|
2724
|
+
() => RA.fromIterable(elements).reduce((acc, a, i) => core.zipWith(acc, a, (acc, a) => f(acc, a, i)), zero),
|
|
2725
|
+
() =>
|
|
2726
|
+
core.suspend(() =>
|
|
2727
|
+
pipe(
|
|
2728
|
+
mergeAll(
|
|
2729
|
+
[zero, ...elements],
|
|
2730
|
+
Option.none<Z>(),
|
|
2731
|
+
(acc, elem, i) => {
|
|
2732
|
+
switch (acc._tag) {
|
|
2733
|
+
case "None": {
|
|
2734
|
+
return Option.some(elem as Z)
|
|
2735
|
+
}
|
|
2736
|
+
case "Some": {
|
|
2737
|
+
return Option.some(f(acc.value, elem as A, i))
|
|
2738
|
+
}
|
|
2739
|
+
}
|
|
2740
|
+
},
|
|
2741
|
+
options
|
|
2742
|
+
),
|
|
2743
|
+
core.map((option) => {
|
|
2744
|
+
switch (option._tag) {
|
|
2745
|
+
case "None": {
|
|
2746
|
+
throw new Error(
|
|
2747
|
+
"BUG: Effect.reduceEffect - please report an issue at https://github.com/Effect-TS/effect/issues"
|
|
2748
|
+
)
|
|
2749
|
+
}
|
|
2750
|
+
case "Some": {
|
|
2751
|
+
return option.value
|
|
2752
|
+
}
|
|
2753
|
+
}
|
|
2754
|
+
})
|
|
2755
|
+
)
|
|
2756
|
+
)
|
|
2757
|
+
))
|
|
2758
|
+
|
|
2759
|
+
/* @internal */
|
|
2760
|
+
export const parallelFinalizers = <A, E, R>(self: Effect.Effect<A, E, R>): Effect.Effect<A, E, R> =>
|
|
2761
|
+
core.contextWithEffect((context) =>
|
|
2762
|
+
Option.match(Context.getOption(context, scopeTag), {
|
|
2763
|
+
onNone: () => self,
|
|
2764
|
+
onSome: (scope) => {
|
|
2765
|
+
switch (scope.strategy._tag) {
|
|
2766
|
+
case "Parallel":
|
|
2767
|
+
return self
|
|
2768
|
+
case "Sequential":
|
|
2769
|
+
case "ParallelN":
|
|
2770
|
+
return core.flatMap(
|
|
2771
|
+
core.scopeFork(scope, ExecutionStrategy.parallel),
|
|
2772
|
+
(inner) => scopeExtend(self, inner)
|
|
2773
|
+
)
|
|
2774
|
+
}
|
|
2775
|
+
}
|
|
2776
|
+
})
|
|
2777
|
+
)
|
|
2778
|
+
|
|
2779
|
+
/* @internal */
|
|
2780
|
+
export const parallelNFinalizers =
|
|
2781
|
+
(parallelism: number) => <A, E, R>(self: Effect.Effect<A, E, R>): Effect.Effect<A, E, R> =>
|
|
2782
|
+
core.contextWithEffect((context) =>
|
|
2783
|
+
Option.match(Context.getOption(context, scopeTag), {
|
|
2784
|
+
onNone: () => self,
|
|
2785
|
+
onSome: (scope) => {
|
|
2786
|
+
if (scope.strategy._tag === "ParallelN" && scope.strategy.parallelism === parallelism) {
|
|
2787
|
+
return self
|
|
2788
|
+
}
|
|
2789
|
+
return core.flatMap(
|
|
2790
|
+
core.scopeFork(scope, ExecutionStrategy.parallelN(parallelism)),
|
|
2791
|
+
(inner) => scopeExtend(self, inner)
|
|
2792
|
+
)
|
|
2793
|
+
}
|
|
2794
|
+
})
|
|
2795
|
+
)
|
|
2796
|
+
|
|
2797
|
+
/* @internal */
|
|
2798
|
+
export const finalizersMask = (strategy: ExecutionStrategy.ExecutionStrategy) =>
|
|
2799
|
+
<A, E, R>(
|
|
2800
|
+
self: (
|
|
2801
|
+
restore: <A1, E1, R1>(self: Effect.Effect<A1, E1, R1>) => Effect.Effect<A1, E1, R1>
|
|
2802
|
+
) => Effect.Effect<A, E, R>
|
|
2803
|
+
): Effect.Effect<A, E, R> => finalizersMaskInternal(strategy, true)(self)
|
|
2804
|
+
|
|
2805
|
+
/* @internal */
|
|
2806
|
+
export const finalizersMaskInternal =
|
|
2807
|
+
(strategy: ExecutionStrategy.ExecutionStrategy, concurrentFinalizers?: boolean | undefined) =>
|
|
2808
|
+
<A, E, R>(
|
|
2809
|
+
self: (
|
|
2810
|
+
restore: <A1, E1, R1>(self: Effect.Effect<A1, E1, R1>) => Effect.Effect<A1, E1, R1>
|
|
2811
|
+
) => Effect.Effect<A, E, R>
|
|
2812
|
+
): Effect.Effect<A, E, R> =>
|
|
2813
|
+
core.contextWithEffect((context) =>
|
|
2814
|
+
Option.match(Context.getOption(context, scopeTag), {
|
|
2815
|
+
onNone: () => self(identity),
|
|
2816
|
+
onSome: (scope) => {
|
|
2817
|
+
if (concurrentFinalizers === true) {
|
|
2818
|
+
const patch = strategy._tag === "Parallel"
|
|
2819
|
+
? parallelFinalizers
|
|
2820
|
+
: strategy._tag === "Sequential"
|
|
2821
|
+
? sequentialFinalizers
|
|
2822
|
+
: parallelNFinalizers(strategy.parallelism)
|
|
2823
|
+
switch (scope.strategy._tag) {
|
|
2824
|
+
case "Parallel":
|
|
2825
|
+
return patch(self(parallelFinalizers))
|
|
2826
|
+
case "Sequential":
|
|
2827
|
+
return patch(self(sequentialFinalizers))
|
|
2828
|
+
case "ParallelN":
|
|
2829
|
+
return patch(self(parallelNFinalizers(scope.strategy.parallelism)))
|
|
2830
|
+
}
|
|
2831
|
+
} else {
|
|
2832
|
+
return self(identity)
|
|
2833
|
+
}
|
|
2834
|
+
}
|
|
2835
|
+
})
|
|
2836
|
+
)
|
|
2837
|
+
|
|
2838
|
+
/* @internal */
|
|
2839
|
+
export const scopeWith = <A, E, R>(
|
|
2840
|
+
f: (scope: Scope.Scope) => Effect.Effect<A, E, R>
|
|
2841
|
+
): Effect.Effect<A, E, R | Scope.Scope> => core.flatMap(scopeTag, f)
|
|
2842
|
+
|
|
2843
|
+
/** @internal */
|
|
2844
|
+
export const scopedWith = <A, E, R>(
|
|
2845
|
+
f: (scope: Scope.Scope) => Effect.Effect<A, E, R>
|
|
2846
|
+
): Effect.Effect<A, E, R> => core.flatMap(scopeMake(), (scope) => core.onExit(f(scope), (exit) => scope.close(exit)))
|
|
2847
|
+
|
|
2848
|
+
/* @internal */
|
|
2849
|
+
export const scopedEffect = <A, E, R>(effect: Effect.Effect<A, E, R>): Effect.Effect<A, E, Exclude<R, Scope.Scope>> =>
|
|
2850
|
+
core.flatMap(scopeMake(), (scope) => scopeUse(effect, scope))
|
|
2851
|
+
|
|
2852
|
+
/* @internal */
|
|
2853
|
+
export const sequentialFinalizers = <A, E, R>(self: Effect.Effect<A, E, R>): Effect.Effect<A, E, R> =>
|
|
2854
|
+
core.contextWithEffect((context) =>
|
|
2855
|
+
Option.match(Context.getOption(context, scopeTag), {
|
|
2856
|
+
onNone: () => self,
|
|
2857
|
+
onSome: (scope) => {
|
|
2858
|
+
switch (scope.strategy._tag) {
|
|
2859
|
+
case "Sequential":
|
|
2860
|
+
return self
|
|
2861
|
+
case "Parallel":
|
|
2862
|
+
case "ParallelN":
|
|
2863
|
+
return core.flatMap(
|
|
2864
|
+
core.scopeFork(scope, ExecutionStrategy.sequential),
|
|
2865
|
+
(inner) => scopeExtend(self, inner)
|
|
2866
|
+
)
|
|
2867
|
+
}
|
|
2868
|
+
}
|
|
2869
|
+
})
|
|
2870
|
+
)
|
|
2871
|
+
|
|
2872
|
+
/* @internal */
|
|
2873
|
+
export const tagMetricsScoped = (key: string, value: string): Effect.Effect<void, never, Scope.Scope> =>
|
|
2874
|
+
labelMetricsScoped([metricLabel.make(key, value)])
|
|
2875
|
+
|
|
2876
|
+
/* @internal */
|
|
2877
|
+
export const labelMetricsScoped = (
|
|
2878
|
+
labels: Iterable<MetricLabel.MetricLabel>
|
|
2879
|
+
): Effect.Effect<void, never, Scope.Scope> =>
|
|
2880
|
+
fiberRefLocallyScopedWith(core.currentMetricLabels, (old) => RA.union(old, labels))
|
|
2881
|
+
|
|
2882
|
+
/* @internal */
|
|
2883
|
+
export const using = dual<
|
|
2884
|
+
<A, A2, E2, R2>(
|
|
2885
|
+
use: (a: A) => Effect.Effect<A2, E2, R2>
|
|
2886
|
+
) => <E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<A2, E | E2, Exclude<R, Scope.Scope> | R2>,
|
|
2887
|
+
<A, E, R, A2, E2, R2>(
|
|
2888
|
+
self: Effect.Effect<A, E, R>,
|
|
2889
|
+
use: (a: A) => Effect.Effect<A2, E2, R2>
|
|
2890
|
+
) => Effect.Effect<A2, E | E2, Exclude<R, Scope.Scope> | R2>
|
|
2891
|
+
>(2, (self, use) => scopedWith((scope) => core.flatMap(scopeExtend(self, scope), use)))
|
|
2892
|
+
|
|
2893
|
+
/** @internal */
|
|
2894
|
+
export const validate = dual<
|
|
2895
|
+
<B, E1, R1>(
|
|
2896
|
+
that: Effect.Effect<B, E1, R1>,
|
|
2897
|
+
options?: {
|
|
2898
|
+
readonly concurrent?: boolean | undefined
|
|
2899
|
+
readonly batching?: boolean | "inherit" | undefined
|
|
2900
|
+
readonly concurrentFinalizers?: boolean | undefined
|
|
2901
|
+
}
|
|
2902
|
+
) => <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<[A, B], E | E1, R | R1>,
|
|
2903
|
+
<A, E, R, B, E1, R1>(
|
|
2904
|
+
self: Effect.Effect<A, E, R>,
|
|
2905
|
+
that: Effect.Effect<B, E1, R1>,
|
|
2906
|
+
options?: {
|
|
2907
|
+
readonly concurrent?: boolean | undefined
|
|
2908
|
+
readonly batching?: boolean | "inherit" | undefined
|
|
2909
|
+
readonly concurrentFinalizers?: boolean | undefined
|
|
2910
|
+
}
|
|
2911
|
+
) => Effect.Effect<[A, B], E | E1, R | R1>
|
|
2912
|
+
>(
|
|
2913
|
+
(args) => core.isEffect(args[1]),
|
|
2914
|
+
(self, that, options) => validateWith(self, that, (a, b) => [a, b], options)
|
|
2915
|
+
)
|
|
2916
|
+
|
|
2917
|
+
/** @internal */
|
|
2918
|
+
export const validateWith = dual<
|
|
2919
|
+
<B, E1, R1, A, C>(
|
|
2920
|
+
that: Effect.Effect<B, E1, R1>,
|
|
2921
|
+
f: (a: A, b: B) => C,
|
|
2922
|
+
options?: {
|
|
2923
|
+
readonly concurrent?: boolean | undefined
|
|
2924
|
+
readonly batching?: boolean | "inherit" | undefined
|
|
2925
|
+
readonly concurrentFinalizers?: boolean | undefined
|
|
2926
|
+
}
|
|
2927
|
+
) => <E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<C, E | E1, R | R1>,
|
|
2928
|
+
<A, E, R, B, E1, R1, C>(
|
|
2929
|
+
self: Effect.Effect<A, E, R>,
|
|
2930
|
+
that: Effect.Effect<B, E1, R1>,
|
|
2931
|
+
f: (a: A, b: B) => C,
|
|
2932
|
+
options?: {
|
|
2933
|
+
readonly concurrent?: boolean | undefined
|
|
2934
|
+
readonly batching?: boolean | "inherit" | undefined
|
|
2935
|
+
readonly concurrentFinalizers?: boolean | undefined
|
|
2936
|
+
}
|
|
2937
|
+
) => Effect.Effect<C, E | E1, R | R1>
|
|
2938
|
+
>((args) => core.isEffect(args[1]), (self, that, f, options) =>
|
|
2939
|
+
core.flatten(zipWithOptions(
|
|
2940
|
+
core.exit(self),
|
|
2941
|
+
core.exit(that),
|
|
2942
|
+
(ea, eb) =>
|
|
2943
|
+
core.exitZipWith(ea, eb, {
|
|
2944
|
+
onSuccess: f,
|
|
2945
|
+
onFailure: (ca, cb) => options?.concurrent ? internalCause.parallel(ca, cb) : internalCause.sequential(ca, cb)
|
|
2946
|
+
}),
|
|
2947
|
+
options
|
|
2948
|
+
)))
|
|
2949
|
+
|
|
2950
|
+
/* @internal */
|
|
2951
|
+
export const validateAllPar = dual<
|
|
2952
|
+
<A, B, E, R>(
|
|
2953
|
+
f: (a: A) => Effect.Effect<B, E, R>
|
|
2954
|
+
) => (elements: Iterable<A>) => Effect.Effect<Array<B>, Array<E>, R>,
|
|
2955
|
+
<A, B, E, R>(
|
|
2956
|
+
elements: Iterable<A>,
|
|
2957
|
+
f: (a: A) => Effect.Effect<B, E, R>
|
|
2958
|
+
) => Effect.Effect<Array<B>, Array<E>, R>
|
|
2959
|
+
>(2, (elements, f) =>
|
|
2960
|
+
core.flatMap(
|
|
2961
|
+
partition(elements, f),
|
|
2962
|
+
([es, bs]) =>
|
|
2963
|
+
es.length === 0
|
|
2964
|
+
? core.succeed(bs)
|
|
2965
|
+
: core.fail(es)
|
|
2966
|
+
))
|
|
2967
|
+
|
|
2968
|
+
/* @internal */
|
|
2969
|
+
export const validateAllParDiscard = dual<
|
|
2970
|
+
<A, B, E, R>(
|
|
2971
|
+
f: (a: A) => Effect.Effect<B, E, R>
|
|
2972
|
+
) => (elements: Iterable<A>) => Effect.Effect<void, Array<E>, R>,
|
|
2973
|
+
<A, B, E, R>(elements: Iterable<A>, f: (a: A) => Effect.Effect<B, E, R>) => Effect.Effect<void, Array<E>, R>
|
|
2974
|
+
>(2, (elements, f) =>
|
|
2975
|
+
core.flatMap(
|
|
2976
|
+
partition(elements, f),
|
|
2977
|
+
([es, _]) =>
|
|
2978
|
+
es.length === 0
|
|
2979
|
+
? core.void
|
|
2980
|
+
: core.fail(es)
|
|
2981
|
+
))
|
|
2982
|
+
|
|
2983
|
+
/* @internal */
|
|
2984
|
+
export const validateFirst = dual<
|
|
2985
|
+
<A, B, E, R>(f: (a: A, i: number) => Effect.Effect<B, E, R>, options?: {
|
|
2986
|
+
readonly concurrency?: Concurrency | undefined
|
|
2987
|
+
readonly batching?: boolean | "inherit" | undefined
|
|
2988
|
+
readonly concurrentFinalizers?: boolean | undefined
|
|
2989
|
+
}) => (elements: Iterable<A>) => Effect.Effect<B, Array<E>, R>,
|
|
2990
|
+
<A, B, E, R>(elements: Iterable<A>, f: (a: A, i: number) => Effect.Effect<B, E, R>, options?: {
|
|
2991
|
+
readonly concurrency?: Concurrency | undefined
|
|
2992
|
+
readonly batching?: boolean | "inherit" | undefined
|
|
2993
|
+
readonly concurrentFinalizers?: boolean | undefined
|
|
2994
|
+
}) => Effect.Effect<B, Array<E>, R>
|
|
2995
|
+
>(
|
|
2996
|
+
(args) => Predicate.isIterable(args[0]),
|
|
2997
|
+
(elements, f, options) => core.flip(forEach(elements, (a, i) => core.flip(f(a, i)), options))
|
|
2998
|
+
)
|
|
2999
|
+
|
|
3000
|
+
/* @internal */
|
|
3001
|
+
export const withClockScoped = <C extends Clock.Clock>(c: C) =>
|
|
3002
|
+
fiberRefLocallyScopedWith(defaultServices.currentServices, Context.add(clock.clockTag, c))
|
|
3003
|
+
|
|
3004
|
+
/* @internal */
|
|
3005
|
+
export const withRandomScoped = <A extends Random.Random>(value: A) =>
|
|
3006
|
+
fiberRefLocallyScopedWith(defaultServices.currentServices, Context.add(randomTag, value))
|
|
3007
|
+
|
|
3008
|
+
/* @internal */
|
|
3009
|
+
export const withConfigProviderScoped = (provider: ConfigProvider) =>
|
|
3010
|
+
fiberRefLocallyScopedWith(defaultServices.currentServices, Context.add(configProviderTag, provider))
|
|
3011
|
+
|
|
3012
|
+
/* @internal */
|
|
3013
|
+
export const withEarlyRelease = <A, E, R>(
|
|
3014
|
+
self: Effect.Effect<A, E, R>
|
|
3015
|
+
): Effect.Effect<[Effect.Effect<void>, A], E, R | Scope.Scope> =>
|
|
3016
|
+
scopeWith((parent) =>
|
|
3017
|
+
core.flatMap(core.scopeFork(parent, executionStrategy.sequential), (child) =>
|
|
3018
|
+
pipe(
|
|
3019
|
+
self,
|
|
3020
|
+
scopeExtend(child),
|
|
3021
|
+
core.map((value) => [
|
|
3022
|
+
core.fiberIdWith((fiberId) => core.scopeClose(child, core.exitInterrupt(fiberId))),
|
|
3023
|
+
value
|
|
3024
|
+
])
|
|
3025
|
+
))
|
|
3026
|
+
)
|
|
3027
|
+
|
|
3028
|
+
/** @internal */
|
|
3029
|
+
export const zipOptions = dual<
|
|
3030
|
+
<A2, E2, R2>(
|
|
3031
|
+
that: Effect.Effect<A2, E2, R2>,
|
|
3032
|
+
options?: {
|
|
3033
|
+
readonly concurrent?: boolean | undefined
|
|
3034
|
+
readonly batching?: boolean | "inherit" | undefined
|
|
3035
|
+
readonly concurrentFinalizers?: boolean | undefined
|
|
3036
|
+
}
|
|
3037
|
+
) => <A, E, R>(
|
|
3038
|
+
self: Effect.Effect<A, E, R>
|
|
3039
|
+
) => Effect.Effect<[A, A2], E | E2, R | R2>,
|
|
3040
|
+
<A, E, R, A2, E2, R2>(
|
|
3041
|
+
self: Effect.Effect<A, E, R>,
|
|
3042
|
+
that: Effect.Effect<A2, E2, R2>,
|
|
3043
|
+
options?: {
|
|
3044
|
+
readonly concurrent?: boolean | undefined
|
|
3045
|
+
readonly batching?: boolean | "inherit" | undefined
|
|
3046
|
+
readonly concurrentFinalizers?: boolean | undefined
|
|
3047
|
+
}
|
|
3048
|
+
) => Effect.Effect<[A, A2], E | E2, R | R2>
|
|
3049
|
+
>((args) => core.isEffect(args[1]), (
|
|
3050
|
+
self,
|
|
3051
|
+
that,
|
|
3052
|
+
options
|
|
3053
|
+
) => zipWithOptions(self, that, (a, b) => [a, b], options))
|
|
3054
|
+
|
|
3055
|
+
/** @internal */
|
|
3056
|
+
export const zipLeftOptions = dual<
|
|
3057
|
+
<A2, E2, R2>(
|
|
3058
|
+
that: Effect.Effect<A2, E2, R2>,
|
|
3059
|
+
options?: {
|
|
3060
|
+
readonly concurrent?: boolean | undefined
|
|
3061
|
+
readonly batching?: boolean | "inherit" | undefined
|
|
3062
|
+
readonly concurrentFinalizers?: boolean | undefined
|
|
3063
|
+
}
|
|
3064
|
+
) => <A, E, R>(
|
|
3065
|
+
self: Effect.Effect<A, E, R>
|
|
3066
|
+
) => Effect.Effect<A, E | E2, R | R2>,
|
|
3067
|
+
<A, E, R, A2, E2, R2>(
|
|
3068
|
+
self: Effect.Effect<A, E, R>,
|
|
3069
|
+
that: Effect.Effect<A2, E2, R2>,
|
|
3070
|
+
options?: {
|
|
3071
|
+
readonly concurrent?: boolean | undefined
|
|
3072
|
+
readonly batching?: boolean | "inherit" | undefined
|
|
3073
|
+
readonly concurrentFinalizers?: boolean | undefined
|
|
3074
|
+
}
|
|
3075
|
+
) => Effect.Effect<A, E | E2, R | R2>
|
|
3076
|
+
>(
|
|
3077
|
+
(args) => core.isEffect(args[1]),
|
|
3078
|
+
(self, that, options) => {
|
|
3079
|
+
if (options?.concurrent !== true && (options?.batching === undefined || options.batching === false)) {
|
|
3080
|
+
return core.zipLeft(self, that)
|
|
3081
|
+
}
|
|
3082
|
+
return zipWithOptions(self, that, (a, _) => a, options)
|
|
3083
|
+
}
|
|
3084
|
+
)
|
|
3085
|
+
|
|
3086
|
+
/** @internal */
|
|
3087
|
+
export const zipRightOptions: {
|
|
3088
|
+
<A2, E2, R2>(
|
|
3089
|
+
that: Effect.Effect<A2, E2, R2>,
|
|
3090
|
+
options?: {
|
|
3091
|
+
readonly concurrent?: boolean | undefined
|
|
3092
|
+
readonly batching?: boolean | "inherit" | undefined
|
|
3093
|
+
readonly concurrentFinalizers?: boolean | undefined
|
|
3094
|
+
}
|
|
3095
|
+
): <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<A2, E2 | E, R2 | R>
|
|
3096
|
+
<A, E, R, A2, E2, R2>(
|
|
3097
|
+
self: Effect.Effect<A, E, R>,
|
|
3098
|
+
that: Effect.Effect<A2, E2, R2>,
|
|
3099
|
+
options?: {
|
|
3100
|
+
readonly concurrent?: boolean | undefined
|
|
3101
|
+
readonly batching?: boolean | "inherit" | undefined
|
|
3102
|
+
readonly concurrentFinalizers?: boolean | undefined
|
|
3103
|
+
}
|
|
3104
|
+
): Effect.Effect<A2, E2 | E, R2 | R>
|
|
3105
|
+
} = dual((args) => core.isEffect(args[1]), <A, E, R, A2, E2, R2>(
|
|
3106
|
+
self: Effect.Effect<A, E, R>,
|
|
3107
|
+
that: Effect.Effect<A2, E2, R2>,
|
|
3108
|
+
options?: {
|
|
3109
|
+
readonly concurrent?: boolean | undefined
|
|
3110
|
+
readonly batching?: boolean | "inherit" | undefined
|
|
3111
|
+
readonly concurrentFinalizers?: boolean | undefined
|
|
3112
|
+
}
|
|
3113
|
+
): Effect.Effect<A2, E2 | E, R2 | R> => {
|
|
3114
|
+
if (options?.concurrent !== true && (options?.batching === undefined || options.batching === false)) {
|
|
3115
|
+
return core.zipRight(self, that)
|
|
3116
|
+
}
|
|
3117
|
+
return zipWithOptions(self, that, (_, b) => b, options)
|
|
3118
|
+
})
|
|
3119
|
+
|
|
3120
|
+
/** @internal */
|
|
3121
|
+
export const zipWithOptions: {
|
|
3122
|
+
<A2, E2, R2, A, B>(
|
|
3123
|
+
that: Effect.Effect<A2, E2, R2>,
|
|
3124
|
+
f: (a: A, b: A2) => B,
|
|
3125
|
+
options?: {
|
|
3126
|
+
readonly concurrent?: boolean | undefined
|
|
3127
|
+
readonly batching?: boolean | "inherit" | undefined
|
|
3128
|
+
readonly concurrentFinalizers?: boolean | undefined
|
|
3129
|
+
}
|
|
3130
|
+
): <E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<B, E2 | E, R2 | R>
|
|
3131
|
+
<A, E, R, A2, E2, R2, B>(
|
|
3132
|
+
self: Effect.Effect<A, E, R>,
|
|
3133
|
+
that: Effect.Effect<A2, E2, R2>,
|
|
3134
|
+
f: (a: A, b: A2) => B,
|
|
3135
|
+
options?: {
|
|
3136
|
+
readonly concurrent?: boolean | undefined
|
|
3137
|
+
readonly batching?: boolean | "inherit" | undefined
|
|
3138
|
+
readonly concurrentFinalizers?: boolean | undefined
|
|
3139
|
+
}
|
|
3140
|
+
): Effect.Effect<B, E2 | E, R2 | R>
|
|
3141
|
+
} = dual((args) => core.isEffect(args[1]), <A, E, R, A2, E2, R2, B>(
|
|
3142
|
+
self: Effect.Effect<A, E, R>,
|
|
3143
|
+
that: Effect.Effect<A2, E2, R2>,
|
|
3144
|
+
f: (a: A, b: A2) => B,
|
|
3145
|
+
options?: {
|
|
3146
|
+
readonly concurrent?: boolean | undefined
|
|
3147
|
+
readonly batching?: boolean | "inherit" | undefined
|
|
3148
|
+
readonly concurrentFinalizers?: boolean | undefined
|
|
3149
|
+
}
|
|
3150
|
+
): Effect.Effect<B, E2 | E, R2 | R> =>
|
|
3151
|
+
core.map(
|
|
3152
|
+
all([self, that], {
|
|
3153
|
+
concurrency: options?.concurrent ? 2 : 1,
|
|
3154
|
+
batching: options?.batching,
|
|
3155
|
+
concurrentFinalizers: options?.concurrentFinalizers
|
|
3156
|
+
}),
|
|
3157
|
+
([a, a2]) => f(a, a2)
|
|
3158
|
+
))
|
|
3159
|
+
|
|
3160
|
+
/* @internal */
|
|
3161
|
+
export const withRuntimeFlagsScoped = (
|
|
3162
|
+
update: RuntimeFlagsPatch.RuntimeFlagsPatch
|
|
3163
|
+
): Effect.Effect<void, never, Scope.Scope> => {
|
|
3164
|
+
if (update === RuntimeFlagsPatch.empty) {
|
|
3165
|
+
return core.void
|
|
3166
|
+
}
|
|
3167
|
+
return pipe(
|
|
3168
|
+
core.runtimeFlags,
|
|
3169
|
+
core.flatMap((runtimeFlags) => {
|
|
3170
|
+
const updatedRuntimeFlags = runtimeFlags_.patch(runtimeFlags, update)
|
|
3171
|
+
const revertRuntimeFlags = runtimeFlags_.diff(updatedRuntimeFlags, runtimeFlags)
|
|
3172
|
+
return pipe(
|
|
3173
|
+
core.updateRuntimeFlags(update),
|
|
3174
|
+
core.zipRight(addFinalizer(() => core.updateRuntimeFlags(revertRuntimeFlags))),
|
|
3175
|
+
core.asVoid
|
|
3176
|
+
)
|
|
3177
|
+
}),
|
|
3178
|
+
core.uninterruptible
|
|
3179
|
+
)
|
|
3180
|
+
}
|
|
3181
|
+
|
|
3182
|
+
// circular with Scope
|
|
3183
|
+
|
|
3184
|
+
/** @internal */
|
|
3185
|
+
export const scopeTag = Context.GenericTag<Scope.Scope>("effect/Scope")
|
|
3186
|
+
|
|
3187
|
+
/* @internal */
|
|
3188
|
+
export const scope: Effect.Effect<Scope.Scope, never, Scope.Scope> = scopeTag
|
|
3189
|
+
|
|
3190
|
+
/** @internal */
|
|
3191
|
+
export interface ScopeImpl extends Scope.CloseableScope {
|
|
3192
|
+
state: {
|
|
3193
|
+
readonly _tag: "Open"
|
|
3194
|
+
readonly finalizers: Map<{}, Scope.Scope.Finalizer>
|
|
3195
|
+
} | {
|
|
3196
|
+
readonly _tag: "Closed"
|
|
3197
|
+
readonly exit: Exit.Exit<unknown, unknown>
|
|
3198
|
+
}
|
|
3199
|
+
}
|
|
3200
|
+
|
|
3201
|
+
const scopeUnsafeAddFinalizer = (scope: ScopeImpl, fin: Scope.Scope.Finalizer): void => {
|
|
3202
|
+
if (scope.state._tag === "Open") {
|
|
3203
|
+
scope.state.finalizers.set({}, fin)
|
|
3204
|
+
}
|
|
3205
|
+
}
|
|
3206
|
+
|
|
3207
|
+
const ScopeImplProto: Omit<ScopeImpl, "strategy" | "state"> = {
|
|
3208
|
+
[core.ScopeTypeId]: core.ScopeTypeId,
|
|
3209
|
+
[core.CloseableScopeTypeId]: core.CloseableScopeTypeId,
|
|
3210
|
+
pipe() {
|
|
3211
|
+
return pipeArguments(this, arguments)
|
|
3212
|
+
},
|
|
3213
|
+
fork(this: ScopeImpl, strategy) {
|
|
3214
|
+
return core.sync(() => {
|
|
3215
|
+
const newScope = scopeUnsafeMake(strategy)
|
|
3216
|
+
if (this.state._tag === "Closed") {
|
|
3217
|
+
newScope.state = this.state
|
|
3218
|
+
return newScope
|
|
3219
|
+
}
|
|
3220
|
+
const key = {}
|
|
3221
|
+
const fin = (exit: Exit.Exit<unknown, unknown>) => newScope.close(exit)
|
|
3222
|
+
this.state.finalizers.set(key, fin)
|
|
3223
|
+
scopeUnsafeAddFinalizer(newScope, (_) =>
|
|
3224
|
+
core.sync(() => {
|
|
3225
|
+
if (this.state._tag === "Open") {
|
|
3226
|
+
this.state.finalizers.delete(key)
|
|
3227
|
+
}
|
|
3228
|
+
}))
|
|
3229
|
+
return newScope
|
|
3230
|
+
})
|
|
3231
|
+
},
|
|
3232
|
+
close(this: ScopeImpl, exit) {
|
|
3233
|
+
return core.suspend(() => {
|
|
3234
|
+
if (this.state._tag === "Closed") {
|
|
3235
|
+
return core.void
|
|
3236
|
+
}
|
|
3237
|
+
const finalizers = Array.from(this.state.finalizers.values()).reverse()
|
|
3238
|
+
this.state = { _tag: "Closed", exit }
|
|
3239
|
+
if (finalizers.length === 0) {
|
|
3240
|
+
return core.void
|
|
3241
|
+
}
|
|
3242
|
+
return executionStrategy.isSequential(this.strategy) ?
|
|
3243
|
+
pipe(
|
|
3244
|
+
core.forEachSequential(finalizers, (fin) => core.exit(fin(exit))),
|
|
3245
|
+
core.flatMap((results) =>
|
|
3246
|
+
pipe(
|
|
3247
|
+
core.exitCollectAll(results),
|
|
3248
|
+
Option.map(core.exitAsVoid),
|
|
3249
|
+
Option.getOrElse(() => core.exitVoid)
|
|
3250
|
+
)
|
|
3251
|
+
)
|
|
3252
|
+
) :
|
|
3253
|
+
executionStrategy.isParallel(this.strategy) ?
|
|
3254
|
+
pipe(
|
|
3255
|
+
forEachParUnbounded(finalizers, (fin) => core.exit(fin(exit)), false),
|
|
3256
|
+
core.flatMap((results) =>
|
|
3257
|
+
pipe(
|
|
3258
|
+
core.exitCollectAll(results, { parallel: true }),
|
|
3259
|
+
Option.map(core.exitAsVoid),
|
|
3260
|
+
Option.getOrElse(() => core.exitVoid)
|
|
3261
|
+
)
|
|
3262
|
+
)
|
|
3263
|
+
) :
|
|
3264
|
+
pipe(
|
|
3265
|
+
forEachParN(finalizers, this.strategy.parallelism, (fin) => core.exit(fin(exit)), false),
|
|
3266
|
+
core.flatMap((results) =>
|
|
3267
|
+
pipe(
|
|
3268
|
+
core.exitCollectAll(results, { parallel: true }),
|
|
3269
|
+
Option.map(core.exitAsVoid),
|
|
3270
|
+
Option.getOrElse(() => core.exitVoid)
|
|
3271
|
+
)
|
|
3272
|
+
)
|
|
3273
|
+
)
|
|
3274
|
+
})
|
|
3275
|
+
},
|
|
3276
|
+
addFinalizer(this: ScopeImpl, fin) {
|
|
3277
|
+
return core.suspend(() => {
|
|
3278
|
+
if (this.state._tag === "Closed") {
|
|
3279
|
+
return fin(this.state.exit)
|
|
3280
|
+
}
|
|
3281
|
+
this.state.finalizers.set({}, fin)
|
|
3282
|
+
return core.void
|
|
3283
|
+
})
|
|
3284
|
+
}
|
|
3285
|
+
}
|
|
3286
|
+
|
|
3287
|
+
const scopeUnsafeMake = (
|
|
3288
|
+
strategy: ExecutionStrategy.ExecutionStrategy = executionStrategy.sequential
|
|
3289
|
+
): ScopeImpl => {
|
|
3290
|
+
const scope = Object.create(ScopeImplProto)
|
|
3291
|
+
scope.strategy = strategy
|
|
3292
|
+
scope.state = { _tag: "Open", finalizers: new Map() }
|
|
3293
|
+
return scope
|
|
3294
|
+
}
|
|
3295
|
+
|
|
3296
|
+
/* @internal */
|
|
3297
|
+
export const scopeMake = (
|
|
3298
|
+
strategy: ExecutionStrategy.ExecutionStrategy = executionStrategy.sequential
|
|
3299
|
+
): Effect.Effect<Scope.Scope.Closeable> => core.sync(() => scopeUnsafeMake(strategy))
|
|
3300
|
+
|
|
3301
|
+
/* @internal */
|
|
3302
|
+
export const scopeExtend = dual<
|
|
3303
|
+
(scope: Scope.Scope) => <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, E, Exclude<R, Scope.Scope>>,
|
|
3304
|
+
<A, E, R>(effect: Effect.Effect<A, E, R>, scope: Scope.Scope) => Effect.Effect<A, E, Exclude<R, Scope.Scope>>
|
|
3305
|
+
>(
|
|
3306
|
+
2,
|
|
3307
|
+
<A, E, R>(effect: Effect.Effect<A, E, R>, scope: Scope.Scope) =>
|
|
3308
|
+
core.mapInputContext<A, E, R, Exclude<R, Scope.Scope>>(
|
|
3309
|
+
effect,
|
|
3310
|
+
// @ts-expect-error
|
|
3311
|
+
Context.merge(Context.make(scopeTag, scope))
|
|
3312
|
+
)
|
|
3313
|
+
)
|
|
3314
|
+
|
|
3315
|
+
/* @internal */
|
|
3316
|
+
export const scopeUse = dual<
|
|
3317
|
+
(
|
|
3318
|
+
scope: Scope.Scope.Closeable
|
|
3319
|
+
) => <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, E, Exclude<R, Scope.Scope>>,
|
|
3320
|
+
<A, E, R>(
|
|
3321
|
+
effect: Effect.Effect<A, E, R>,
|
|
3322
|
+
scope: Scope.Scope.Closeable
|
|
3323
|
+
) => Effect.Effect<A, E, Exclude<R, Scope.Scope>>
|
|
3324
|
+
>(2, (effect, scope) =>
|
|
3325
|
+
pipe(
|
|
3326
|
+
effect,
|
|
3327
|
+
scopeExtend(scope),
|
|
3328
|
+
core.onExit((exit) => scope.close(exit))
|
|
3329
|
+
))
|
|
3330
|
+
|
|
3331
|
+
// circular with Supervisor
|
|
3332
|
+
|
|
3333
|
+
/** @internal */
|
|
3334
|
+
export const fiberRefUnsafeMakeSupervisor = (
|
|
3335
|
+
initial: Supervisor.Supervisor<any>
|
|
3336
|
+
): FiberRef.FiberRef<Supervisor.Supervisor<any>> =>
|
|
3337
|
+
core.fiberRefUnsafeMakePatch(initial, {
|
|
3338
|
+
differ: SupervisorPatch.differ,
|
|
3339
|
+
fork: SupervisorPatch.empty
|
|
3340
|
+
})
|
|
3341
|
+
|
|
3342
|
+
// circular with FiberRef
|
|
3343
|
+
|
|
3344
|
+
/* @internal */
|
|
3345
|
+
export const fiberRefLocallyScoped = dual<
|
|
3346
|
+
<A>(value: A) => (self: FiberRef.FiberRef<A>) => Effect.Effect<void, never, Scope.Scope>,
|
|
3347
|
+
<A>(self: FiberRef.FiberRef<A>, value: A) => Effect.Effect<void, never, Scope.Scope>
|
|
3348
|
+
>(2, (self, value) =>
|
|
3349
|
+
core.asVoid(
|
|
3350
|
+
acquireRelease(
|
|
3351
|
+
core.flatMap(
|
|
3352
|
+
core.fiberRefGet(self),
|
|
3353
|
+
(oldValue) => core.as(core.fiberRefSet(self, value), oldValue)
|
|
3354
|
+
),
|
|
3355
|
+
(oldValue) => core.fiberRefSet(self, oldValue)
|
|
3356
|
+
)
|
|
3357
|
+
))
|
|
3358
|
+
|
|
3359
|
+
/* @internal */
|
|
3360
|
+
export const fiberRefLocallyScopedWith = dual<
|
|
3361
|
+
<A>(f: (a: A) => A) => (self: FiberRef.FiberRef<A>) => Effect.Effect<void, never, Scope.Scope>,
|
|
3362
|
+
<A>(self: FiberRef.FiberRef<A>, f: (a: A) => A) => Effect.Effect<void, never, Scope.Scope>
|
|
3363
|
+
>(2, (self, f) => core.fiberRefGetWith(self, (a) => fiberRefLocallyScoped(self, f(a))))
|
|
3364
|
+
|
|
3365
|
+
/* @internal */
|
|
3366
|
+
export const fiberRefMake = <A>(
|
|
3367
|
+
initial: A,
|
|
3368
|
+
options?: {
|
|
3369
|
+
readonly fork?: ((a: A) => A) | undefined
|
|
3370
|
+
readonly join?: ((left: A, right: A) => A) | undefined
|
|
3371
|
+
}
|
|
3372
|
+
): Effect.Effect<FiberRef.FiberRef<A>, never, Scope.Scope> =>
|
|
3373
|
+
fiberRefMakeWith(() => core.fiberRefUnsafeMake(initial, options))
|
|
3374
|
+
|
|
3375
|
+
/* @internal */
|
|
3376
|
+
export const fiberRefMakeWith = <Value>(
|
|
3377
|
+
ref: LazyArg<FiberRef.FiberRef<Value>>
|
|
3378
|
+
): Effect.Effect<FiberRef.FiberRef<Value>, never, Scope.Scope> =>
|
|
3379
|
+
acquireRelease(
|
|
3380
|
+
core.tap(core.sync(ref), (ref) => core.fiberRefUpdate(ref, identity)),
|
|
3381
|
+
(fiberRef) => core.fiberRefDelete(fiberRef)
|
|
3382
|
+
)
|
|
3383
|
+
|
|
3384
|
+
/* @internal */
|
|
3385
|
+
export const fiberRefMakeContext = <A>(
|
|
3386
|
+
initial: Context.Context<A>
|
|
3387
|
+
): Effect.Effect<FiberRef.FiberRef<Context.Context<A>>, never, Scope.Scope> =>
|
|
3388
|
+
fiberRefMakeWith(() => core.fiberRefUnsafeMakeContext(initial))
|
|
3389
|
+
|
|
3390
|
+
/* @internal */
|
|
3391
|
+
export const fiberRefMakeRuntimeFlags = (
|
|
3392
|
+
initial: RuntimeFlags.RuntimeFlags
|
|
3393
|
+
): Effect.Effect<FiberRef.FiberRef<RuntimeFlags.RuntimeFlags>, never, Scope.Scope> =>
|
|
3394
|
+
fiberRefMakeWith(() => core.fiberRefUnsafeMakeRuntimeFlags(initial))
|
|
3395
|
+
|
|
3396
|
+
/** @internal */
|
|
3397
|
+
export const currentRuntimeFlags: FiberRef.FiberRef<RuntimeFlags.RuntimeFlags> = core.fiberRefUnsafeMakeRuntimeFlags(
|
|
3398
|
+
runtimeFlags_.none
|
|
3399
|
+
)
|
|
3400
|
+
|
|
3401
|
+
/** @internal */
|
|
3402
|
+
export const currentSupervisor: FiberRef.FiberRef<Supervisor.Supervisor<any>> = fiberRefUnsafeMakeSupervisor(
|
|
3403
|
+
supervisor.none
|
|
3404
|
+
)
|
|
3405
|
+
|
|
3406
|
+
// circular with Fiber
|
|
3407
|
+
|
|
3408
|
+
/* @internal */
|
|
3409
|
+
export const fiberAwaitAll = <const T extends Iterable<Fiber.Fiber<any, any>>>(
|
|
3410
|
+
fibers: T
|
|
3411
|
+
): Effect.Effect<
|
|
3412
|
+
[T] extends [ReadonlyArray<infer U>]
|
|
3413
|
+
? number extends T["length"] ? Array<U extends Fiber.Fiber<infer A, infer E> ? Exit.Exit<A, E> : never>
|
|
3414
|
+
: { -readonly [K in keyof T]: T[K] extends Fiber.Fiber<infer A, infer E> ? Exit.Exit<A, E> : never }
|
|
3415
|
+
: Array<T extends Iterable<infer U> ? U extends Fiber.Fiber<infer A, infer E> ? Exit.Exit<A, E> : never : never>
|
|
3416
|
+
> => forEach(fibers, internalFiber._await) as any
|
|
3417
|
+
|
|
3418
|
+
/** @internal */
|
|
3419
|
+
export const fiberAll = <A, E>(fibers: Iterable<Fiber.Fiber<A, E>>): Fiber.Fiber<Array<A>, E> => {
|
|
3420
|
+
const _fiberAll = {
|
|
3421
|
+
...Effectable.CommitPrototype,
|
|
3422
|
+
commit() {
|
|
3423
|
+
return internalFiber.join(this)
|
|
3424
|
+
},
|
|
3425
|
+
[internalFiber.FiberTypeId]: internalFiber.fiberVariance,
|
|
3426
|
+
id: () =>
|
|
3427
|
+
RA.fromIterable(fibers).reduce((id, fiber) => FiberId.combine(id, fiber.id()), FiberId.none as FiberId.FiberId),
|
|
3428
|
+
await: core.exit(forEachParUnbounded(fibers, (fiber) => core.flatten(fiber.await), false)),
|
|
3429
|
+
children: core.map(forEachParUnbounded(fibers, (fiber) => fiber.children, false), RA.flatten),
|
|
3430
|
+
inheritAll: core.forEachSequentialDiscard(fibers, (fiber) => fiber.inheritAll),
|
|
3431
|
+
poll: core.map(
|
|
3432
|
+
core.forEachSequential(fibers, (fiber) => fiber.poll),
|
|
3433
|
+
RA.reduceRight(
|
|
3434
|
+
Option.some<Exit.Exit<Array<A>, E>>(core.exitSucceed(new Array())),
|
|
3435
|
+
(optionB, optionA) => {
|
|
3436
|
+
switch (optionA._tag) {
|
|
3437
|
+
case "None": {
|
|
3438
|
+
return Option.none()
|
|
3439
|
+
}
|
|
3440
|
+
case "Some": {
|
|
3441
|
+
switch (optionB._tag) {
|
|
3442
|
+
case "None": {
|
|
3443
|
+
return Option.none()
|
|
3444
|
+
}
|
|
3445
|
+
case "Some": {
|
|
3446
|
+
return Option.some(
|
|
3447
|
+
core.exitZipWith(optionA.value, optionB.value, {
|
|
3448
|
+
onSuccess: (a, chunk) => [a, ...chunk],
|
|
3449
|
+
onFailure: internalCause.parallel
|
|
3450
|
+
})
|
|
3451
|
+
)
|
|
3452
|
+
}
|
|
3453
|
+
}
|
|
3454
|
+
}
|
|
3455
|
+
}
|
|
3456
|
+
}
|
|
3457
|
+
)
|
|
3458
|
+
),
|
|
3459
|
+
interruptAsFork: (fiberId: FiberId.FiberId) =>
|
|
3460
|
+
core.forEachSequentialDiscard(fibers, (fiber) => fiber.interruptAsFork(fiberId))
|
|
3461
|
+
}
|
|
3462
|
+
return _fiberAll
|
|
3463
|
+
}
|
|
3464
|
+
|
|
3465
|
+
/* @internal */
|
|
3466
|
+
export const fiberInterruptFork = <A, E>(self: Fiber.Fiber<A, E>): Effect.Effect<void> =>
|
|
3467
|
+
core.asVoid(forkDaemon(core.interruptFiber(self)))
|
|
3468
|
+
|
|
3469
|
+
/* @internal */
|
|
3470
|
+
export const fiberJoinAll = <A, E>(fibers: Iterable<Fiber.Fiber<A, E>>): Effect.Effect<Array<A>, E> =>
|
|
3471
|
+
internalFiber.join(fiberAll(fibers))
|
|
3472
|
+
|
|
3473
|
+
/* @internal */
|
|
3474
|
+
export const fiberScoped = <A, E>(self: Fiber.Fiber<A, E>): Effect.Effect<Fiber.Fiber<A, E>, never, Scope.Scope> =>
|
|
3475
|
+
acquireRelease(core.succeed(self), core.interruptFiber)
|
|
3476
|
+
|
|
3477
|
+
//
|
|
3478
|
+
// circular race
|
|
3479
|
+
//
|
|
3480
|
+
|
|
3481
|
+
/** @internal */
|
|
3482
|
+
export const raceWith = dual<
|
|
3483
|
+
<A1, E1, R1, E, A, A2, E2, R2, A3, E3, R3>(
|
|
3484
|
+
other: Effect.Effect<A1, E1, R1>,
|
|
3485
|
+
options: {
|
|
3486
|
+
readonly onSelfDone: (exit: Exit.Exit<A, E>, fiber: Fiber.Fiber<A1, E1>) => Effect.Effect<A2, E2, R2>
|
|
3487
|
+
readonly onOtherDone: (exit: Exit.Exit<A1, E1>, fiber: Fiber.Fiber<A, E>) => Effect.Effect<A3, E3, R3>
|
|
3488
|
+
}
|
|
3489
|
+
) => <R>(self: Effect.Effect<A, E, R>) => Effect.Effect<A2 | A3, E2 | E3, R | R1 | R2 | R3>,
|
|
3490
|
+
<A, E, R, A1, E1, R1, A2, E2, R2, A3, E3, R3>(
|
|
3491
|
+
self: Effect.Effect<A, E, R>,
|
|
3492
|
+
other: Effect.Effect<A1, E1, R1>,
|
|
3493
|
+
options: {
|
|
3494
|
+
readonly onSelfDone: (exit: Exit.Exit<A, E>, fiber: Fiber.Fiber<A1, E1>) => Effect.Effect<A2, E2, R2>
|
|
3495
|
+
readonly onOtherDone: (exit: Exit.Exit<A1, E1>, fiber: Fiber.Fiber<A, E>) => Effect.Effect<A3, E3, R3>
|
|
3496
|
+
}
|
|
3497
|
+
) => Effect.Effect<A2 | A3, E2 | E3, R | R1 | R2 | R3>
|
|
3498
|
+
>(3, (self, other, options) =>
|
|
3499
|
+
raceFibersWith(self, other, {
|
|
3500
|
+
onSelfWin: (winner, loser) =>
|
|
3501
|
+
core.flatMap(winner.await, (exit) => {
|
|
3502
|
+
switch (exit._tag) {
|
|
3503
|
+
case OpCodes.OP_SUCCESS: {
|
|
3504
|
+
return core.flatMap(
|
|
3505
|
+
winner.inheritAll,
|
|
3506
|
+
() => options.onSelfDone(exit, loser)
|
|
3507
|
+
)
|
|
3508
|
+
}
|
|
3509
|
+
case OpCodes.OP_FAILURE: {
|
|
3510
|
+
return options.onSelfDone(exit, loser)
|
|
3511
|
+
}
|
|
3512
|
+
}
|
|
3513
|
+
}),
|
|
3514
|
+
onOtherWin: (winner, loser) =>
|
|
3515
|
+
core.flatMap(winner.await, (exit) => {
|
|
3516
|
+
switch (exit._tag) {
|
|
3517
|
+
case OpCodes.OP_SUCCESS: {
|
|
3518
|
+
return core.flatMap(
|
|
3519
|
+
winner.inheritAll,
|
|
3520
|
+
() => options.onOtherDone(exit, loser)
|
|
3521
|
+
)
|
|
3522
|
+
}
|
|
3523
|
+
case OpCodes.OP_FAILURE: {
|
|
3524
|
+
return options.onOtherDone(exit, loser)
|
|
3525
|
+
}
|
|
3526
|
+
}
|
|
3527
|
+
})
|
|
3528
|
+
}))
|
|
3529
|
+
|
|
3530
|
+
/** @internal */
|
|
3531
|
+
export const disconnect = <A, E, R>(self: Effect.Effect<A, E, R>): Effect.Effect<A, E, R> =>
|
|
3532
|
+
core.uninterruptibleMask((restore) =>
|
|
3533
|
+
core.fiberIdWith((fiberId) =>
|
|
3534
|
+
core.flatMap(forkDaemon(restore(self)), (fiber) =>
|
|
3535
|
+
pipe(
|
|
3536
|
+
restore(internalFiber.join(fiber)),
|
|
3537
|
+
core.onInterrupt(() => pipe(fiber, internalFiber.interruptAsFork(fiberId)))
|
|
3538
|
+
))
|
|
3539
|
+
)
|
|
3540
|
+
)
|
|
3541
|
+
|
|
3542
|
+
/** @internal */
|
|
3543
|
+
export const race = dual<
|
|
3544
|
+
<A2, E2, R2>(
|
|
3545
|
+
that: Effect.Effect<A2, E2, R2>
|
|
3546
|
+
) => <A, E, R>(
|
|
3547
|
+
self: Effect.Effect<A, E, R>
|
|
3548
|
+
) => Effect.Effect<A | A2, E | E2, R | R2>,
|
|
3549
|
+
<A, E, R, A2, E2, R2>(
|
|
3550
|
+
self: Effect.Effect<A, E, R>,
|
|
3551
|
+
that: Effect.Effect<A2, E2, R2>
|
|
3552
|
+
) => Effect.Effect<A | A2, E | E2, R | R2>
|
|
3553
|
+
>(
|
|
3554
|
+
2,
|
|
3555
|
+
(self, that) =>
|
|
3556
|
+
core.fiberIdWith((parentFiberId) =>
|
|
3557
|
+
raceWith(self, that, {
|
|
3558
|
+
onSelfDone: (exit, right) =>
|
|
3559
|
+
core.exitMatchEffect(exit, {
|
|
3560
|
+
onFailure: (cause) =>
|
|
3561
|
+
pipe(
|
|
3562
|
+
internalFiber.join(right),
|
|
3563
|
+
internalEffect.mapErrorCause((cause2) => internalCause.parallel(cause, cause2))
|
|
3564
|
+
),
|
|
3565
|
+
onSuccess: (value) =>
|
|
3566
|
+
pipe(
|
|
3567
|
+
right,
|
|
3568
|
+
core.interruptAsFiber(parentFiberId),
|
|
3569
|
+
core.as(value)
|
|
3570
|
+
)
|
|
3571
|
+
}),
|
|
3572
|
+
onOtherDone: (exit, left) =>
|
|
3573
|
+
core.exitMatchEffect(exit, {
|
|
3574
|
+
onFailure: (cause) =>
|
|
3575
|
+
pipe(
|
|
3576
|
+
internalFiber.join(left),
|
|
3577
|
+
internalEffect.mapErrorCause((cause2) => internalCause.parallel(cause2, cause))
|
|
3578
|
+
),
|
|
3579
|
+
onSuccess: (value) =>
|
|
3580
|
+
pipe(
|
|
3581
|
+
left,
|
|
3582
|
+
core.interruptAsFiber(parentFiberId),
|
|
3583
|
+
core.as(value)
|
|
3584
|
+
)
|
|
3585
|
+
})
|
|
3586
|
+
})
|
|
3587
|
+
)
|
|
3588
|
+
)
|
|
3589
|
+
|
|
3590
|
+
/** @internal */
|
|
3591
|
+
export const raceFibersWith = dual<
|
|
3592
|
+
<A1, E1, R1, E, A, A2, E2, R2, A3, E3, R3>(
|
|
3593
|
+
other: Effect.Effect<A1, E1, R1>,
|
|
3594
|
+
options: {
|
|
3595
|
+
readonly onSelfWin: (
|
|
3596
|
+
winner: Fiber.RuntimeFiber<A, E>,
|
|
3597
|
+
loser: Fiber.RuntimeFiber<A1, E1>
|
|
3598
|
+
) => Effect.Effect<A2, E2, R2>
|
|
3599
|
+
readonly onOtherWin: (
|
|
3600
|
+
winner: Fiber.RuntimeFiber<A1, E1>,
|
|
3601
|
+
loser: Fiber.RuntimeFiber<A, E>
|
|
3602
|
+
) => Effect.Effect<A3, E3, R3>
|
|
3603
|
+
readonly selfScope?: fiberScope.FiberScope | undefined
|
|
3604
|
+
readonly otherScope?: fiberScope.FiberScope | undefined
|
|
3605
|
+
}
|
|
3606
|
+
) => <R>(self: Effect.Effect<A, E, R>) => Effect.Effect<A2 | A3, E2 | E3, R | R1 | R2 | R3>,
|
|
3607
|
+
<A, E, R, A1, E1, R1, A2, E2, R2, A3, E3, R3>(
|
|
3608
|
+
self: Effect.Effect<A, E, R>,
|
|
3609
|
+
other: Effect.Effect<A1, E1, R1>,
|
|
3610
|
+
options: {
|
|
3611
|
+
readonly onSelfWin: (
|
|
3612
|
+
winner: Fiber.RuntimeFiber<A, E>,
|
|
3613
|
+
loser: Fiber.RuntimeFiber<A1, E1>
|
|
3614
|
+
) => Effect.Effect<A2, E2, R2>
|
|
3615
|
+
readonly onOtherWin: (
|
|
3616
|
+
winner: Fiber.RuntimeFiber<A1, E1>,
|
|
3617
|
+
loser: Fiber.RuntimeFiber<A, E>
|
|
3618
|
+
) => Effect.Effect<A3, E3, R3>
|
|
3619
|
+
readonly selfScope?: fiberScope.FiberScope | undefined
|
|
3620
|
+
readonly otherScope?: fiberScope.FiberScope | undefined
|
|
3621
|
+
}
|
|
3622
|
+
) => Effect.Effect<A2 | A3, E2 | E3, R | R1 | R2 | R3>
|
|
3623
|
+
>(3, <A, E, R, A1, E1, R1, A2, E2, R2, A3, E3, R3>(
|
|
3624
|
+
self: Effect.Effect<A, E, R>,
|
|
3625
|
+
other: Effect.Effect<A1, E1, R1>,
|
|
3626
|
+
options: {
|
|
3627
|
+
readonly onSelfWin: (
|
|
3628
|
+
winner: Fiber.RuntimeFiber<A, E>,
|
|
3629
|
+
loser: Fiber.RuntimeFiber<A1, E1>
|
|
3630
|
+
) => Effect.Effect<A2, E2, R2>
|
|
3631
|
+
readonly onOtherWin: (
|
|
3632
|
+
winner: Fiber.RuntimeFiber<A1, E1>,
|
|
3633
|
+
loser: Fiber.RuntimeFiber<A, E>
|
|
3634
|
+
) => Effect.Effect<A3, E3, R3>
|
|
3635
|
+
readonly selfScope?: fiberScope.FiberScope | undefined
|
|
3636
|
+
readonly otherScope?: fiberScope.FiberScope | undefined
|
|
3637
|
+
}
|
|
3638
|
+
) =>
|
|
3639
|
+
core.withFiberRuntime((parentFiber, parentStatus) => {
|
|
3640
|
+
const parentRuntimeFlags = parentStatus.runtimeFlags
|
|
3641
|
+
const raceIndicator = MRef.make(true)
|
|
3642
|
+
const leftFiber: FiberRuntime<A, E> = unsafeMakeChildFiber(
|
|
3643
|
+
self,
|
|
3644
|
+
parentFiber,
|
|
3645
|
+
parentRuntimeFlags,
|
|
3646
|
+
options.selfScope
|
|
3647
|
+
)
|
|
3648
|
+
const rightFiber: FiberRuntime<A1, E1> = unsafeMakeChildFiber(
|
|
3649
|
+
other,
|
|
3650
|
+
parentFiber,
|
|
3651
|
+
parentRuntimeFlags,
|
|
3652
|
+
options.otherScope
|
|
3653
|
+
)
|
|
3654
|
+
return core.async((cb) => {
|
|
3655
|
+
leftFiber.addObserver(() => completeRace(leftFiber, rightFiber, options.onSelfWin, raceIndicator, cb))
|
|
3656
|
+
rightFiber.addObserver(() => completeRace(rightFiber, leftFiber, options.onOtherWin, raceIndicator, cb))
|
|
3657
|
+
leftFiber.startFork(self)
|
|
3658
|
+
rightFiber.startFork(other)
|
|
3659
|
+
}, FiberId.combine(leftFiber.id(), rightFiber.id()))
|
|
3660
|
+
}))
|
|
3661
|
+
|
|
3662
|
+
const completeRace = <A2, A3, E2, E3, R, R1, R2, R3>(
|
|
3663
|
+
winner: Fiber.RuntimeFiber<any, any>,
|
|
3664
|
+
loser: Fiber.RuntimeFiber<any, any>,
|
|
3665
|
+
cont: (winner: Fiber.RuntimeFiber<any, any>, loser: Fiber.RuntimeFiber<any, any>) => Effect.Effect<any, any, any>,
|
|
3666
|
+
ab: MRef.MutableRef<boolean>,
|
|
3667
|
+
cb: (_: Effect.Effect<A2 | A3, E2 | E3, R | R1 | R2 | R3>) => void
|
|
3668
|
+
): void => {
|
|
3669
|
+
if (MRef.compareAndSet(true, false)(ab)) {
|
|
3670
|
+
cb(cont(winner, loser))
|
|
3671
|
+
}
|
|
3672
|
+
}
|
|
3673
|
+
|
|
3674
|
+
/** @internal */
|
|
3675
|
+
export const ensuring: {
|
|
3676
|
+
<X, R1>(
|
|
3677
|
+
finalizer: Effect.Effect<X, never, R1>
|
|
3678
|
+
): <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R1 | R>
|
|
3679
|
+
<A, E, R, X, R1>(self: Effect.Effect<A, E, R>, finalizer: Effect.Effect<X, never, R1>): Effect.Effect<A, E, R1 | R>
|
|
3680
|
+
} = dual(
|
|
3681
|
+
2,
|
|
3682
|
+
<A, E, R, X, R1>(self: Effect.Effect<A, E, R>, finalizer: Effect.Effect<X, never, R1>): Effect.Effect<A, E, R1 | R> =>
|
|
3683
|
+
core.uninterruptibleMask((restore) =>
|
|
3684
|
+
core.matchCauseEffect(restore(self), {
|
|
3685
|
+
onFailure: (cause1) =>
|
|
3686
|
+
core.matchCauseEffect(finalizer, {
|
|
3687
|
+
onFailure: (cause2) => core.failCause(internalCause.sequential(cause1, cause2)),
|
|
3688
|
+
onSuccess: () => core.failCause(cause1)
|
|
3689
|
+
}),
|
|
3690
|
+
onSuccess: (a) => core.as(finalizer, a)
|
|
3691
|
+
})
|
|
3692
|
+
)
|
|
3693
|
+
)
|
|
3694
|
+
|
|
3695
|
+
/** @internal */
|
|
3696
|
+
export const invokeWithInterrupt: <A, E, R>(
|
|
3697
|
+
self: Effect.Effect<A, E, R>,
|
|
3698
|
+
entries: ReadonlyArray<Entry<unknown>>,
|
|
3699
|
+
onInterrupt?: () => void
|
|
3700
|
+
) => Effect.Effect<void, E, R> = <A, E, R>(
|
|
3701
|
+
self: Effect.Effect<A, E, R>,
|
|
3702
|
+
entries: ReadonlyArray<Entry<unknown>>,
|
|
3703
|
+
onInterrupt?: () => void
|
|
3704
|
+
) =>
|
|
3705
|
+
core.fiberIdWith((id) =>
|
|
3706
|
+
core.flatMap(
|
|
3707
|
+
core.flatMap(
|
|
3708
|
+
forkDaemon(core.interruptible(self)),
|
|
3709
|
+
(processing) =>
|
|
3710
|
+
core.async<void, E>((cb) => {
|
|
3711
|
+
const counts = entries.map((_) => _.listeners.count)
|
|
3712
|
+
const checkDone = () => {
|
|
3713
|
+
if (counts.every((count) => count === 0)) {
|
|
3714
|
+
if (
|
|
3715
|
+
entries.every((_) => {
|
|
3716
|
+
if (_.result.state.current._tag === "Pending") {
|
|
3717
|
+
return true
|
|
3718
|
+
} else if (
|
|
3719
|
+
_.result.state.current._tag === "Done" &&
|
|
3720
|
+
core.exitIsExit(_.result.state.current.effect) &&
|
|
3721
|
+
_.result.state.current.effect._tag === "Failure" &&
|
|
3722
|
+
internalCause.isInterrupted(_.result.state.current.effect.cause)
|
|
3723
|
+
) {
|
|
3724
|
+
return true
|
|
3725
|
+
} else {
|
|
3726
|
+
return false
|
|
3727
|
+
}
|
|
3728
|
+
})
|
|
3729
|
+
) {
|
|
3730
|
+
cleanup.forEach((f) => f())
|
|
3731
|
+
onInterrupt?.()
|
|
3732
|
+
cb(core.interruptFiber(processing))
|
|
3733
|
+
}
|
|
3734
|
+
}
|
|
3735
|
+
}
|
|
3736
|
+
processing.addObserver((exit) => {
|
|
3737
|
+
cleanup.forEach((f) => f())
|
|
3738
|
+
cb(exit)
|
|
3739
|
+
})
|
|
3740
|
+
const cleanup = entries.map((r, i) => {
|
|
3741
|
+
const observer = (count: number) => {
|
|
3742
|
+
counts[i] = count
|
|
3743
|
+
checkDone()
|
|
3744
|
+
}
|
|
3745
|
+
r.listeners.addObserver(observer)
|
|
3746
|
+
return () => r.listeners.removeObserver(observer)
|
|
3747
|
+
})
|
|
3748
|
+
checkDone()
|
|
3749
|
+
return core.sync(() => {
|
|
3750
|
+
cleanup.forEach((f) => f())
|
|
3751
|
+
})
|
|
3752
|
+
})
|
|
3753
|
+
),
|
|
3754
|
+
() =>
|
|
3755
|
+
core.suspend(() => {
|
|
3756
|
+
const residual = entries.flatMap((entry) => {
|
|
3757
|
+
if (!entry.state.completed) {
|
|
3758
|
+
return [entry]
|
|
3759
|
+
}
|
|
3760
|
+
return []
|
|
3761
|
+
})
|
|
3762
|
+
return core.forEachSequentialDiscard(
|
|
3763
|
+
residual,
|
|
3764
|
+
(entry) => complete(entry.request as any, core.exitInterrupt(id))
|
|
3765
|
+
)
|
|
3766
|
+
})
|
|
3767
|
+
)
|
|
3768
|
+
)
|
|
3769
|
+
|
|
3770
|
+
/** @internal */
|
|
3771
|
+
export const interruptWhenPossible = dual<
|
|
3772
|
+
(all: Iterable<Request<any, any>>) => <A, E, R>(
|
|
3773
|
+
self: Effect.Effect<A, E, R>
|
|
3774
|
+
) => Effect.Effect<void, E, R>,
|
|
3775
|
+
<A, E, R>(
|
|
3776
|
+
self: Effect.Effect<A, E, R>,
|
|
3777
|
+
all: Iterable<Request<any, any>>
|
|
3778
|
+
) => Effect.Effect<void, E, R>
|
|
3779
|
+
>(2, (self, all) =>
|
|
3780
|
+
core.fiberRefGetWith(
|
|
3781
|
+
currentRequestMap,
|
|
3782
|
+
(map) =>
|
|
3783
|
+
core.suspend(() => {
|
|
3784
|
+
const entries = RA.fromIterable(all).flatMap((_) => map.has(_) ? [map.get(_)!] : [])
|
|
3785
|
+
return invokeWithInterrupt(self, entries)
|
|
3786
|
+
})
|
|
3787
|
+
))
|
|
3788
|
+
|
|
3789
|
+
// circular Tracer
|
|
3790
|
+
|
|
3791
|
+
/** @internal */
|
|
3792
|
+
export const makeSpanScoped = (
|
|
3793
|
+
name: string,
|
|
3794
|
+
options?: Tracer.SpanOptions | undefined
|
|
3795
|
+
): Effect.Effect<Tracer.Span, never, Scope.Scope> => {
|
|
3796
|
+
options = tracer.addSpanStackTrace(options)
|
|
3797
|
+
return core.uninterruptible(
|
|
3798
|
+
core.withFiberRuntime((fiber) => {
|
|
3799
|
+
const scope = Context.unsafeGet(fiber.getFiberRef(core.currentContext), scopeTag)
|
|
3800
|
+
const span = internalEffect.unsafeMakeSpan(fiber, name, options)
|
|
3801
|
+
const timingEnabled = fiber.getFiberRef(core.currentTracerTimingEnabled)
|
|
3802
|
+
const clock_ = Context.get(fiber.getFiberRef(defaultServices.currentServices), clock.clockTag)
|
|
3803
|
+
return core.as(
|
|
3804
|
+
core.scopeAddFinalizerExit(scope, (exit) => internalEffect.endSpan(span, exit, clock_, timingEnabled)),
|
|
3805
|
+
span
|
|
3806
|
+
)
|
|
3807
|
+
})
|
|
3808
|
+
)
|
|
3809
|
+
}
|
|
3810
|
+
|
|
3811
|
+
/* @internal */
|
|
3812
|
+
export const withTracerScoped = (value: Tracer.Tracer): Effect.Effect<void, never, Scope.Scope> =>
|
|
3813
|
+
fiberRefLocallyScopedWith(defaultServices.currentServices, Context.add(tracer.tracerTag, value))
|
|
3814
|
+
|
|
3815
|
+
/** @internal */
|
|
3816
|
+
export const withSpanScoped: {
|
|
3817
|
+
(
|
|
3818
|
+
name: string,
|
|
3819
|
+
options?: Tracer.SpanOptions
|
|
3820
|
+
): <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<A, E, Scope.Scope | Exclude<R, Tracer.ParentSpan>>
|
|
3821
|
+
<A, E, R>(
|
|
3822
|
+
self: Effect.Effect<A, E, R>,
|
|
3823
|
+
name: string,
|
|
3824
|
+
options?: Tracer.SpanOptions
|
|
3825
|
+
): Effect.Effect<A, E, Scope.Scope | Exclude<R, Tracer.ParentSpan>>
|
|
3826
|
+
} = function() {
|
|
3827
|
+
const dataFirst = typeof arguments[0] !== "string"
|
|
3828
|
+
const name = dataFirst ? arguments[1] : arguments[0]
|
|
3829
|
+
const options = tracer.addSpanStackTrace(dataFirst ? arguments[2] : arguments[1])
|
|
3830
|
+
if (dataFirst) {
|
|
3831
|
+
const self = arguments[0]
|
|
3832
|
+
return core.flatMap(
|
|
3833
|
+
makeSpanScoped(name, tracer.addSpanStackTrace(options)),
|
|
3834
|
+
(span) => internalEffect.provideService(self, tracer.spanTag, span)
|
|
3835
|
+
)
|
|
3836
|
+
}
|
|
3837
|
+
return (self: Effect.Effect<any, any, any>) =>
|
|
3838
|
+
core.flatMap(
|
|
3839
|
+
makeSpanScoped(name, tracer.addSpanStackTrace(options)),
|
|
3840
|
+
(span) => internalEffect.provideService(self, tracer.spanTag, span)
|
|
3841
|
+
)
|
|
3842
|
+
} as any
|