@clayroach/effect 3.19.14-source-capture.6 → 3.19.14-source-capture.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (371) hide show
  1. package/dist/cjs/Utils.js +1 -1
  2. package/dist/cjs/Utils.js.map +1 -1
  3. package/dist/cjs/internal/clock.js +1 -1
  4. package/dist/cjs/internal/clock.js.map +1 -1
  5. package/dist/esm/Utils.js +1 -1
  6. package/dist/esm/Utils.js.map +1 -1
  7. package/dist/esm/internal/clock.js +1 -1
  8. package/dist/esm/internal/clock.js.map +1 -1
  9. package/package.json +1 -1
  10. package/src/Arbitrary.ts +0 -1101
  11. package/src/Array.ts +0 -3589
  12. package/src/BigDecimal.ts +0 -1349
  13. package/src/BigInt.ts +0 -643
  14. package/src/Boolean.ts +0 -287
  15. package/src/Brand.ts +0 -360
  16. package/src/Cache.ts +0 -281
  17. package/src/Cause.ts +0 -1555
  18. package/src/Channel.ts +0 -2355
  19. package/src/ChildExecutorDecision.ts +0 -146
  20. package/src/Chunk.ts +0 -1495
  21. package/src/Clock.ts +0 -111
  22. package/src/Config.ts +0 -542
  23. package/src/ConfigError.ts +0 -270
  24. package/src/ConfigProvider.ts +0 -333
  25. package/src/ConfigProviderPathPatch.ts +0 -100
  26. package/src/Console.ts +0 -226
  27. package/src/Context.ts +0 -585
  28. package/src/Cron.ts +0 -706
  29. package/src/Data.ts +0 -596
  30. package/src/DateTime.ts +0 -1686
  31. package/src/DefaultServices.ts +0 -34
  32. package/src/Deferred.ts +0 -301
  33. package/src/Differ.ts +0 -450
  34. package/src/Duration.ts +0 -1000
  35. package/src/Effect.ts +0 -14839
  36. package/src/Effectable.ts +0 -107
  37. package/src/Either.ts +0 -1040
  38. package/src/Encoding.ts +0 -195
  39. package/src/Equal.ts +0 -98
  40. package/src/Equivalence.ts +0 -235
  41. package/src/ExecutionPlan.ts +0 -308
  42. package/src/ExecutionStrategy.ts +0 -119
  43. package/src/Exit.ts +0 -467
  44. package/src/FastCheck.ts +0 -9
  45. package/src/Fiber.ts +0 -744
  46. package/src/FiberHandle.ts +0 -540
  47. package/src/FiberId.ts +0 -195
  48. package/src/FiberMap.ts +0 -656
  49. package/src/FiberRef.ts +0 -431
  50. package/src/FiberRefs.ts +0 -204
  51. package/src/FiberRefsPatch.ts +0 -105
  52. package/src/FiberSet.ts +0 -491
  53. package/src/FiberStatus.ts +0 -108
  54. package/src/Function.ts +0 -1222
  55. package/src/GlobalValue.ts +0 -53
  56. package/src/Graph.ts +0 -3732
  57. package/src/GroupBy.ts +0 -103
  58. package/src/HKT.ts +0 -45
  59. package/src/Hash.ts +0 -195
  60. package/src/HashMap.ts +0 -519
  61. package/src/HashRing.ts +0 -317
  62. package/src/HashSet.ts +0 -2346
  63. package/src/Inspectable.ts +0 -287
  64. package/src/Iterable.ts +0 -1119
  65. package/src/JSONSchema.ts +0 -1044
  66. package/src/KeyedPool.ts +0 -167
  67. package/src/Layer.ts +0 -1251
  68. package/src/LayerMap.ts +0 -436
  69. package/src/List.ts +0 -977
  70. package/src/LogLevel.ts +0 -285
  71. package/src/LogSpan.ts +0 -25
  72. package/src/Logger.ts +0 -702
  73. package/src/Mailbox.ts +0 -268
  74. package/src/ManagedRuntime.ts +0 -180
  75. package/src/Match.ts +0 -1477
  76. package/src/MergeDecision.ts +0 -95
  77. package/src/MergeState.ts +0 -172
  78. package/src/MergeStrategy.ts +0 -107
  79. package/src/Metric.ts +0 -780
  80. package/src/MetricBoundaries.ts +0 -69
  81. package/src/MetricHook.ts +0 -151
  82. package/src/MetricKey.ts +0 -224
  83. package/src/MetricKeyType.ts +0 -262
  84. package/src/MetricLabel.ts +0 -47
  85. package/src/MetricPair.ts +0 -71
  86. package/src/MetricPolling.ts +0 -148
  87. package/src/MetricRegistry.ts +0 -48
  88. package/src/MetricState.ts +0 -257
  89. package/src/Micro.ts +0 -4405
  90. package/src/ModuleVersion.ts +0 -18
  91. package/src/MutableHashMap.ts +0 -411
  92. package/src/MutableHashSet.ts +0 -706
  93. package/src/MutableList.ts +0 -297
  94. package/src/MutableQueue.ts +0 -227
  95. package/src/MutableRef.ts +0 -202
  96. package/src/NonEmptyIterable.ts +0 -32
  97. package/src/Number.ts +0 -1071
  98. package/src/Option.ts +0 -2170
  99. package/src/Order.ts +0 -373
  100. package/src/Ordering.ts +0 -111
  101. package/src/ParseResult.ts +0 -2031
  102. package/src/PartitionedSemaphore.ts +0 -200
  103. package/src/Pipeable.ts +0 -566
  104. package/src/Pool.ts +0 -204
  105. package/src/Predicate.ts +0 -1405
  106. package/src/Pretty.ts +0 -205
  107. package/src/PrimaryKey.ts +0 -23
  108. package/src/PubSub.ts +0 -182
  109. package/src/Queue.ts +0 -644
  110. package/src/Random.ts +0 -204
  111. package/src/RateLimiter.ts +0 -138
  112. package/src/RcMap.ts +0 -141
  113. package/src/RcRef.ts +0 -122
  114. package/src/Readable.ts +0 -93
  115. package/src/Record.ts +0 -1274
  116. package/src/RedBlackTree.ts +0 -421
  117. package/src/Redacted.ts +0 -144
  118. package/src/Ref.ts +0 -180
  119. package/src/RegExp.ts +0 -38
  120. package/src/Reloadable.ts +0 -127
  121. package/src/Request.ts +0 -347
  122. package/src/RequestBlock.ts +0 -118
  123. package/src/RequestResolver.ts +0 -366
  124. package/src/Resource.ts +0 -119
  125. package/src/Runtime.ts +0 -383
  126. package/src/RuntimeFlags.ts +0 -368
  127. package/src/RuntimeFlagsPatch.ts +0 -183
  128. package/src/STM.ts +0 -2045
  129. package/src/Schedule.ts +0 -2219
  130. package/src/ScheduleDecision.ts +0 -62
  131. package/src/ScheduleInterval.ts +0 -151
  132. package/src/ScheduleIntervals.ts +0 -122
  133. package/src/Scheduler.ts +0 -353
  134. package/src/Schema.ts +0 -10914
  135. package/src/SchemaAST.ts +0 -3043
  136. package/src/Scope.ts +0 -204
  137. package/src/ScopedCache.ts +0 -151
  138. package/src/ScopedRef.ts +0 -117
  139. package/src/Secret.ts +0 -88
  140. package/src/SingleProducerAsyncInput.ts +0 -67
  141. package/src/Sink.ts +0 -1461
  142. package/src/SortedMap.ts +0 -287
  143. package/src/SortedSet.ts +0 -390
  144. package/src/Stream.ts +0 -6468
  145. package/src/StreamEmit.ts +0 -136
  146. package/src/StreamHaltStrategy.ts +0 -123
  147. package/src/Streamable.ts +0 -45
  148. package/src/String.ts +0 -778
  149. package/src/Struct.ts +0 -243
  150. package/src/Subscribable.ts +0 -100
  151. package/src/SubscriptionRef.ts +0 -298
  152. package/src/Supervisor.ts +0 -240
  153. package/src/Symbol.ts +0 -29
  154. package/src/SynchronizedRef.ts +0 -270
  155. package/src/TArray.ts +0 -495
  156. package/src/TDeferred.ts +0 -100
  157. package/src/TMap.ts +0 -515
  158. package/src/TPriorityQueue.ts +0 -223
  159. package/src/TPubSub.ts +0 -200
  160. package/src/TQueue.ts +0 -432
  161. package/src/TRandom.ts +0 -129
  162. package/src/TReentrantLock.ts +0 -224
  163. package/src/TRef.ts +0 -178
  164. package/src/TSemaphore.ts +0 -129
  165. package/src/TSet.ts +0 -365
  166. package/src/TSubscriptionRef.ts +0 -192
  167. package/src/Take.ts +0 -258
  168. package/src/TestAnnotation.ts +0 -158
  169. package/src/TestAnnotationMap.ts +0 -119
  170. package/src/TestAnnotations.ts +0 -117
  171. package/src/TestClock.ts +0 -556
  172. package/src/TestConfig.ts +0 -47
  173. package/src/TestContext.ts +0 -36
  174. package/src/TestLive.ts +0 -53
  175. package/src/TestServices.ts +0 -390
  176. package/src/TestSized.ts +0 -55
  177. package/src/Tracer.ts +0 -198
  178. package/src/Trie.ts +0 -840
  179. package/src/Tuple.ts +0 -305
  180. package/src/Types.ts +0 -353
  181. package/src/Unify.ts +0 -113
  182. package/src/UpstreamPullRequest.ts +0 -117
  183. package/src/UpstreamPullStrategy.ts +0 -121
  184. package/src/Utils.ts +0 -809
  185. package/src/index.ts +0 -1561
  186. package/src/internal/array.ts +0 -8
  187. package/src/internal/blockedRequests.ts +0 -520
  188. package/src/internal/cache.ts +0 -733
  189. package/src/internal/cause.ts +0 -1050
  190. package/src/internal/channel/channelExecutor.ts +0 -1200
  191. package/src/internal/channel/channelState.ts +0 -134
  192. package/src/internal/channel/childExecutorDecision.ts +0 -96
  193. package/src/internal/channel/continuation.ts +0 -200
  194. package/src/internal/channel/mergeDecision.ts +0 -113
  195. package/src/internal/channel/mergeState.ts +0 -120
  196. package/src/internal/channel/mergeStrategy.ts +0 -72
  197. package/src/internal/channel/singleProducerAsyncInput.ts +0 -259
  198. package/src/internal/channel/subexecutor.ts +0 -229
  199. package/src/internal/channel/upstreamPullRequest.ts +0 -84
  200. package/src/internal/channel/upstreamPullStrategy.ts +0 -87
  201. package/src/internal/channel.ts +0 -2603
  202. package/src/internal/clock.ts +0 -95
  203. package/src/internal/completedRequestMap.ts +0 -9
  204. package/src/internal/concurrency.ts +0 -54
  205. package/src/internal/config.ts +0 -716
  206. package/src/internal/configError.ts +0 -304
  207. package/src/internal/configProvider/pathPatch.ts +0 -97
  208. package/src/internal/configProvider.ts +0 -799
  209. package/src/internal/console.ts +0 -153
  210. package/src/internal/context.ts +0 -337
  211. package/src/internal/core-effect.ts +0 -2293
  212. package/src/internal/core-stream.ts +0 -998
  213. package/src/internal/core.ts +0 -3273
  214. package/src/internal/data.ts +0 -36
  215. package/src/internal/dataSource.ts +0 -327
  216. package/src/internal/dateTime.ts +0 -1277
  217. package/src/internal/defaultServices/console.ts +0 -100
  218. package/src/internal/defaultServices.ts +0 -163
  219. package/src/internal/deferred.ts +0 -46
  220. package/src/internal/differ/chunkPatch.ts +0 -211
  221. package/src/internal/differ/contextPatch.ts +0 -232
  222. package/src/internal/differ/hashMapPatch.ts +0 -220
  223. package/src/internal/differ/hashSetPatch.ts +0 -176
  224. package/src/internal/differ/orPatch.ts +0 -311
  225. package/src/internal/differ/readonlyArrayPatch.ts +0 -210
  226. package/src/internal/differ.ts +0 -200
  227. package/src/internal/doNotation.ts +0 -80
  228. package/src/internal/effect/circular.ts +0 -905
  229. package/src/internal/effectable.ts +0 -131
  230. package/src/internal/either.ts +0 -110
  231. package/src/internal/encoding/base64.ts +0 -286
  232. package/src/internal/encoding/base64Url.ts +0 -29
  233. package/src/internal/encoding/common.ts +0 -51
  234. package/src/internal/encoding/hex.ts +0 -315
  235. package/src/internal/errors.ts +0 -7
  236. package/src/internal/executionPlan.ts +0 -114
  237. package/src/internal/executionStrategy.ts +0 -74
  238. package/src/internal/fiber.ts +0 -388
  239. package/src/internal/fiberId.ts +0 -267
  240. package/src/internal/fiberMessage.ts +0 -82
  241. package/src/internal/fiberRefs/patch.ts +0 -144
  242. package/src/internal/fiberRefs.ts +0 -297
  243. package/src/internal/fiberRuntime.ts +0 -3915
  244. package/src/internal/fiberScope.ts +0 -71
  245. package/src/internal/fiberStatus.ts +0 -119
  246. package/src/internal/groupBy.ts +0 -530
  247. package/src/internal/hashMap/array.ts +0 -49
  248. package/src/internal/hashMap/bitwise.ts +0 -32
  249. package/src/internal/hashMap/config.ts +0 -14
  250. package/src/internal/hashMap/keySet.ts +0 -8
  251. package/src/internal/hashMap/node.ts +0 -391
  252. package/src/internal/hashMap.ts +0 -586
  253. package/src/internal/hashSet.ts +0 -323
  254. package/src/internal/keyedPool.ts +0 -244
  255. package/src/internal/layer/circular.ts +0 -228
  256. package/src/internal/layer.ts +0 -1487
  257. package/src/internal/logSpan.ts +0 -20
  258. package/src/internal/logger-circular.ts +0 -24
  259. package/src/internal/logger.ts +0 -485
  260. package/src/internal/mailbox.ts +0 -561
  261. package/src/internal/managedRuntime/circular.ts +0 -6
  262. package/src/internal/managedRuntime.ts +0 -134
  263. package/src/internal/matcher.ts +0 -652
  264. package/src/internal/metric/boundaries.ts +0 -75
  265. package/src/internal/metric/hook.ts +0 -483
  266. package/src/internal/metric/key.ts +0 -167
  267. package/src/internal/metric/keyType.ts +0 -238
  268. package/src/internal/metric/label.ts +0 -41
  269. package/src/internal/metric/pair.ts +0 -48
  270. package/src/internal/metric/polling.ts +0 -149
  271. package/src/internal/metric/registry.ts +0 -187
  272. package/src/internal/metric/state.ts +0 -290
  273. package/src/internal/metric.ts +0 -577
  274. package/src/internal/opCodes/cause.ts +0 -35
  275. package/src/internal/opCodes/channel.ts +0 -83
  276. package/src/internal/opCodes/channelChildExecutorDecision.ts +0 -17
  277. package/src/internal/opCodes/channelMergeDecision.ts +0 -11
  278. package/src/internal/opCodes/channelMergeState.ts +0 -17
  279. package/src/internal/opCodes/channelMergeStrategy.ts +0 -11
  280. package/src/internal/opCodes/channelState.ts +0 -23
  281. package/src/internal/opCodes/channelUpstreamPullRequest.ts +0 -11
  282. package/src/internal/opCodes/channelUpstreamPullStrategy.ts +0 -11
  283. package/src/internal/opCodes/config.ts +0 -65
  284. package/src/internal/opCodes/configError.ts +0 -35
  285. package/src/internal/opCodes/continuation.ts +0 -11
  286. package/src/internal/opCodes/deferred.ts +0 -11
  287. package/src/internal/opCodes/effect.ts +0 -89
  288. package/src/internal/opCodes/layer.ts +0 -59
  289. package/src/internal/opCodes/streamHaltStrategy.ts +0 -23
  290. package/src/internal/option.ts +0 -80
  291. package/src/internal/pool.ts +0 -432
  292. package/src/internal/pubsub.ts +0 -1762
  293. package/src/internal/query.ts +0 -204
  294. package/src/internal/queue.ts +0 -766
  295. package/src/internal/random.ts +0 -161
  296. package/src/internal/rateLimiter.ts +0 -93
  297. package/src/internal/rcMap.ts +0 -285
  298. package/src/internal/rcRef.ts +0 -192
  299. package/src/internal/redBlackTree/iterator.ts +0 -200
  300. package/src/internal/redBlackTree/node.ts +0 -68
  301. package/src/internal/redBlackTree.ts +0 -1245
  302. package/src/internal/redacted.ts +0 -73
  303. package/src/internal/ref.ts +0 -171
  304. package/src/internal/reloadable.ts +0 -140
  305. package/src/internal/request.ts +0 -177
  306. package/src/internal/resource.ts +0 -76
  307. package/src/internal/ringBuffer.ts +0 -68
  308. package/src/internal/runtime.ts +0 -558
  309. package/src/internal/runtimeFlags.ts +0 -188
  310. package/src/internal/runtimeFlagsPatch.ts +0 -103
  311. package/src/internal/schedule/decision.ts +0 -47
  312. package/src/internal/schedule/interval.ts +0 -101
  313. package/src/internal/schedule/intervals.ts +0 -180
  314. package/src/internal/schedule.ts +0 -2199
  315. package/src/internal/schema/errors.ts +0 -191
  316. package/src/internal/schema/schemaId.ts +0 -106
  317. package/src/internal/schema/util.ts +0 -50
  318. package/src/internal/scopedCache.ts +0 -644
  319. package/src/internal/scopedRef.ts +0 -118
  320. package/src/internal/secret.ts +0 -89
  321. package/src/internal/singleShotGen.ts +0 -35
  322. package/src/internal/sink.ts +0 -2120
  323. package/src/internal/stack.ts +0 -10
  324. package/src/internal/stm/core.ts +0 -817
  325. package/src/internal/stm/entry.ts +0 -59
  326. package/src/internal/stm/journal.ts +0 -123
  327. package/src/internal/stm/opCodes/stm.ts +0 -71
  328. package/src/internal/stm/opCodes/stmState.ts +0 -17
  329. package/src/internal/stm/opCodes/strategy.ts +0 -17
  330. package/src/internal/stm/opCodes/tExit.ts +0 -29
  331. package/src/internal/stm/opCodes/tryCommit.ts +0 -11
  332. package/src/internal/stm/stm.ts +0 -1453
  333. package/src/internal/stm/stmState.ts +0 -136
  334. package/src/internal/stm/tArray.ts +0 -550
  335. package/src/internal/stm/tDeferred.ts +0 -81
  336. package/src/internal/stm/tExit.ts +0 -190
  337. package/src/internal/stm/tMap.ts +0 -824
  338. package/src/internal/stm/tPriorityQueue.ts +0 -267
  339. package/src/internal/stm/tPubSub.ts +0 -551
  340. package/src/internal/stm/tQueue.ts +0 -393
  341. package/src/internal/stm/tRandom.ts +0 -140
  342. package/src/internal/stm/tReentrantLock.ts +0 -352
  343. package/src/internal/stm/tRef.ts +0 -195
  344. package/src/internal/stm/tSemaphore.ts +0 -113
  345. package/src/internal/stm/tSet.ts +0 -259
  346. package/src/internal/stm/tSubscriptionRef.ts +0 -286
  347. package/src/internal/stm/tryCommit.ts +0 -34
  348. package/src/internal/stm/txnId.ts +0 -14
  349. package/src/internal/stm/versioned.ts +0 -4
  350. package/src/internal/stream/debounceState.ts +0 -57
  351. package/src/internal/stream/emit.ts +0 -123
  352. package/src/internal/stream/haltStrategy.ts +0 -94
  353. package/src/internal/stream/handoff.ts +0 -187
  354. package/src/internal/stream/handoffSignal.ts +0 -59
  355. package/src/internal/stream/pull.ts +0 -34
  356. package/src/internal/stream/sinkEndReason.ts +0 -30
  357. package/src/internal/stream/zipAllState.ts +0 -88
  358. package/src/internal/stream/zipChunksState.ts +0 -56
  359. package/src/internal/stream.ts +0 -8801
  360. package/src/internal/string-utils.ts +0 -107
  361. package/src/internal/subscriptionRef.ts +0 -138
  362. package/src/internal/supervisor/patch.ts +0 -190
  363. package/src/internal/supervisor.ts +0 -303
  364. package/src/internal/synchronizedRef.ts +0 -114
  365. package/src/internal/take.ts +0 -199
  366. package/src/internal/testing/sleep.ts +0 -27
  367. package/src/internal/testing/suspendedWarningData.ts +0 -85
  368. package/src/internal/testing/warningData.ts +0 -94
  369. package/src/internal/tracer.ts +0 -293
  370. package/src/internal/trie.ts +0 -722
  371. package/src/internal/version.ts +0 -7
