| 2355 | * @since 4.0.0 |
| 2356 | */ |
| 2357 | export class BackPressureStrategy<in out A> implements PubSub.Strategy<A> { |
| 2358 | publishers: MutableList.MutableList< |
| 2359 | readonly [A, Deferred.Deferred<boolean>, boolean] |
| 2360 | > = MutableList.make() |
| 2361 | |
| 2362 | get shutdown(): Effect.Effect<void> { |
| 2363 | return Effect.withFiber((fiber) => |
| 2364 | Effect.forEach( |
| 2365 | MutableList.takeAll(this.publishers), |
| 2366 | ([_, deferred, last]) => last ? Deferred.interruptWith(deferred, fiber.id) : Effect.void, |
| 2367 | { concurrency: "unbounded", discard: true } |
| 2368 | ) |
| 2369 | ) |
| 2370 | } |
| 2371 | |
| 2372 | handleSurplus( |
| 2373 | pubsub: PubSub.Atomic<A>, |
| 2374 | subscribers: PubSub.Subscribers<A>, |
| 2375 | elements: Iterable<A>, |
| 2376 | isShutdown: MutableRef.MutableRef<boolean> |
| 2377 | ): Effect.Effect<boolean> { |
| 2378 | return Effect.suspend(() => { |
| 2379 | const deferred = Deferred.makeUnsafe<boolean>() |
| 2380 | this.offerUnsafe(elements, deferred) |
| 2381 | this.onPubSubEmptySpaceUnsafe(pubsub, subscribers) |
| 2382 | this.completeSubscribersUnsafe(pubsub, subscribers) |
| 2383 | return (MutableRef.get(isShutdown) ? Effect.interrupt : Deferred.await(deferred)).pipe( |
| 2384 | Effect.onInterrupt(() => { |
| 2385 | this.removeUnsafe(deferred) |
| 2386 | return Effect.void |
| 2387 | }) |
| 2388 | ) |
| 2389 | }) |
| 2390 | } |
| 2391 | |
| 2392 | onPubSubEmptySpaceUnsafe( |
| 2393 | pubsub: PubSub.Atomic<A>, |
| 2394 | subscribers: PubSub.Subscribers<A> |
| 2395 | ): void { |
| 2396 | let keepPolling = true |
| 2397 | while (keepPolling && !pubsub.isFull()) { |
| 2398 | const publisher = MutableList.take(this.publishers) |
| 2399 | if (publisher === MutableList.Empty) { |
| 2400 | keepPolling = false |
| 2401 | } else { |
| 2402 | const [value, deferred] = publisher |
| 2403 | const published = pubsub.publish(value) |
| 2404 | if (published && publisher[2]) { |
| 2405 | Deferred.doneUnsafe(deferred, Exit.succeed(true)) |
| 2406 | } else if (!published) { |
| 2407 | MutableList.prepend(this.publishers, publisher) |
| 2408 | } |
| 2409 | this.completeSubscribersUnsafe(pubsub, subscribers) |
| 2410 | } |
| 2411 | } |
| 2412 | } |
| 2413 | |
| 2414 | completePollersUnsafe( |