@@ -1,3915 +0,0 @@
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
- // Capture stack trace early (while user code is on stack)
1973
- const rawStack = new Error().stack ?? ""
1974
-
1975
- const [effects, reconcile] = allResolveInput(arg)
1976
- const count = Array.isArray(effects) ? effects.length : undefined
1977
-
1978
- let result: Effect.Effect<any, any, any>
1979
-
1980
- if (options?.mode === "validate") {
1981
- result = allValidate(effects, reconcile, options) as any
1982
- } else if (options?.mode === "either") {
1983
- result = allEither(effects, reconcile, options) as any
1984
- } else {
1985
- result = options?.discard !== true && reconcile._tag === "Some"
1986
- ? core.map(
1987
- forEach(effects, identity, options as any),
1988
- reconcile.value
1989
- ) as any
1990
- : forEach(effects, identity, options as any) as any
1991
- }
1992
-
1993
- // Set operation metadata in trace field for OpSupervision
1994
- ;(result as any).trace = core.makeOperationMeta("all", rawStack, count)
1995
-
1996
- return result as Effect.All.Return<Arg, O>
1997
- }
1998
-
1999
- /* @internal */
2000
- export const allWith = <
2001
- O extends NoExcessProperties<{
2002
- readonly concurrency?: Concurrency | undefined
2003
- readonly batching?: boolean | "inherit" | undefined
2004
- readonly discard?: boolean | undefined
2005
- readonly mode?: "default" | "validate" | "either" | undefined
2006
- readonly concurrentFinalizers?: boolean | undefined
2007
- }, O>
2008
- >(options?: O) =>
2009
- <const Arg extends Iterable<Effect.Effect<any, any, any>> | Record<string, Effect.Effect<any, any, any>>>(
2010
- arg: Arg
2011
- ): Effect.All.Return<Arg, O> => all(arg, options)
2012
-
2013
- /* @internal */
2014
- export const allSuccesses = <Eff extends Effect.Effect<any, any, any>>(
2015
- elements: Iterable<Eff>,
2016
- options?: {
2017
- readonly concurrency?: Concurrency | undefined
2018
- readonly batching?: boolean | "inherit" | undefined
2019
- readonly concurrentFinalizers?: boolean | undefined
2020
- }
2021
- ): Effect.Effect<Array<Effect.Effect.Success<Eff>>, never, Effect.Effect.Context<Eff>> =>
2022
- core.map(
2023
- all(RA.fromIterable(elements).map(core.exit), options),
2024
- RA.filterMap((exit) => core.exitIsSuccess(exit) ? Option.some(exit.effect_instruction_i0) : Option.none())
2025
- )
2026
-
2027
- /* @internal */
2028
- export const replicate = dual<
2029
- (n: number) => <A, E, R>(self: Effect.Effect<A, E, R>) => Array<Effect.Effect<A, E, R>>,
2030
- <A, E, R>(self: Effect.Effect<A, E, R>, n: number) => Array<Effect.Effect<A, E, R>>
2031
- >(2, (self, n) => Array.from({ length: n }, () => self))
2032
-
2033
- /* @internal */
2034
- export const replicateEffect: {
2035
- (
2036
- n: number,
2037
- options?: {
2038
- readonly concurrency?: Concurrency | undefined
2039
- readonly batching?: boolean | "inherit" | undefined
2040
- readonly discard?: false | undefined
2041
- readonly concurrentFinalizers?: boolean | undefined
2042
- }
2043
- ): <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<Array<A>, E, R>
2044
- (
2045
- n: number,
2046
- options: {
2047
- readonly concurrency?: Concurrency | undefined
2048
- readonly batching?: boolean | "inherit" | undefined
2049
- readonly discard: true
2050
- readonly concurrentFinalizers?: boolean | undefined
2051
- }
2052
- ): <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<void, E, R>
2053
- <A, E, R>(
2054
- self: Effect.Effect<A, E, R>,
2055
- n: number,
2056
- options?: {
2057
- readonly concurrency?: Concurrency | undefined
2058
- readonly batching?: boolean | "inherit" | undefined
2059
- readonly discard?: false | undefined
2060
- readonly concurrentFinalizers?: boolean | undefined
2061
- }
2062
- ): Effect.Effect<Array<A>, E, R>
2063
- <A, E, R>(
2064
- self: Effect.Effect<A, E, R>,
2065
- n: number,
2066
- options: {
2067
- readonly concurrency?: Concurrency | undefined
2068
- readonly batching?: boolean | "inherit" | undefined
2069
- readonly discard: true
2070
- readonly concurrentFinalizers?: boolean | undefined
2071
- }
2072
- ): Effect.Effect<void, E, R>
2073
- } = dual(
2074
- (args) => core.isEffect(args[0]),
2075
- (self, n, options) => all(replicate(self, n), options)
2076
- )
2077
-
2078
- /* @internal */
2079
- export const forEach: {
2080
- <B, E, R, S extends Iterable<any>>(
2081
- f: (a: RA.ReadonlyArray.Infer<S>, i: number) => Effect.Effect<B, E, R>,
2082
- options?: {
2083
- readonly concurrency?: Concurrency | undefined
2084
- readonly batching?: boolean | "inherit" | undefined
2085
- readonly discard?: false | undefined
2086
- readonly concurrentFinalizers?: boolean | undefined
2087
- } | undefined
2088
- ): (
2089
- self: S
2090
- ) => Effect.Effect<RA.ReadonlyArray.With<S, B>, E, R>
2091
- <A, B, E, R>(
2092
- f: (a: A, i: number) => Effect.Effect<B, E, R>,
2093
- options: {
2094
- readonly concurrency?: Concurrency | undefined
2095
- readonly batching?: boolean | "inherit" | undefined
2096
- readonly discard: true
2097
- readonly concurrentFinalizers?: boolean | undefined
2098
- }
2099
- ): (self: Iterable<A>) => Effect.Effect<void, E, R>
2100
- <A, B, E, R>(
2101
- self: RA.NonEmptyReadonlyArray<A>,
2102
- f: (a: A, i: number) => Effect.Effect<B, E, R>,
2103
- options?: {
2104
- readonly concurrency?: Concurrency | undefined
2105
- readonly batching?: boolean | "inherit" | undefined
2106
- readonly discard?: false | undefined
2107
- readonly concurrentFinalizers?: boolean | undefined
2108
- } | undefined
2109
- ): Effect.Effect<RA.NonEmptyArray<B>, E, R>
2110
- <A, B, E, R>(
2111
- self: Iterable<A>,
2112
- f: (a: A, i: number) => Effect.Effect<B, E, R>,
2113
- options?: {
2114
- readonly concurrency?: Concurrency | undefined
2115
- readonly batching?: boolean | "inherit" | undefined
2116
- readonly discard?: false | undefined
2117
- readonly concurrentFinalizers?: boolean | undefined
2118
- } | undefined
2119
- ): Effect.Effect<Array<B>, E, R>
2120
- <A, B, E, R>(
2121
- self: Iterable<A>,
2122
- f: (a: A, i: number) => Effect.Effect<B, E, R>,
2123
- options: {
2124
- readonly concurrency?: Concurrency | undefined
2125
- readonly batching?: boolean | "inherit" | undefined
2126
- readonly discard: true
2127
- readonly concurrentFinalizers?: boolean | undefined
2128
- }
2129
- ): Effect.Effect<void, E, R>
2130
- } = dual((args) => Predicate.isIterable(args[0]), <A, R, E, B>(
2131
- self: Iterable<A>,
2132
- f: (a: A, i: number) => Effect.Effect<B, E, R>,
2133
- options?: {
2134
- readonly concurrency?: Concurrency | undefined
2135
- readonly batching?: boolean | "inherit" | undefined
2136
- readonly discard?: boolean | undefined
2137
- readonly concurrentFinalizers?: boolean | undefined
2138
- }
2139
- ) => {
2140
- // Capture stack trace early (while user code is on stack)
2141
- const rawStack = new Error().stack ?? ""
2142
- const count = Array.isArray(self) ? self.length : undefined
2143
-
2144
- const result = core.withFiberRuntime<A | void, E, R>((r) => {
2145
- const isRequestBatchingEnabled = options?.batching === true ||
2146
- (options?.batching === "inherit" && r.getFiberRef(core.currentRequestBatching))
2147
-
2148
- if (options?.discard) {
2149
- return concurrency.match(
2150
- options.concurrency,
2151
- () =>
2152
- finalizersMaskInternal(ExecutionStrategy.sequential, options?.concurrentFinalizers)((restore) =>
2153
- isRequestBatchingEnabled
2154
- ? forEachConcurrentDiscard(self, (a, i) => restore(f(a, i)), true, false, 1)
2155
- : core.forEachSequentialDiscard(self, (a, i) => restore(f(a, i)))
2156
- ),
2157
- () =>
2158
- finalizersMaskInternal(ExecutionStrategy.parallel, options?.concurrentFinalizers)((restore) =>
2159
- forEachConcurrentDiscard(self, (a, i) => restore(f(a, i)), isRequestBatchingEnabled, false)
2160
- ),
2161
- (n) =>
2162
- finalizersMaskInternal(ExecutionStrategy.parallelN(n), options?.concurrentFinalizers)((restore) =>
2163
- forEachConcurrentDiscard(self, (a, i) => restore(f(a, i)), isRequestBatchingEnabled, false, n)
2164
- )
2165
- )
2166
- }
2167
-
2168
- return concurrency.match(
2169
- options?.concurrency,
2170
- () =>
2171
- finalizersMaskInternal(ExecutionStrategy.sequential, options?.concurrentFinalizers)((restore) =>
2172
- isRequestBatchingEnabled
2173
- ? forEachParN(self, 1, (a, i) => restore(f(a, i)), true)
2174
- : core.forEachSequential(self, (a, i) => restore(f(a, i)))
2175
- ),
2176
- () =>
2177
- finalizersMaskInternal(ExecutionStrategy.parallel, options?.concurrentFinalizers)((restore) =>
2178
- forEachParUnbounded(self, (a, i) => restore(f(a, i)), isRequestBatchingEnabled)
2179
- ),
2180
- (n) =>
2181
- finalizersMaskInternal(ExecutionStrategy.parallelN(n), options?.concurrentFinalizers)((restore) =>
2182
- forEachParN(self, n, (a, i) => restore(f(a, i)), isRequestBatchingEnabled)
2183
- )
2184
- )
2185
- })
2186
-
2187
- // Set operation metadata in trace field for OpSupervision
2188
- ;(result as any).trace = core.makeOperationMeta("forEach", rawStack, count)
2189
-
2190
- return result
2191
- })
2192
-
2193
- /* @internal */
2194
- export const forEachParUnbounded = <A, B, E, R>(
2195
- self: Iterable<A>,
2196
- f: (a: A, i: number) => Effect.Effect<B, E, R>,
2197
- batching: boolean
2198
- ): Effect.Effect<Array<B>, E, R> =>
2199
- core.suspend(() => {
2200
- const as = RA.fromIterable(self)
2201
- const array = new Array<B>(as.length)
2202
- const fn = (a: A, i: number) => core.flatMap(f(a, i), (b) => core.sync(() => array[i] = b))
2203
- return core.zipRight(forEachConcurrentDiscard(as, fn, batching, false), core.succeed(array))
2204
- })
2205
-
2206
- /** @internal */
2207
- export const forEachConcurrentDiscard = <A, X, E, R>(
2208
- self: Iterable<A>,
2209
- f: (a: A, i: number) => Effect.Effect<X, E, R>,
2210
- batching: boolean,
2211
- processAll: boolean,
2212
- n?: number
2213
- ): Effect.Effect<void, E, R> =>
2214
- core.uninterruptibleMask((restore) =>
2215
- core.transplant((graft) =>
2216
- core.withFiberRuntime<void, E, R>((parent) => {
2217
- let todos = Array.from(self).reverse()
2218
- let target = todos.length
2219
- if (target === 0) {
2220
- return core.void
2221
- }
2222
- let counter = 0
2223
- let interrupted = false
2224
- const fibersCount = n ? Math.min(todos.length, n) : todos.length
2225
- const fibers = new Set<FiberRuntime<Exit.Exit<X, E> | Effect.Blocked<X, E>>>()
2226
- const results = new Array()
2227
- const interruptAll = () =>
2228
- fibers.forEach((fiber) => {
2229
- fiber.currentScheduler.scheduleTask(() => {
2230
- fiber.unsafeInterruptAsFork(parent.id())
2231
- }, 0)
2232
- })
2233
- const startOrder = new Array<FiberRuntime<Exit.Exit<X, E> | Effect.Blocked<X, E>>>()
2234
- const joinOrder = new Array<FiberRuntime<Exit.Exit<X, E> | Effect.Blocked<X, E>>>()
2235
- const residual = new Array<core.Blocked>()
2236
- const collectExits = () => {
2237
- const exits: Array<Exit.Exit<any, E>> = results
2238
- .filter(({ exit }) => exit._tag === "Failure")
2239
- .sort((a, b) => a.index < b.index ? -1 : a.index === b.index ? 0 : 1)
2240
- .map(({ exit }) => exit)
2241
- if (exits.length === 0) {
2242
- exits.push(core.exitVoid)
2243
- }
2244
- return exits
2245
- }
2246
- const runFiber = <A, E, R>(eff: Effect.Effect<A, E, R>, interruptImmediately = false) => {
2247
- const runnable = core.uninterruptible(graft(eff))
2248
- const fiber = unsafeForkUnstarted(
2249
- runnable,
2250
- parent,
2251
- parent.currentRuntimeFlags,
2252
- fiberScope.globalScope
2253
- )
2254
- parent.currentScheduler.scheduleTask(() => {
2255
- if (interruptImmediately) {
2256
- fiber.unsafeInterruptAsFork(parent.id())
2257
- }
2258
- fiber.resume(runnable)
2259
- }, 0)
2260
- return fiber
2261
- }
2262
- const onInterruptSignal = () => {
2263
- if (!processAll) {
2264
- target -= todos.length
2265
- todos = []
2266
- }
2267
- interrupted = true
2268
- interruptAll()
2269
- }
2270
- const stepOrExit = batching ? core.step : core.exit
2271
- const processingFiber = runFiber(
2272
- core.async<any, any, any>((resume) => {
2273
- const pushResult = <X, E>(res: Exit.Exit<X, E> | Effect.Blocked<X, E>, index: number) => {
2274
- if (res._op === "Blocked") {
2275
- residual.push(res as core.Blocked)
2276
- } else {
2277
- results.push({ index, exit: res })
2278
- if (res._op === "Failure" && !interrupted) {
2279
- onInterruptSignal()
2280
- }
2281
- }
2282
- }
2283
- const next = () => {
2284
- if (todos.length > 0) {
2285
- const a = todos.pop()!
2286
- let index = counter++
2287
- const returnNextElement = () => {
2288
- const a = todos.pop()!
2289
- index = counter++
2290
- return core.flatMap(core.yieldNow(), () =>
2291
- core.flatMap(
2292
- stepOrExit(restore(f(a, index))),
2293
- onRes
2294
- ))
2295
- }
2296
- const onRes = (
2297
- res: Exit.Exit<X, E> | Effect.Blocked<X, E>
2298
- ): Effect.Effect<Exit.Exit<X, E> | Effect.Blocked<X, E>, never, R> => {
2299
- if (todos.length > 0) {
2300
- pushResult(res, index)
2301
- if (todos.length > 0) {
2302
- return returnNextElement()
2303
- }
2304
- }
2305
- return core.succeed(res)
2306
- }
2307
- const todo = core.flatMap(
2308
- stepOrExit(restore(f(a, index))),
2309
- onRes
2310
- )
2311
- const fiber = runFiber(todo)
2312
- startOrder.push(fiber)
2313
- fibers.add(fiber)
2314
- if (interrupted) {
2315
- fiber.currentScheduler.scheduleTask(() => {
2316
- fiber.unsafeInterruptAsFork(parent.id())
2317
- }, 0)
2318
- }
2319
- fiber.addObserver((wrapped) => {
2320
- let exit: Exit.Exit<any, any> | core.Blocked
2321
- if (wrapped._op === "Failure") {
2322
- exit = wrapped
2323
- } else {
2324
- exit = wrapped.effect_instruction_i0 as any
2325
- }
2326
- joinOrder.push(fiber)
2327
- fibers.delete(fiber)
2328
- pushResult(exit, index)
2329
- if (results.length === target) {
2330
- resume(core.succeed(Option.getOrElse(
2331
- core.exitCollectAll(collectExits(), { parallel: true }),
2332
- () => core.exitVoid
2333
- )))
2334
- } else if (residual.length + results.length === target) {
2335
- const exits = collectExits()
2336
- const requests = residual.map((blocked) => blocked.effect_instruction_i0).reduce(RequestBlock_.par)
2337
- resume(core.succeed(core.blocked(
2338
- requests,
2339
- forEachConcurrentDiscard(
2340
- [
2341
- Option.getOrElse(
2342
- core.exitCollectAll(exits, { parallel: true }),
2343
- () => core.exitVoid
2344
- ),
2345
- ...residual.map((blocked) => blocked.effect_instruction_i1)
2346
- ],
2347
- (i) => i,
2348
- batching,
2349
- true,
2350
- n
2351
- )
2352
- )))
2353
- } else {
2354
- next()
2355
- }
2356
- })
2357
- }
2358
- }
2359
- for (let i = 0; i < fibersCount; i++) {
2360
- next()
2361
- }
2362
- })
2363
- )
2364
- return core.asVoid(
2365
- core.onExit(
2366
- core.flatten(restore(internalFiber.join(processingFiber))),
2367
- core.exitMatch({
2368
- onFailure: (cause) => {
2369
- onInterruptSignal()
2370
- const target = residual.length + 1
2371
- const concurrency = Math.min(typeof n === "number" ? n : residual.length, residual.length)
2372
- const toPop = Array.from(residual)
2373
- return core.async<any, any>((cb) => {
2374
- const exits: Array<Exit.Exit<any, any>> = []
2375
- let count = 0
2376
- let index = 0
2377
- const check = (index: number, hitNext: boolean) => (exit: Exit.Exit<any, any>) => {
2378
- exits[index] = exit
2379
- count++
2380
- if (count === target) {
2381
- cb(core.exitSucceed(core.exitFailCause(cause)))
2382
- }
2383
- if (toPop.length > 0 && hitNext) {
2384
- next()
2385
- }
2386
- }
2387
- const next = () => {
2388
- runFiber(toPop.pop()!, true).addObserver(check(index, true))
2389
- index++
2390
- }
2391
- processingFiber.addObserver(check(index, false))
2392
- index++
2393
- for (let i = 0; i < concurrency; i++) {
2394
- next()
2395
- }
2396
- }) as any
2397
- },
2398
- onSuccess: () => core.forEachSequential(joinOrder, (f) => f.inheritAll)
2399
- })
2400
- )
2401
- )
2402
- })
2403
- )
2404
- )
2405
-
2406
- /* @internal */
2407
- export const forEachParN = <A, B, E, R>(
2408
- self: Iterable<A>,
2409
- n: number,
2410
- f: (a: A, i: number) => Effect.Effect<B, E, R>,
2411
- batching: boolean
2412
- ): Effect.Effect<Array<B>, E, R> =>
2413
- core.suspend(() => {
2414
- const as = RA.fromIterable(self)
2415
- const array = new Array<B>(as.length)
2416
- const fn = (a: A, i: number) => core.map(f(a, i), (b) => array[i] = b)
2417
- return core.zipRight(forEachConcurrentDiscard(as, fn, batching, false, n), core.succeed(array))
2418
- })
2419
-
2420
- /* @internal */
2421
- export const fork = <A, E, R>(self: Effect.Effect<A, E, R>): Effect.Effect<Fiber.RuntimeFiber<A, E>, never, R> => {
2422
- // Capture stack trace immediately while user code is on stack
2423
- // Creating Error object is cheap; parsing is delayed until we know capture is enabled
2424
- const rawStack = new Error().stack ?? ""
2425
-
2426
- const result: Effect.Effect<Fiber.RuntimeFiber<A, E>, never, R> = core.withFiberRuntime((state, status) => {
2427
- // Check if capture is enabled, then parse the pre-captured stack if needed
2428
- const capturedLocation = state.getFiberRef(core.currentCaptureStackTraces) && rawStack
2429
- ? tracer.parseSourceLocationFromStack(rawStack)
2430
- : undefined
2431
-
2432
- const fiber = unsafeForkWithLocation(self, state, status.runtimeFlags, null, capturedLocation)
2433
- return core.succeed(fiber)
2434
- })
2435
-
2436
- // Set operation metadata in trace field for OpSupervision
2437
- ;(result as any).trace = core.makeOperationMeta("fork", rawStack, 1)
2438
-
2439
- return result
2440
- }
2441
-
2442
- /* @internal */
2443
- export const forkDaemon = <A, E, R>(self: Effect.Effect<A, E, R>): Effect.Effect<Fiber.RuntimeFiber<A, E>, never, R> => {
2444
- const rawStack = new Error().stack ?? ""
2445
- const result = forkWithScopeOverride(self, fiberScope.globalScope)
2446
- ;(result as any).trace = core.makeOperationMeta("forkDaemon", rawStack, 1)
2447
- return result
2448
- }
2449
-
2450
- /* @internal */
2451
- export const forkWithErrorHandler = dual<
2452
- <E, X>(
2453
- handler: (e: E) => Effect.Effect<X>
2454
- ) => <A, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<Fiber.RuntimeFiber<A, E>, never, R>,
2455
- <A, E, R, X>(
2456
- self: Effect.Effect<A, E, R>,
2457
- handler: (e: E) => Effect.Effect<X>
2458
- ) => Effect.Effect<Fiber.RuntimeFiber<A, E>, never, R>
2459
- >(2, (self, handler) =>
2460
- fork(core.onError(self, (cause) => {
2461
- const either = internalCause.failureOrCause(cause)
2462
- switch (either._tag) {
2463
- case "Left":
2464
- return handler(either.left)
2465
- case "Right":
2466
- return core.failCause(either.right)
2467
- }
2468
- })))
2469
-
2470
- /** @internal */
2471
- export const unsafeFork = <A, E, R, E2, B>(
2472
- effect: Effect.Effect<A, E, R>,
2473
- parentFiber: FiberRuntime<B, E2>,
2474
- parentRuntimeFlags: RuntimeFlags.RuntimeFlags,
2475
- overrideScope: fiberScope.FiberScope | null = null
2476
- ): FiberRuntime<A, E> => {
2477
- const childFiber = unsafeMakeChildFiber(effect, parentFiber, parentRuntimeFlags, overrideScope)
2478
- childFiber.resume(effect)
2479
- return childFiber
2480
- }
2481
-
2482
- /** @internal */
2483
- export const unsafeForkWithLocation = <A, E, R, E2, B>(
2484
- effect: Effect.Effect<A, E, R>,
2485
- parentFiber: FiberRuntime<B, E2>,
2486
- parentRuntimeFlags: RuntimeFlags.RuntimeFlags,
2487
- overrideScope: fiberScope.FiberScope | null = null,
2488
- capturedLocation: tracer.SourceLocation | undefined = undefined
2489
- ): FiberRuntime<A, E> => {
2490
- const childFiber = unsafeMakeChildFiberWithLocation(effect, parentFiber, parentRuntimeFlags, overrideScope, capturedLocation)
2491
- childFiber.resume(effect)
2492
- return childFiber
2493
- }
2494
-
2495
- /** @internal */
2496
- export const unsafeForkUnstarted = <A, E, R, E2, B>(
2497
- effect: Effect.Effect<A, E, R>,
2498
- parentFiber: FiberRuntime<B, E2>,
2499
- parentRuntimeFlags: RuntimeFlags.RuntimeFlags,
2500
- overrideScope: fiberScope.FiberScope | null = null
2501
- ): FiberRuntime<A, E> => {
2502
- const childFiber = unsafeMakeChildFiber(effect, parentFiber, parentRuntimeFlags, overrideScope)
2503
- return childFiber
2504
- }
2505
-
2506
- /** @internal */
2507
- export const unsafeMakeChildFiber = <A, E, R, E2, B>(
2508
- effect: Effect.Effect<A, E, R>,
2509
- parentFiber: FiberRuntime<B, E2>,
2510
- parentRuntimeFlags: RuntimeFlags.RuntimeFlags,
2511
- overrideScope: fiberScope.FiberScope | null = null
2512
- ): FiberRuntime<A, E> => {
2513
- return unsafeMakeChildFiberWithLocation(effect, parentFiber, parentRuntimeFlags, overrideScope, undefined)
2514
- }
2515
-
2516
- /** @internal */
2517
- export const unsafeMakeChildFiberWithLocation = <A, E, R, E2, B>(
2518
- effect: Effect.Effect<A, E, R>,
2519
- parentFiber: FiberRuntime<B, E2>,
2520
- parentRuntimeFlags: RuntimeFlags.RuntimeFlags,
2521
- overrideScope: fiberScope.FiberScope | null = null,
2522
- capturedLocation: tracer.SourceLocation | undefined = undefined
2523
- ): FiberRuntime<A, E> => {
2524
- const childId = FiberId.unsafeMake()
2525
- const parentFiberRefs = parentFiber.getFiberRefs()
2526
- const childFiberRefs = fiberRefs.forkAs(parentFiberRefs, childId)
2527
- const childFiber = new FiberRuntime<A, E>(childId, childFiberRefs, parentRuntimeFlags)
2528
-
2529
- // Set pre-captured source location if enabled
2530
- if (capturedLocation && parentFiber.getFiberRef(core.currentCaptureStackTraces)) {
2531
- childFiber.setFiberRef(core.currentSourceLocation, capturedLocation)
2532
- }
2533
-
2534
- const childContext = fiberRefs.getOrDefault(
2535
- childFiberRefs,
2536
- core.currentContext as unknown as FiberRef.FiberRef<Context.Context<R>>
2537
- )
2538
- const supervisor = childFiber.currentSupervisor
2539
-
2540
- supervisor.onStart(
2541
- childContext,
2542
- effect,
2543
- Option.some(parentFiber),
2544
- childFiber
2545
- )
2546
-
2547
- childFiber.addObserver((exit) => supervisor.onEnd(exit, childFiber))
2548
-
2549
- const parentScope = overrideScope !== null ? overrideScope : pipe(
2550
- parentFiber.getFiberRef(core.currentForkScopeOverride),
2551
- Option.getOrElse(() => parentFiber.scope())
2552
- )
2553
-
2554
- parentScope.add(parentRuntimeFlags, childFiber)
2555
-
2556
- return childFiber
2557
- }
2558
-
2559
- /* @internal */
2560
- const forkWithScopeOverride = <A, E, R>(
2561
- self: Effect.Effect<A, E, R>,
2562
- scopeOverride: fiberScope.FiberScope
2563
- ): Effect.Effect<Fiber.RuntimeFiber<A, E>, never, R> =>
2564
- core.withFiberRuntime((parentFiber, parentStatus) =>
2565
- core.succeed(unsafeFork(self, parentFiber, parentStatus.runtimeFlags, scopeOverride))
2566
- )
2567
-
2568
- /* @internal */
2569
- export const mergeAll = dual<
2570
- <Z, Eff extends Effect.Effect<any, any, any>>(
2571
- zero: Z,
2572
- f: (z: Z, a: Effect.Effect.Success<Eff>, i: number) => Z,
2573
- options?: {
2574
- readonly concurrency?: Concurrency | undefined
2575
- readonly batching?: boolean | "inherit" | undefined
2576
- readonly concurrentFinalizers?: boolean | undefined
2577
- }
2578
- ) => (elements: Iterable<Eff>) => Effect.Effect<Z, Effect.Effect.Error<Eff>, Effect.Effect.Context<Eff>>,
2579
- <Eff extends Effect.Effect<any, any, any>, Z>(
2580
- elements: Iterable<Eff>,
2581
- zero: Z,
2582
- f: (z: Z, a: Effect.Effect.Success<Eff>, i: number) => Z,
2583
- options?: {
2584
- readonly concurrency?: Concurrency | undefined
2585
- readonly batching?: boolean | "inherit" | undefined
2586
- readonly concurrentFinalizers?: boolean | undefined
2587
- }
2588
- ) => Effect.Effect<Z, Effect.Effect.Error<Eff>, Effect.Effect.Context<Eff>>
2589
- >(
2590
- (args) => Predicate.isFunction(args[2]),
2591
- <A, E, R, Z>(elements: Iterable<Effect.Effect<A, E, R>>, zero: Z, f: (z: Z, a: A, i: number) => Z, options?: {
2592
- readonly concurrency?: Concurrency | undefined
2593
- readonly batching?: boolean | "inherit" | undefined
2594
- readonly concurrentFinalizers?: boolean | undefined
2595
- }) =>
2596
- concurrency.matchSimple(
2597
- options?.concurrency,
2598
- () =>
2599
- RA.fromIterable(elements).reduce(
2600
- (acc, a, i) => core.zipWith(acc, a, (acc, a) => f(acc, a, i)),
2601
- core.succeed(zero) as Effect.Effect<Z, E, R>
2602
- ),
2603
- () =>
2604
- core.flatMap(Ref.make(zero), (acc) =>
2605
- core.flatMap(
2606
- forEach(
2607
- elements,
2608
- (effect, i) => core.flatMap(effect, (a) => Ref.update(acc, (b) => f(b, a, i))),
2609
- options
2610
- ),
2611
- () => Ref.get(acc)
2612
- ))
2613
- )
2614
- )
2615
-
2616
- /* @internal */
2617
- export const partition = dual<
2618
- <A, B, E, R>(
2619
- f: (a: A, i: number) => Effect.Effect<B, E, R>,
2620
- options?: {
2621
- readonly concurrency?: Concurrency | undefined
2622
- readonly batching?: boolean | "inherit" | undefined
2623
- readonly concurrentFinalizers?: boolean | undefined
2624
- }
2625
- ) => (elements: Iterable<A>) => Effect.Effect<[excluded: Array<E>, satisfying: Array<B>], never, R>,
2626
- <A, B, E, R>(
2627
- elements: Iterable<A>,
2628
- f: (a: A, i: number) => Effect.Effect<B, E, R>,
2629
- options?: {
2630
- readonly concurrency?: Concurrency | undefined
2631
- readonly batching?: boolean | "inherit" | undefined
2632
- readonly concurrentFinalizers?: boolean | undefined
2633
- }
2634
- ) => Effect.Effect<[excluded: Array<E>, satisfying: Array<B>], never, R>
2635
- >((args) => Predicate.isIterable(args[0]), (elements, f, options) =>
2636
- pipe(
2637
- forEach(elements, (a, i) => core.either(f(a, i)), options),
2638
- core.map((chunk) => core.partitionMap(chunk, identity))
2639
- ))
2640
-
2641
- /* @internal */
2642
- export const validateAll = dual<
2643
- {
2644
- <A, B, E, R>(
2645
- f: (a: A, i: number) => Effect.Effect<B, E, R>,
2646
- options?: {
2647
- readonly concurrency?: Concurrency | undefined
2648
- readonly batching?: boolean | "inherit" | undefined
2649
- readonly discard?: false | undefined
2650
- readonly concurrentFinalizers?: boolean | undefined
2651
- }
2652
- ): (elements: Iterable<A>) => Effect.Effect<Array<B>, RA.NonEmptyArray<E>, R>
2653
- <A, B, E, R>(
2654
- f: (a: A, i: number) => Effect.Effect<B, E, R>,
2655
- options: {
2656
- readonly concurrency?: Concurrency | undefined
2657
- readonly batching?: boolean | "inherit" | undefined
2658
- readonly discard: true
2659
- readonly concurrentFinalizers?: boolean | undefined
2660
- }
2661
- ): (elements: Iterable<A>) => Effect.Effect<void, RA.NonEmptyArray<E>, R>
2662
- },
2663
- {
2664
- <A, B, E, R>(
2665
- elements: Iterable<A>,
2666
- f: (a: A, i: number) => Effect.Effect<B, E, R>,
2667
- options?: {
2668
- readonly concurrency?: Concurrency | undefined
2669
- readonly batching?: boolean | "inherit" | undefined
2670
- readonly discard?: false | undefined
2671
- readonly concurrentFinalizers?: boolean | undefined
2672
- }
2673
- ): Effect.Effect<Array<B>, RA.NonEmptyArray<E>, R>
2674
- <A, B, E, R>(
2675
- elements: Iterable<A>,
2676
- f: (a: A, i: number) => Effect.Effect<B, E, R>,
2677
- options: {
2678
- readonly concurrency?: Concurrency | undefined
2679
- readonly batching?: boolean | "inherit" | undefined
2680
- readonly discard: true
2681
- readonly concurrentFinalizers?: boolean | undefined
2682
- }
2683
- ): Effect.Effect<void, RA.NonEmptyArray<E>, R>
2684
- }
2685
- >(
2686
- (args) => Predicate.isIterable(args[0]),
2687
- <A, B, E, R>(elements: Iterable<A>, f: (a: A, i: number) => Effect.Effect<B, E, R>, options?: {
2688
- readonly concurrency?: Concurrency | undefined
2689
- readonly batching?: boolean | "inherit" | undefined
2690
- readonly discard?: boolean | undefined
2691
- readonly concurrentFinalizers?: boolean | undefined
2692
- }): Effect.Effect<any, RA.NonEmptyArray<E>, R> =>
2693
- core.flatMap(
2694
- partition(elements, f, {
2695
- concurrency: options?.concurrency,
2696
- batching: options?.batching,
2697
- concurrentFinalizers: options?.concurrentFinalizers
2698
- }),
2699
- ([es, bs]) =>
2700
- RA.isNonEmptyArray(es)
2701
- ? core.fail(es)
2702
- : options?.discard
2703
- ? core.void
2704
- : core.succeed(bs)
2705
- )
2706
- )
2707
-
2708
- /* @internal */
2709
- export const raceAll: <Eff extends Effect.Effect<any, any, any>>(
2710
- all: Iterable<Eff>
2711
- ) => Effect.Effect<Effect.Effect.Success<Eff>, Effect.Effect.Error<Eff>, Effect.Effect.Context<Eff>> = <
2712
- A,
2713
- E,
2714
- R
2715
- >(all: Iterable<Effect.Effect<A, E, R>>): Effect.Effect<A, E, R> =>
2716
- core.withFiberRuntime((state, status) =>
2717
- core.async<A, E, R>((resume) => {
2718
- const fibers = new Set<FiberRuntime<A, E>>()
2719
- let winner: FiberRuntime<A, E> | undefined
2720
- let failures: Cause.Cause<E> = internalCause.empty
2721
- const interruptAll = () => {
2722
- for (const fiber of fibers) {
2723
- fiber.unsafeInterruptAsFork(state.id())
2724
- }
2725
- }
2726
- let latch = false
2727
- let empty = true
2728
- for (const self of all) {
2729
- empty = false
2730
- const fiber = unsafeFork(
2731
- core.interruptible(self),
2732
- state,
2733
- status.runtimeFlags
2734
- )
2735
- fibers.add(fiber)
2736
- fiber.addObserver((exit) => {
2737
- fibers.delete(fiber)
2738
- if (!winner) {
2739
- if (exit._tag === "Success") {
2740
- latch = true
2741
- winner = fiber
2742
- failures = internalCause.empty
2743
- interruptAll()
2744
- } else {
2745
- failures = internalCause.parallel(exit.cause, failures)
2746
- }
2747
- }
2748
- if (latch && fibers.size === 0) {
2749
- resume(
2750
- winner ? core.zipRight(internalFiber.inheritAll(winner), winner.unsafePoll()!) : core.failCause(failures)
2751
- )
2752
- }
2753
- })
2754
- if (winner) break
2755
- }
2756
- if (empty) {
2757
- return resume(core.dieSync(() => new core.IllegalArgumentException(`Received an empty collection of effects`)))
2758
- }
2759
- latch = true
2760
- return internalFiber.interruptAllAs(fibers, state.id())
2761
- })
2762
- )
2763
-
2764
- /* @internal */
2765
- export const reduceEffect = dual<
2766
- <Z, E, R, Eff extends Effect.Effect<any, any, any>>(
2767
- zero: Effect.Effect<Z, E, R>,
2768
- f: (z: NoInfer<Z>, a: Effect.Effect.Success<Eff>, i: number) => Z,
2769
- options?: {
2770
- readonly concurrency?: Concurrency | undefined
2771
- readonly batching?: boolean | "inherit" | undefined
2772
- readonly concurrentFinalizers?: boolean | undefined
2773
- }
2774
- ) => (elements: Iterable<Eff>) => Effect.Effect<Z, E | Effect.Effect.Error<Eff>, R | Effect.Effect.Context<Eff>>,
2775
- <Eff extends Effect.Effect<any, any, any>, Z, E, R>(
2776
- elements: Iterable<Eff>,
2777
- zero: Effect.Effect<Z, E, R>,
2778
- f: (z: NoInfer<Z>, a: Effect.Effect.Success<Eff>, i: number) => Z,
2779
- options?: {
2780
- readonly concurrency?: Concurrency | undefined
2781
- readonly batching?: boolean | "inherit" | undefined
2782
- readonly concurrentFinalizers?: boolean | undefined
2783
- }
2784
- ) => Effect.Effect<Z, E | Effect.Effect.Error<Eff>, R | Effect.Effect.Context<Eff>>
2785
- >((args) => Predicate.isIterable(args[0]) && !core.isEffect(args[0]), <A, E, R, Z>(
2786
- elements: Iterable<Effect.Effect<A, E, R>>,
2787
- zero: Effect.Effect<Z, E, R>,
2788
- f: (z: NoInfer<Z>, a: NoInfer<A>, i: number) => Z,
2789
- options?: {
2790
- readonly concurrency?: Concurrency | undefined
2791
- readonly batching?: boolean | "inherit" | undefined
2792
- readonly concurrentFinalizers?: boolean | undefined
2793
- }
2794
- ) =>
2795
- concurrency.matchSimple(
2796
- options?.concurrency,
2797
- () => RA.fromIterable(elements).reduce((acc, a, i) => core.zipWith(acc, a, (acc, a) => f(acc, a, i)), zero),
2798
- () =>
2799
- core.suspend(() =>
2800
- pipe(
2801
- mergeAll(
2802
- [zero, ...elements],
2803
- Option.none<Z>(),
2804
- (acc, elem, i) => {
2805
- switch (acc._tag) {
2806
- case "None": {
2807
- return Option.some(elem as Z)
2808
- }
2809
- case "Some": {
2810
- return Option.some(f(acc.value, elem as A, i))
2811
- }
2812
- }
2813
- },
2814
- options
2815
- ),
2816
- core.map((option) => {
2817
- switch (option._tag) {
2818
- case "None": {
2819
- throw new Error(
2820
- "BUG: Effect.reduceEffect - please report an issue at https://github.com/Effect-TS/effect/issues"
2821
- )
2822
- }
2823
- case "Some": {
2824
- return option.value
2825
- }
2826
- }
2827
- })
2828
- )
2829
- )
2830
- ))
2831
-
2832
- /* @internal */
2833
- export const parallelFinalizers = <A, E, R>(self: Effect.Effect<A, E, R>): Effect.Effect<A, E, R> =>
2834
- core.contextWithEffect((context) =>
2835
- Option.match(Context.getOption(context, scopeTag), {
2836
- onNone: () => self,
2837
- onSome: (scope) => {
2838
- switch (scope.strategy._tag) {
2839
- case "Parallel":
2840
- return self
2841
- case "Sequential":
2842
- case "ParallelN":
2843
- return core.flatMap(
2844
- core.scopeFork(scope, ExecutionStrategy.parallel),
2845
- (inner) => scopeExtend(self, inner)
2846
- )
2847
- }
2848
- }
2849
- })
2850
- )
2851
-
2852
- /* @internal */
2853
- export const parallelNFinalizers =
2854
- (parallelism: number) => <A, E, R>(self: Effect.Effect<A, E, R>): Effect.Effect<A, E, R> =>
2855
- core.contextWithEffect((context) =>
2856
- Option.match(Context.getOption(context, scopeTag), {
2857
- onNone: () => self,
2858
- onSome: (scope) => {
2859
- if (scope.strategy._tag === "ParallelN" && scope.strategy.parallelism === parallelism) {
2860
- return self
2861
- }
2862
- return core.flatMap(
2863
- core.scopeFork(scope, ExecutionStrategy.parallelN(parallelism)),
2864
- (inner) => scopeExtend(self, inner)
2865
- )
2866
- }
2867
- })
2868
- )
2869
-
2870
- /* @internal */
2871
- export const finalizersMask = (strategy: ExecutionStrategy.ExecutionStrategy) =>
2872
- <A, E, R>(
2873
- self: (
2874
- restore: <A1, E1, R1>(self: Effect.Effect<A1, E1, R1>) => Effect.Effect<A1, E1, R1>
2875
- ) => Effect.Effect<A, E, R>
2876
- ): Effect.Effect<A, E, R> => finalizersMaskInternal(strategy, true)(self)
2877
-
2878
- /* @internal */
2879
- export const finalizersMaskInternal =
2880
- (strategy: ExecutionStrategy.ExecutionStrategy, concurrentFinalizers?: boolean | undefined) =>
2881
- <A, E, R>(
2882
- self: (
2883
- restore: <A1, E1, R1>(self: Effect.Effect<A1, E1, R1>) => Effect.Effect<A1, E1, R1>
2884
- ) => Effect.Effect<A, E, R>
2885
- ): Effect.Effect<A, E, R> =>
2886
- core.contextWithEffect((context) =>
2887
- Option.match(Context.getOption(context, scopeTag), {
2888
- onNone: () => self(identity),
2889
- onSome: (scope) => {
2890
- if (concurrentFinalizers === true) {
2891
- const patch = strategy._tag === "Parallel"
2892
- ? parallelFinalizers
2893
- : strategy._tag === "Sequential"
2894
- ? sequentialFinalizers
2895
- : parallelNFinalizers(strategy.parallelism)
2896
- switch (scope.strategy._tag) {
2897
- case "Parallel":
2898
- return patch(self(parallelFinalizers))
2899
- case "Sequential":
2900
- return patch(self(sequentialFinalizers))
2901
- case "ParallelN":
2902
- return patch(self(parallelNFinalizers(scope.strategy.parallelism)))
2903
- }
2904
- } else {
2905
- return self(identity)
2906
- }
2907
- }
2908
- })
2909
- )
2910
-
2911
- /* @internal */
2912
- export const scopeWith = <A, E, R>(
2913
- f: (scope: Scope.Scope) => Effect.Effect<A, E, R>
2914
- ): Effect.Effect<A, E, R | Scope.Scope> => core.flatMap(scopeTag, f)
2915
-
2916
- /** @internal */
2917
- export const scopedWith = <A, E, R>(
2918
- f: (scope: Scope.Scope) => Effect.Effect<A, E, R>
2919
- ): Effect.Effect<A, E, R> => core.flatMap(scopeMake(), (scope) => core.onExit(f(scope), (exit) => scope.close(exit)))
2920
-
2921
- /* @internal */
2922
- export const scopedEffect = <A, E, R>(effect: Effect.Effect<A, E, R>): Effect.Effect<A, E, Exclude<R, Scope.Scope>> =>
2923
- core.flatMap(scopeMake(), (scope) => scopeUse(effect, scope))
2924
-
2925
- /* @internal */
2926
- export const sequentialFinalizers = <A, E, R>(self: Effect.Effect<A, E, R>): Effect.Effect<A, E, R> =>
2927
- core.contextWithEffect((context) =>
2928
- Option.match(Context.getOption(context, scopeTag), {
2929
- onNone: () => self,
2930
- onSome: (scope) => {
2931
- switch (scope.strategy._tag) {
2932
- case "Sequential":
2933
- return self
2934
- case "Parallel":
2935
- case "ParallelN":
2936
- return core.flatMap(
2937
- core.scopeFork(scope, ExecutionStrategy.sequential),
2938
- (inner) => scopeExtend(self, inner)
2939
- )
2940
- }
2941
- }
2942
- })
2943
- )
2944
-
2945
- /* @internal */
2946
- export const tagMetricsScoped = (key: string, value: string): Effect.Effect<void, never, Scope.Scope> =>
2947
- labelMetricsScoped([metricLabel.make(key, value)])
2948
-
2949
- /* @internal */
2950
- export const labelMetricsScoped = (
2951
- labels: Iterable<MetricLabel.MetricLabel>
2952
- ): Effect.Effect<void, never, Scope.Scope> =>
2953
- fiberRefLocallyScopedWith(core.currentMetricLabels, (old) => RA.union(old, labels))
2954
-
2955
- /* @internal */
2956
- export const using = dual<
2957
- <A, A2, E2, R2>(
2958
- use: (a: A) => Effect.Effect<A2, E2, R2>
2959
- ) => <E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<A2, E | E2, Exclude<R, Scope.Scope> | R2>,
2960
- <A, E, R, A2, E2, R2>(
2961
- self: Effect.Effect<A, E, R>,
2962
- use: (a: A) => Effect.Effect<A2, E2, R2>
2963
- ) => Effect.Effect<A2, E | E2, Exclude<R, Scope.Scope> | R2>
2964
- >(2, (self, use) => scopedWith((scope) => core.flatMap(scopeExtend(self, scope), use)))
2965
-
2966
- /** @internal */
2967
- export const validate = dual<
2968
- <B, E1, R1>(
2969
- that: Effect.Effect<B, E1, R1>,
2970
- options?: {
2971
- readonly concurrent?: boolean | undefined
2972
- readonly batching?: boolean | "inherit" | undefined
2973
- readonly concurrentFinalizers?: boolean | undefined
2974
- }
2975
- ) => <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<[A, B], E | E1, R | R1>,
2976
- <A, E, R, B, E1, R1>(
2977
- self: Effect.Effect<A, E, R>,
2978
- that: Effect.Effect<B, E1, R1>,
2979
- options?: {
2980
- readonly concurrent?: boolean | undefined
2981
- readonly batching?: boolean | "inherit" | undefined
2982
- readonly concurrentFinalizers?: boolean | undefined
2983
- }
2984
- ) => Effect.Effect<[A, B], E | E1, R | R1>
2985
- >(
2986
- (args) => core.isEffect(args[1]),
2987
- (self, that, options) => validateWith(self, that, (a, b) => [a, b], options)
2988
- )
2989
-
2990
- /** @internal */
2991
- export const validateWith = dual<
2992
- <B, E1, R1, A, C>(
2993
- that: Effect.Effect<B, E1, R1>,
2994
- f: (a: A, b: B) => C,
2995
- options?: {
2996
- readonly concurrent?: boolean | undefined
2997
- readonly batching?: boolean | "inherit" | undefined
2998
- readonly concurrentFinalizers?: boolean | undefined
2999
- }
3000
- ) => <E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<C, E | E1, R | R1>,
3001
- <A, E, R, B, E1, R1, C>(
3002
- self: Effect.Effect<A, E, R>,
3003
- that: Effect.Effect<B, E1, R1>,
3004
- f: (a: A, b: B) => C,
3005
- options?: {
3006
- readonly concurrent?: boolean | undefined
3007
- readonly batching?: boolean | "inherit" | undefined
3008
- readonly concurrentFinalizers?: boolean | undefined
3009
- }
3010
- ) => Effect.Effect<C, E | E1, R | R1>
3011
- >((args) => core.isEffect(args[1]), (self, that, f, options) =>
3012
- core.flatten(zipWithOptions(
3013
- core.exit(self),
3014
- core.exit(that),
3015
- (ea, eb) =>
3016
- core.exitZipWith(ea, eb, {
3017
- onSuccess: f,
3018
- onFailure: (ca, cb) => options?.concurrent ? internalCause.parallel(ca, cb) : internalCause.sequential(ca, cb)
3019
- }),
3020
- options
3021
- )))
3022
-
3023
- /* @internal */
3024
- export const validateAllPar = dual<
3025
- <A, B, E, R>(
3026
- f: (a: A) => Effect.Effect<B, E, R>
3027
- ) => (elements: Iterable<A>) => Effect.Effect<Array<B>, Array<E>, R>,
3028
- <A, B, E, R>(
3029
- elements: Iterable<A>,
3030
- f: (a: A) => Effect.Effect<B, E, R>
3031
- ) => Effect.Effect<Array<B>, Array<E>, R>
3032
- >(2, (elements, f) =>
3033
- core.flatMap(
3034
- partition(elements, f),
3035
- ([es, bs]) =>
3036
- es.length === 0
3037
- ? core.succeed(bs)
3038
- : core.fail(es)
3039
- ))
3040
-
3041
- /* @internal */
3042
- export const validateAllParDiscard = dual<
3043
- <A, B, E, R>(
3044
- f: (a: A) => Effect.Effect<B, E, R>
3045
- ) => (elements: Iterable<A>) => Effect.Effect<void, Array<E>, R>,
3046
- <A, B, E, R>(elements: Iterable<A>, f: (a: A) => Effect.Effect<B, E, R>) => Effect.Effect<void, Array<E>, R>
3047
- >(2, (elements, f) =>
3048
- core.flatMap(
3049
- partition(elements, f),
3050
- ([es, _]) =>
3051
- es.length === 0
3052
- ? core.void
3053
- : core.fail(es)
3054
- ))
3055
-
3056
- /* @internal */
3057
- export const validateFirst = dual<
3058
- <A, B, E, R>(f: (a: A, i: number) => Effect.Effect<B, E, R>, options?: {
3059
- readonly concurrency?: Concurrency | undefined
3060
- readonly batching?: boolean | "inherit" | undefined
3061
- readonly concurrentFinalizers?: boolean | undefined
3062
- }) => (elements: Iterable<A>) => Effect.Effect<B, Array<E>, R>,
3063
- <A, B, E, R>(elements: Iterable<A>, f: (a: A, i: number) => Effect.Effect<B, E, R>, options?: {
3064
- readonly concurrency?: Concurrency | undefined
3065
- readonly batching?: boolean | "inherit" | undefined
3066
- readonly concurrentFinalizers?: boolean | undefined
3067
- }) => Effect.Effect<B, Array<E>, R>
3068
- >(
3069
- (args) => Predicate.isIterable(args[0]),
3070
- (elements, f, options) => core.flip(forEach(elements, (a, i) => core.flip(f(a, i)), options))
3071
- )
3072
-
3073
- /* @internal */
3074
- export const withClockScoped = <C extends Clock.Clock>(c: C) =>
3075
- fiberRefLocallyScopedWith(defaultServices.currentServices, Context.add(clock.clockTag, c))
3076
-
3077
- /* @internal */
3078
- export const withRandomScoped = <A extends Random.Random>(value: A) =>
3079
- fiberRefLocallyScopedWith(defaultServices.currentServices, Context.add(randomTag, value))
3080
-
3081
- /* @internal */
3082
- export const withConfigProviderScoped = (provider: ConfigProvider) =>
3083
- fiberRefLocallyScopedWith(defaultServices.currentServices, Context.add(configProviderTag, provider))
3084
-
3085
- /* @internal */
3086
- export const withEarlyRelease = <A, E, R>(
3087
- self: Effect.Effect<A, E, R>
3088
- ): Effect.Effect<[Effect.Effect<void>, A], E, R | Scope.Scope> =>
3089
- scopeWith((parent) =>
3090
- core.flatMap(core.scopeFork(parent, executionStrategy.sequential), (child) =>
3091
- pipe(
3092
- self,
3093
- scopeExtend(child),
3094
- core.map((value) => [
3095
- core.fiberIdWith((fiberId) => core.scopeClose(child, core.exitInterrupt(fiberId))),
3096
- value
3097
- ])
3098
- ))
3099
- )
3100
-
3101
- /** @internal */
3102
- export const zipOptions = dual<
3103
- <A2, E2, R2>(
3104
- that: Effect.Effect<A2, E2, R2>,
3105
- options?: {
3106
- readonly concurrent?: boolean | undefined
3107
- readonly batching?: boolean | "inherit" | undefined
3108
- readonly concurrentFinalizers?: boolean | undefined
3109
- }
3110
- ) => <A, E, R>(
3111
- self: Effect.Effect<A, E, R>
3112
- ) => Effect.Effect<[A, A2], E | E2, R | R2>,
3113
- <A, E, R, A2, E2, R2>(
3114
- self: Effect.Effect<A, E, R>,
3115
- that: Effect.Effect<A2, E2, R2>,
3116
- options?: {
3117
- readonly concurrent?: boolean | undefined
3118
- readonly batching?: boolean | "inherit" | undefined
3119
- readonly concurrentFinalizers?: boolean | undefined
3120
- }
3121
- ) => Effect.Effect<[A, A2], E | E2, R | R2>
3122
- >((args) => core.isEffect(args[1]), (
3123
- self,
3124
- that,
3125
- options
3126
- ) => zipWithOptions(self, that, (a, b) => [a, b], options))
3127
-
3128
- /** @internal */
3129
- export const zipLeftOptions = dual<
3130
- <A2, E2, R2>(
3131
- that: Effect.Effect<A2, E2, R2>,
3132
- options?: {
3133
- readonly concurrent?: boolean | undefined
3134
- readonly batching?: boolean | "inherit" | undefined
3135
- readonly concurrentFinalizers?: boolean | undefined
3136
- }
3137
- ) => <A, E, R>(
3138
- self: Effect.Effect<A, E, R>
3139
- ) => Effect.Effect<A, E | E2, R | R2>,
3140
- <A, E, R, A2, E2, R2>(
3141
- self: Effect.Effect<A, E, R>,
3142
- that: Effect.Effect<A2, E2, R2>,
3143
- options?: {
3144
- readonly concurrent?: boolean | undefined
3145
- readonly batching?: boolean | "inherit" | undefined
3146
- readonly concurrentFinalizers?: boolean | undefined
3147
- }
3148
- ) => Effect.Effect<A, E | E2, R | R2>
3149
- >(
3150
- (args) => core.isEffect(args[1]),
3151
- (self, that, options) => {
3152
- if (options?.concurrent !== true && (options?.batching === undefined || options.batching === false)) {
3153
- return core.zipLeft(self, that)
3154
- }
3155
- return zipWithOptions(self, that, (a, _) => a, options)
3156
- }
3157
- )
3158
-
3159
- /** @internal */
3160
- export const zipRightOptions: {
3161
- <A2, E2, R2>(
3162
- that: Effect.Effect<A2, E2, R2>,
3163
- options?: {
3164
- readonly concurrent?: boolean | undefined
3165
- readonly batching?: boolean | "inherit" | undefined
3166
- readonly concurrentFinalizers?: boolean | undefined
3167
- }
3168
- ): <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<A2, E2 | E, R2 | R>
3169
- <A, E, R, A2, E2, R2>(
3170
- self: Effect.Effect<A, E, R>,
3171
- that: Effect.Effect<A2, E2, R2>,
3172
- options?: {
3173
- readonly concurrent?: boolean | undefined
3174
- readonly batching?: boolean | "inherit" | undefined
3175
- readonly concurrentFinalizers?: boolean | undefined
3176
- }
3177
- ): Effect.Effect<A2, E2 | E, R2 | R>
3178
- } = dual((args) => core.isEffect(args[1]), <A, E, R, A2, E2, R2>(
3179
- self: Effect.Effect<A, E, R>,
3180
- that: Effect.Effect<A2, E2, R2>,
3181
- options?: {
3182
- readonly concurrent?: boolean | undefined
3183
- readonly batching?: boolean | "inherit" | undefined
3184
- readonly concurrentFinalizers?: boolean | undefined
3185
- }
3186
- ): Effect.Effect<A2, E2 | E, R2 | R> => {
3187
- if (options?.concurrent !== true && (options?.batching === undefined || options.batching === false)) {
3188
- return core.zipRight(self, that)
3189
- }
3190
- return zipWithOptions(self, that, (_, b) => b, options)
3191
- })
3192
-
3193
- /** @internal */
3194
- export const zipWithOptions: {
3195
- <A2, E2, R2, A, B>(
3196
- that: Effect.Effect<A2, E2, R2>,
3197
- f: (a: A, b: A2) => B,
3198
- options?: {
3199
- readonly concurrent?: boolean | undefined
3200
- readonly batching?: boolean | "inherit" | undefined
3201
- readonly concurrentFinalizers?: boolean | undefined
3202
- }
3203
- ): <E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<B, E2 | E, R2 | R>
3204
- <A, E, R, A2, E2, R2, B>(
3205
- self: Effect.Effect<A, E, R>,
3206
- that: Effect.Effect<A2, E2, R2>,
3207
- f: (a: A, b: A2) => B,
3208
- options?: {
3209
- readonly concurrent?: boolean | undefined
3210
- readonly batching?: boolean | "inherit" | undefined
3211
- readonly concurrentFinalizers?: boolean | undefined
3212
- }
3213
- ): Effect.Effect<B, E2 | E, R2 | R>
3214
- } = dual((args) => core.isEffect(args[1]), <A, E, R, A2, E2, R2, B>(
3215
- self: Effect.Effect<A, E, R>,
3216
- that: Effect.Effect<A2, E2, R2>,
3217
- f: (a: A, b: A2) => B,
3218
- options?: {
3219
- readonly concurrent?: boolean | undefined
3220
- readonly batching?: boolean | "inherit" | undefined
3221
- readonly concurrentFinalizers?: boolean | undefined
3222
- }
3223
- ): Effect.Effect<B, E2 | E, R2 | R> =>
3224
- core.map(
3225
- all([self, that], {
3226
- concurrency: options?.concurrent ? 2 : 1,
3227
- batching: options?.batching,
3228
- concurrentFinalizers: options?.concurrentFinalizers
3229
- }),
3230
- ([a, a2]) => f(a, a2)
3231
- ))
3232
-
3233
- /* @internal */
3234
- export const withRuntimeFlagsScoped = (
3235
- update: RuntimeFlagsPatch.RuntimeFlagsPatch
3236
- ): Effect.Effect<void, never, Scope.Scope> => {
3237
- if (update === RuntimeFlagsPatch.empty) {
3238
- return core.void
3239
- }
3240
- return pipe(
3241
- core.runtimeFlags,
3242
- core.flatMap((runtimeFlags) => {
3243
- const updatedRuntimeFlags = runtimeFlags_.patch(runtimeFlags, update)
3244
- const revertRuntimeFlags = runtimeFlags_.diff(updatedRuntimeFlags, runtimeFlags)
3245
- return pipe(
3246
- core.updateRuntimeFlags(update),
3247
- core.zipRight(addFinalizer(() => core.updateRuntimeFlags(revertRuntimeFlags))),
3248
- core.asVoid
3249
- )
3250
- }),
3251
- core.uninterruptible
3252
- )
3253
- }
3254
-
3255
- // circular with Scope
3256
-
3257
- /** @internal */
3258
- export const scopeTag = Context.GenericTag<Scope.Scope>("effect/Scope")
3259
-
3260
- /* @internal */
3261
- export const scope: Effect.Effect<Scope.Scope, never, Scope.Scope> = scopeTag
3262
-
3263
- /** @internal */
3264
- export interface ScopeImpl extends Scope.CloseableScope {
3265
- state: {
3266
- readonly _tag: "Open"
3267
- readonly finalizers: Map<{}, Scope.Scope.Finalizer>
3268
- } | {
3269
- readonly _tag: "Closed"
3270
- readonly exit: Exit.Exit<unknown, unknown>
3271
- }
3272
- }
3273
-
3274
- const scopeUnsafeAddFinalizer = (scope: ScopeImpl, fin: Scope.Scope.Finalizer): void => {
3275
- if (scope.state._tag === "Open") {
3276
- scope.state.finalizers.set({}, fin)
3277
- }
3278
- }
3279
-
3280
- const ScopeImplProto: Omit<ScopeImpl, "strategy" | "state"> = {
3281
- [core.ScopeTypeId]: core.ScopeTypeId,
3282
- [core.CloseableScopeTypeId]: core.CloseableScopeTypeId,
3283
- pipe() {
3284
- return pipeArguments(this, arguments)
3285
- },
3286
- fork(this: ScopeImpl, strategy) {
3287
- return core.sync(() => {
3288
- const newScope = scopeUnsafeMake(strategy)
3289
- if (this.state._tag === "Closed") {
3290
- newScope.state = this.state
3291
- return newScope
3292
- }
3293
- const key = {}
3294
- const fin = (exit: Exit.Exit<unknown, unknown>) => newScope.close(exit)
3295
- this.state.finalizers.set(key, fin)
3296
- scopeUnsafeAddFinalizer(newScope, (_) =>
3297
- core.sync(() => {
3298
- if (this.state._tag === "Open") {
3299
- this.state.finalizers.delete(key)
3300
- }
3301
- }))
3302
- return newScope
3303
- })
3304
- },
3305
- close(this: ScopeImpl, exit) {
3306
- return core.suspend(() => {
3307
- if (this.state._tag === "Closed") {
3308
- return core.void
3309
- }
3310
- const finalizers = Array.from(this.state.finalizers.values()).reverse()
3311
- this.state = { _tag: "Closed", exit }
3312
- if (finalizers.length === 0) {
3313
- return core.void
3314
- }
3315
- return executionStrategy.isSequential(this.strategy) ?
3316
- pipe(
3317
- core.forEachSequential(finalizers, (fin) => core.exit(fin(exit))),
3318
- core.flatMap((results) =>
3319
- pipe(
3320
- core.exitCollectAll(results),
3321
- Option.map(core.exitAsVoid),
3322
- Option.getOrElse(() => core.exitVoid)
3323
- )
3324
- )
3325
- ) :
3326
- executionStrategy.isParallel(this.strategy) ?
3327
- pipe(
3328
- forEachParUnbounded(finalizers, (fin) => core.exit(fin(exit)), false),
3329
- core.flatMap((results) =>
3330
- pipe(
3331
- core.exitCollectAll(results, { parallel: true }),
3332
- Option.map(core.exitAsVoid),
3333
- Option.getOrElse(() => core.exitVoid)
3334
- )
3335
- )
3336
- ) :
3337
- pipe(
3338
- forEachParN(finalizers, this.strategy.parallelism, (fin) => core.exit(fin(exit)), false),
3339
- core.flatMap((results) =>
3340
- pipe(
3341
- core.exitCollectAll(results, { parallel: true }),
3342
- Option.map(core.exitAsVoid),
3343
- Option.getOrElse(() => core.exitVoid)
3344
- )
3345
- )
3346
- )
3347
- })
3348
- },
3349
- addFinalizer(this: ScopeImpl, fin) {
3350
- return core.suspend(() => {
3351
- if (this.state._tag === "Closed") {
3352
- return fin(this.state.exit)
3353
- }
3354
- this.state.finalizers.set({}, fin)
3355
- return core.void
3356
- })
3357
- }
3358
- }
3359
-
3360
- const scopeUnsafeMake = (
3361
- strategy: ExecutionStrategy.ExecutionStrategy = executionStrategy.sequential
3362
- ): ScopeImpl => {
3363
- const scope = Object.create(ScopeImplProto)
3364
- scope.strategy = strategy
3365
- scope.state = { _tag: "Open", finalizers: new Map() }
3366
- return scope
3367
- }
3368
-
3369
- /* @internal */
3370
- export const scopeMake = (
3371
- strategy: ExecutionStrategy.ExecutionStrategy = executionStrategy.sequential
3372
- ): Effect.Effect<Scope.Scope.Closeable> => core.sync(() => scopeUnsafeMake(strategy))
3373
-
3374
- /* @internal */
3375
- export const scopeExtend = dual<
3376
- (scope: Scope.Scope) => <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, E, Exclude<R, Scope.Scope>>,
3377
- <A, E, R>(effect: Effect.Effect<A, E, R>, scope: Scope.Scope) => Effect.Effect<A, E, Exclude<R, Scope.Scope>>
3378
- >(
3379
- 2,
3380
- <A, E, R>(effect: Effect.Effect<A, E, R>, scope: Scope.Scope) =>
3381
- core.mapInputContext<A, E, R, Exclude<R, Scope.Scope>>(
3382
- effect,
3383
- // @ts-expect-error
3384
- Context.merge(Context.make(scopeTag, scope))
3385
- )
3386
- )
3387
-
3388
- /* @internal */
3389
- export const scopeUse = dual<
3390
- (
3391
- scope: Scope.Scope.Closeable
3392
- ) => <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, E, Exclude<R, Scope.Scope>>,
3393
- <A, E, R>(
3394
- effect: Effect.Effect<A, E, R>,
3395
- scope: Scope.Scope.Closeable
3396
- ) => Effect.Effect<A, E, Exclude<R, Scope.Scope>>
3397
- >(2, (effect, scope) =>
3398
- pipe(
3399
- effect,
3400
- scopeExtend(scope),
3401
- core.onExit((exit) => scope.close(exit))
3402
- ))
3403
-
3404
- // circular with Supervisor
3405
-
3406
- /** @internal */
3407
- export const fiberRefUnsafeMakeSupervisor = (
3408
- initial: Supervisor.Supervisor<any>
3409
- ): FiberRef.FiberRef<Supervisor.Supervisor<any>> =>
3410
- core.fiberRefUnsafeMakePatch(initial, {
3411
- differ: SupervisorPatch.differ,
3412
- fork: SupervisorPatch.empty
3413
- })
3414
-
3415
- // circular with FiberRef
3416
-
3417
- /* @internal */
3418
- export const fiberRefLocallyScoped = dual<
3419
- <A>(value: A) => (self: FiberRef.FiberRef<A>) => Effect.Effect<void, never, Scope.Scope>,
3420
- <A>(self: FiberRef.FiberRef<A>, value: A) => Effect.Effect<void, never, Scope.Scope>
3421
- >(2, (self, value) =>
3422
- core.asVoid(
3423
- acquireRelease(
3424
- core.flatMap(
3425
- core.fiberRefGet(self),
3426
- (oldValue) => core.as(core.fiberRefSet(self, value), oldValue)
3427
- ),
3428
- (oldValue) => core.fiberRefSet(self, oldValue)
3429
- )
3430
- ))
3431
-
3432
- /* @internal */
3433
- export const fiberRefLocallyScopedWith = dual<
3434
- <A>(f: (a: A) => A) => (self: FiberRef.FiberRef<A>) => Effect.Effect<void, never, Scope.Scope>,
3435
- <A>(self: FiberRef.FiberRef<A>, f: (a: A) => A) => Effect.Effect<void, never, Scope.Scope>
3436
- >(2, (self, f) => core.fiberRefGetWith(self, (a) => fiberRefLocallyScoped(self, f(a))))
3437
-
3438
- /* @internal */
3439
- export const fiberRefMake = <A>(
3440
- initial: A,
3441
- options?: {
3442
- readonly fork?: ((a: A) => A) | undefined
3443
- readonly join?: ((left: A, right: A) => A) | undefined
3444
- }
3445
- ): Effect.Effect<FiberRef.FiberRef<A>, never, Scope.Scope> =>
3446
- fiberRefMakeWith(() => core.fiberRefUnsafeMake(initial, options))
3447
-
3448
- /* @internal */
3449
- export const fiberRefMakeWith = <Value>(
3450
- ref: LazyArg<FiberRef.FiberRef<Value>>
3451
- ): Effect.Effect<FiberRef.FiberRef<Value>, never, Scope.Scope> =>
3452
- acquireRelease(
3453
- core.tap(core.sync(ref), (ref) => core.fiberRefUpdate(ref, identity)),
3454
- (fiberRef) => core.fiberRefDelete(fiberRef)
3455
- )
3456
-
3457
- /* @internal */
3458
- export const fiberRefMakeContext = <A>(
3459
- initial: Context.Context<A>
3460
- ): Effect.Effect<FiberRef.FiberRef<Context.Context<A>>, never, Scope.Scope> =>
3461
- fiberRefMakeWith(() => core.fiberRefUnsafeMakeContext(initial))
3462
-
3463
- /* @internal */
3464
- export const fiberRefMakeRuntimeFlags = (
3465
- initial: RuntimeFlags.RuntimeFlags
3466
- ): Effect.Effect<FiberRef.FiberRef<RuntimeFlags.RuntimeFlags>, never, Scope.Scope> =>
3467
- fiberRefMakeWith(() => core.fiberRefUnsafeMakeRuntimeFlags(initial))
3468
-
3469
- /** @internal */
3470
- export const currentRuntimeFlags: FiberRef.FiberRef<RuntimeFlags.RuntimeFlags> = core.fiberRefUnsafeMakeRuntimeFlags(
3471
- runtimeFlags_.none
3472
- )
3473
-
3474
- /** @internal */
3475
- export const currentSupervisor: FiberRef.FiberRef<Supervisor.Supervisor<any>> = fiberRefUnsafeMakeSupervisor(
3476
- supervisor.none
3477
- )
3478
-
3479
- // circular with Fiber
3480
-
3481
- /* @internal */
3482
- export const fiberAwaitAll = <const T extends Iterable<Fiber.Fiber<any, any>>>(
3483
- fibers: T
3484
- ): Effect.Effect<
3485
- [T] extends [ReadonlyArray<infer U>]
3486
- ? number extends T["length"] ? Array<U extends Fiber.Fiber<infer A, infer E> ? Exit.Exit<A, E> : never>
3487
- : { -readonly [K in keyof T]: T[K] extends Fiber.Fiber<infer A, infer E> ? Exit.Exit<A, E> : never }
3488
- : Array<T extends Iterable<infer U> ? U extends Fiber.Fiber<infer A, infer E> ? Exit.Exit<A, E> : never : never>
3489
- > => forEach(fibers, internalFiber._await) as any
3490
-
3491
- /** @internal */
3492
- export const fiberAll = <A, E>(fibers: Iterable<Fiber.Fiber<A, E>>): Fiber.Fiber<Array<A>, E> => {
3493
- const _fiberAll = {
3494
- ...Effectable.CommitPrototype,
3495
- commit() {
3496
- return internalFiber.join(this)
3497
- },
3498
- [internalFiber.FiberTypeId]: internalFiber.fiberVariance,
3499
- id: () =>
3500
- RA.fromIterable(fibers).reduce((id, fiber) => FiberId.combine(id, fiber.id()), FiberId.none as FiberId.FiberId),
3501
- await: core.exit(forEachParUnbounded(fibers, (fiber) => core.flatten(fiber.await), false)),
3502
- children: core.map(forEachParUnbounded(fibers, (fiber) => fiber.children, false), RA.flatten),
3503
- inheritAll: core.forEachSequentialDiscard(fibers, (fiber) => fiber.inheritAll),
3504
- poll: core.map(
3505
- core.forEachSequential(fibers, (fiber) => fiber.poll),
3506
- RA.reduceRight(
3507
- Option.some<Exit.Exit<Array<A>, E>>(core.exitSucceed(new Array())),
3508
- (optionB, optionA) => {
3509
- switch (optionA._tag) {
3510
- case "None": {
3511
- return Option.none()
3512
- }
3513
- case "Some": {
3514
- switch (optionB._tag) {
3515
- case "None": {
3516
- return Option.none()
3517
- }
3518
- case "Some": {
3519
- return Option.some(
3520
- core.exitZipWith(optionA.value, optionB.value, {
3521
- onSuccess: (a, chunk) => [a, ...chunk],
3522
- onFailure: internalCause.parallel
3523
- })
3524
- )
3525
- }
3526
- }
3527
- }
3528
- }
3529
- }
3530
- )
3531
- ),
3532
- interruptAsFork: (fiberId: FiberId.FiberId) =>
3533
- core.forEachSequentialDiscard(fibers, (fiber) => fiber.interruptAsFork(fiberId))
3534
- }
3535
- return _fiberAll
3536
- }
3537
-
3538
- /* @internal */
3539
- export const fiberInterruptFork = <A, E>(self: Fiber.Fiber<A, E>): Effect.Effect<void> =>
3540
- core.asVoid(forkDaemon(core.interruptFiber(self)))
3541
-
3542
- /* @internal */
3543
- export const fiberJoinAll = <A, E>(fibers: Iterable<Fiber.Fiber<A, E>>): Effect.Effect<Array<A>, E> =>
3544
- internalFiber.join(fiberAll(fibers))
3545
-
3546
- /* @internal */
3547
- export const fiberScoped = <A, E>(self: Fiber.Fiber<A, E>): Effect.Effect<Fiber.Fiber<A, E>, never, Scope.Scope> =>
3548
- acquireRelease(core.succeed(self), core.interruptFiber)
3549
-
3550
- //
3551
- // circular race
3552
- //
3553
-
3554
- /** @internal */
3555
- export const raceWith = dual<
3556
- <A1, E1, R1, E, A, A2, E2, R2, A3, E3, R3>(
3557
- other: Effect.Effect<A1, E1, R1>,
3558
- options: {
3559
- readonly onSelfDone: (exit: Exit.Exit<A, E>, fiber: Fiber.Fiber<A1, E1>) => Effect.Effect<A2, E2, R2>
3560
- readonly onOtherDone: (exit: Exit.Exit<A1, E1>, fiber: Fiber.Fiber<A, E>) => Effect.Effect<A3, E3, R3>
3561
- }
3562
- ) => <R>(self: Effect.Effect<A, E, R>) => Effect.Effect<A2 | A3, E2 | E3, R | R1 | R2 | R3>,
3563
- <A, E, R, A1, E1, R1, A2, E2, R2, A3, E3, R3>(
3564
- self: Effect.Effect<A, E, R>,
3565
- other: Effect.Effect<A1, E1, R1>,
3566
- options: {
3567
- readonly onSelfDone: (exit: Exit.Exit<A, E>, fiber: Fiber.Fiber<A1, E1>) => Effect.Effect<A2, E2, R2>
3568
- readonly onOtherDone: (exit: Exit.Exit<A1, E1>, fiber: Fiber.Fiber<A, E>) => Effect.Effect<A3, E3, R3>
3569
- }
3570
- ) => Effect.Effect<A2 | A3, E2 | E3, R | R1 | R2 | R3>
3571
- >(3, (self, other, options) =>
3572
- raceFibersWith(self, other, {
3573
- onSelfWin: (winner, loser) =>
3574
- core.flatMap(winner.await, (exit) => {
3575
- switch (exit._tag) {
3576
- case OpCodes.OP_SUCCESS: {
3577
- return core.flatMap(
3578
- winner.inheritAll,
3579
- () => options.onSelfDone(exit, loser)
3580
- )
3581
- }
3582
- case OpCodes.OP_FAILURE: {
3583
- return options.onSelfDone(exit, loser)
3584
- }
3585
- }
3586
- }),
3587
- onOtherWin: (winner, loser) =>
3588
- core.flatMap(winner.await, (exit) => {
3589
- switch (exit._tag) {
3590
- case OpCodes.OP_SUCCESS: {
3591
- return core.flatMap(
3592
- winner.inheritAll,
3593
- () => options.onOtherDone(exit, loser)
3594
- )
3595
- }
3596
- case OpCodes.OP_FAILURE: {
3597
- return options.onOtherDone(exit, loser)
3598
- }
3599
- }
3600
- })
3601
- }))
3602
-
3603
- /** @internal */
3604
- export const disconnect = <A, E, R>(self: Effect.Effect<A, E, R>): Effect.Effect<A, E, R> =>
3605
- core.uninterruptibleMask((restore) =>
3606
- core.fiberIdWith((fiberId) =>
3607
- core.flatMap(forkDaemon(restore(self)), (fiber) =>
3608
- pipe(
3609
- restore(internalFiber.join(fiber)),
3610
- core.onInterrupt(() => pipe(fiber, internalFiber.interruptAsFork(fiberId)))
3611
- ))
3612
- )
3613
- )
3614
-
3615
- /** @internal */
3616
- export const race = dual<
3617
- <A2, E2, R2>(
3618
- that: Effect.Effect<A2, E2, R2>
3619
- ) => <A, E, R>(
3620
- self: Effect.Effect<A, E, R>
3621
- ) => Effect.Effect<A | A2, E | E2, R | R2>,
3622
- <A, E, R, A2, E2, R2>(
3623
- self: Effect.Effect<A, E, R>,
3624
- that: Effect.Effect<A2, E2, R2>
3625
- ) => Effect.Effect<A | A2, E | E2, R | R2>
3626
- >(
3627
- 2,
3628
- (self, that) =>
3629
- core.fiberIdWith((parentFiberId) =>
3630
- raceWith(self, that, {
3631
- onSelfDone: (exit, right) =>
3632
- core.exitMatchEffect(exit, {
3633
- onFailure: (cause) =>
3634
- pipe(
3635
- internalFiber.join(right),
3636
- internalEffect.mapErrorCause((cause2) => internalCause.parallel(cause, cause2))
3637
- ),
3638
- onSuccess: (value) =>
3639
- pipe(
3640
- right,
3641
- core.interruptAsFiber(parentFiberId),
3642
- core.as(value)
3643
- )
3644
- }),
3645
- onOtherDone: (exit, left) =>
3646
- core.exitMatchEffect(exit, {
3647
- onFailure: (cause) =>
3648
- pipe(
3649
- internalFiber.join(left),
3650
- internalEffect.mapErrorCause((cause2) => internalCause.parallel(cause2, cause))
3651
- ),
3652
- onSuccess: (value) =>
3653
- pipe(
3654
- left,
3655
- core.interruptAsFiber(parentFiberId),
3656
- core.as(value)
3657
- )
3658
- })
3659
- })
3660
- )
3661
- )
3662
-
3663
- /** @internal */
3664
- export const raceFibersWith = dual<
3665
- <A1, E1, R1, E, A, A2, E2, R2, A3, E3, R3>(
3666
- other: Effect.Effect<A1, E1, R1>,
3667
- options: {
3668
- readonly onSelfWin: (
3669
- winner: Fiber.RuntimeFiber<A, E>,
3670
- loser: Fiber.RuntimeFiber<A1, E1>
3671
- ) => Effect.Effect<A2, E2, R2>
3672
- readonly onOtherWin: (
3673
- winner: Fiber.RuntimeFiber<A1, E1>,
3674
- loser: Fiber.RuntimeFiber<A, E>
3675
- ) => Effect.Effect<A3, E3, R3>
3676
- readonly selfScope?: fiberScope.FiberScope | undefined
3677
- readonly otherScope?: fiberScope.FiberScope | undefined
3678
- }
3679
- ) => <R>(self: Effect.Effect<A, E, R>) => Effect.Effect<A2 | A3, E2 | E3, R | R1 | R2 | R3>,
3680
- <A, E, R, A1, E1, R1, A2, E2, R2, A3, E3, R3>(
3681
- self: Effect.Effect<A, E, R>,
3682
- other: Effect.Effect<A1, E1, R1>,
3683
- options: {
3684
- readonly onSelfWin: (
3685
- winner: Fiber.RuntimeFiber<A, E>,
3686
- loser: Fiber.RuntimeFiber<A1, E1>
3687
- ) => Effect.Effect<A2, E2, R2>
3688
- readonly onOtherWin: (
3689
- winner: Fiber.RuntimeFiber<A1, E1>,
3690
- loser: Fiber.RuntimeFiber<A, E>
3691
- ) => Effect.Effect<A3, E3, R3>
3692
- readonly selfScope?: fiberScope.FiberScope | undefined
3693
- readonly otherScope?: fiberScope.FiberScope | undefined
3694
- }
3695
- ) => Effect.Effect<A2 | A3, E2 | E3, R | R1 | R2 | R3>
3696
- >(3, <A, E, R, A1, E1, R1, A2, E2, R2, A3, E3, R3>(
3697
- self: Effect.Effect<A, E, R>,
3698
- other: Effect.Effect<A1, E1, R1>,
3699
- options: {
3700
- readonly onSelfWin: (
3701
- winner: Fiber.RuntimeFiber<A, E>,
3702
- loser: Fiber.RuntimeFiber<A1, E1>
3703
- ) => Effect.Effect<A2, E2, R2>
3704
- readonly onOtherWin: (
3705
- winner: Fiber.RuntimeFiber<A1, E1>,
3706
- loser: Fiber.RuntimeFiber<A, E>
3707
- ) => Effect.Effect<A3, E3, R3>
3708
- readonly selfScope?: fiberScope.FiberScope | undefined
3709
- readonly otherScope?: fiberScope.FiberScope | undefined
3710
- }
3711
- ) =>
3712
- core.withFiberRuntime((parentFiber, parentStatus) => {
3713
- const parentRuntimeFlags = parentStatus.runtimeFlags
3714
- const raceIndicator = MRef.make(true)
3715
- const leftFiber: FiberRuntime<A, E> = unsafeMakeChildFiber(
3716
- self,
3717
- parentFiber,
3718
- parentRuntimeFlags,
3719
- options.selfScope
3720
- )
3721
- const rightFiber: FiberRuntime<A1, E1> = unsafeMakeChildFiber(
3722
- other,
3723
- parentFiber,
3724
- parentRuntimeFlags,
3725
- options.otherScope
3726
- )
3727
- return core.async((cb) => {
3728
- leftFiber.addObserver(() => completeRace(leftFiber, rightFiber, options.onSelfWin, raceIndicator, cb))
3729
- rightFiber.addObserver(() => completeRace(rightFiber, leftFiber, options.onOtherWin, raceIndicator, cb))
3730
- leftFiber.startFork(self)
3731
- rightFiber.startFork(other)
3732
- }, FiberId.combine(leftFiber.id(), rightFiber.id()))
3733
- }))
3734
-
3735
- const completeRace = <A2, A3, E2, E3, R, R1, R2, R3>(
3736
- winner: Fiber.RuntimeFiber<any, any>,
3737
- loser: Fiber.RuntimeFiber<any, any>,
3738
- cont: (winner: Fiber.RuntimeFiber<any, any>, loser: Fiber.RuntimeFiber<any, any>) => Effect.Effect<any, any, any>,
3739
- ab: MRef.MutableRef<boolean>,
3740
- cb: (_: Effect.Effect<A2 | A3, E2 | E3, R | R1 | R2 | R3>) => void
3741
- ): void => {
3742
- if (MRef.compareAndSet(true, false)(ab)) {
3743
- cb(cont(winner, loser))
3744
- }
3745
- }
3746
-
3747
- /** @internal */
3748
- export const ensuring: {
3749
- <X, R1>(
3750
- finalizer: Effect.Effect<X, never, R1>
3751
- ): <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R1 | R>
3752
- <A, E, R, X, R1>(self: Effect.Effect<A, E, R>, finalizer: Effect.Effect<X, never, R1>): Effect.Effect<A, E, R1 | R>
3753
- } = dual(
3754
- 2,
3755
- <A, E, R, X, R1>(self: Effect.Effect<A, E, R>, finalizer: Effect.Effect<X, never, R1>): Effect.Effect<A, E, R1 | R> =>
3756
- core.uninterruptibleMask((restore) =>
3757
- core.matchCauseEffect(restore(self), {
3758
- onFailure: (cause1) =>
3759
- core.matchCauseEffect(finalizer, {
3760
- onFailure: (cause2) => core.failCause(internalCause.sequential(cause1, cause2)),
3761
- onSuccess: () => core.failCause(cause1)
3762
- }),
3763
- onSuccess: (a) => core.as(finalizer, a)
3764
- })
3765
- )
3766
- )
3767
-
3768
- /** @internal */
3769
- export const invokeWithInterrupt: <A, E, R>(
3770
- self: Effect.Effect<A, E, R>,
3771
- entries: ReadonlyArray<Entry<unknown>>,
3772
- onInterrupt?: () => void
3773
- ) => Effect.Effect<void, E, R> = <A, E, R>(
3774
- self: Effect.Effect<A, E, R>,
3775
- entries: ReadonlyArray<Entry<unknown>>,
3776
- onInterrupt?: () => void
3777
- ) =>
3778
- core.fiberIdWith((id) =>
3779
- core.flatMap(
3780
- core.flatMap(
3781
- forkDaemon(core.interruptible(self)),
3782
- (processing) =>
3783
- core.async<void, E>((cb) => {
3784
- const counts = entries.map((_) => _.listeners.count)
3785
- const checkDone = () => {
3786
- if (counts.every((count) => count === 0)) {
3787
- if (
3788
- entries.every((_) => {
3789
- if (_.result.state.current._tag === "Pending") {
3790
- return true
3791
- } else if (
3792
- _.result.state.current._tag === "Done" &&
3793
- core.exitIsExit(_.result.state.current.effect) &&
3794
- _.result.state.current.effect._tag === "Failure" &&
3795
- internalCause.isInterrupted(_.result.state.current.effect.cause)
3796
- ) {
3797
- return true
3798
- } else {
3799
- return false
3800
- }
3801
- })
3802
- ) {
3803
- cleanup.forEach((f) => f())
3804
- onInterrupt?.()
3805
- cb(core.interruptFiber(processing))
3806
- }
3807
- }
3808
- }
3809
- processing.addObserver((exit) => {
3810
- cleanup.forEach((f) => f())
3811
- cb(exit)
3812
- })
3813
- const cleanup = entries.map((r, i) => {
3814
- const observer = (count: number) => {
3815
- counts[i] = count
3816
- checkDone()
3817
- }
3818
- r.listeners.addObserver(observer)
3819
- return () => r.listeners.removeObserver(observer)
3820
- })
3821
- checkDone()
3822
- return core.sync(() => {
3823
- cleanup.forEach((f) => f())
3824
- })
3825
- })
3826
- ),
3827
- () =>
3828
- core.suspend(() => {
3829
- const residual = entries.flatMap((entry) => {
3830
- if (!entry.state.completed) {
3831
- return [entry]
3832
- }
3833
- return []
3834
- })
3835
- return core.forEachSequentialDiscard(
3836
- residual,
3837
- (entry) => complete(entry.request as any, core.exitInterrupt(id))
3838
- )
3839
- })
3840
- )
3841
- )
3842
-
3843
- /** @internal */
3844
- export const interruptWhenPossible = dual<
3845
- (all: Iterable<Request<any, any>>) => <A, E, R>(
3846
- self: Effect.Effect<A, E, R>
3847
- ) => Effect.Effect<void, E, R>,
3848
- <A, E, R>(
3849
- self: Effect.Effect<A, E, R>,
3850
- all: Iterable<Request<any, any>>
3851
- ) => Effect.Effect<void, E, R>
3852
- >(2, (self, all) =>
3853
- core.fiberRefGetWith(
3854
- currentRequestMap,
3855
- (map) =>
3856
- core.suspend(() => {
3857
- const entries = RA.fromIterable(all).flatMap((_) => map.has(_) ? [map.get(_)!] : [])
3858
- return invokeWithInterrupt(self, entries)
3859
- })
3860
- ))
3861
-
3862
- // circular Tracer
3863
-
3864
- /** @internal */
3865
- export const makeSpanScoped = (
3866
- name: string,
3867
- options?: Tracer.SpanOptions | undefined
3868
- ): Effect.Effect<Tracer.Span, never, Scope.Scope> => {
3869
- options = tracer.addSpanStackTrace(options)
3870
- return core.uninterruptible(
3871
- core.withFiberRuntime((fiber) => {
3872
- const scope = Context.unsafeGet(fiber.getFiberRef(core.currentContext), scopeTag)
3873
- const span = internalEffect.unsafeMakeSpan(fiber, name, options)
3874
- const timingEnabled = fiber.getFiberRef(core.currentTracerTimingEnabled)
3875
- const clock_ = Context.get(fiber.getFiberRef(defaultServices.currentServices), clock.clockTag)
3876
- return core.as(
3877
- core.scopeAddFinalizerExit(scope, (exit) => internalEffect.endSpan(span, exit, clock_, timingEnabled)),
3878
- span
3879
- )
3880
- })
3881
- )
3882
- }
3883
-
3884
- /* @internal */
3885
- export const withTracerScoped = (value: Tracer.Tracer): Effect.Effect<void, never, Scope.Scope> =>
3886
- fiberRefLocallyScopedWith(defaultServices.currentServices, Context.add(tracer.tracerTag, value))
3887
-
3888
- /** @internal */
3889
- export const withSpanScoped: {
3890
- (
3891
- name: string,
3892
- options?: Tracer.SpanOptions
3893
- ): <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<A, E, Scope.Scope | Exclude<R, Tracer.ParentSpan>>
3894
- <A, E, R>(
3895
- self: Effect.Effect<A, E, R>,
3896
- name: string,
3897
- options?: Tracer.SpanOptions
3898
- ): Effect.Effect<A, E, Scope.Scope | Exclude<R, Tracer.ParentSpan>>
3899
- } = function() {
3900
- const dataFirst = typeof arguments[0] !== "string"
3901
- const name = dataFirst ? arguments[1] : arguments[0]
3902
- const options = tracer.addSpanStackTrace(dataFirst ? arguments[2] : arguments[1])
3903
- if (dataFirst) {
3904
- const self = arguments[0]
3905
- return core.flatMap(
3906
- makeSpanScoped(name, tracer.addSpanStackTrace(options)),
3907
- (span) => internalEffect.provideService(self, tracer.spanTag, span)
3908
- )
3909
- }
3910
- return (self: Effect.Effect<any, any, any>) =>
3911
- core.flatMap(
3912
- makeSpanScoped(name, tracer.addSpanStackTrace(options)),
3913
- (span) => internalEffect.provideService(self, tracer.spanTag, span)
3914
- )
3915
- } as any