effect 4.0.0-beta.17 → 4.0.0-beta.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Array.d.ts +127 -299
- package/dist/Array.d.ts.map +1 -1
- package/dist/Array.js +102 -62
- package/dist/Array.js.map +1 -1
- package/dist/Cache.d.ts.map +1 -1
- package/dist/Cache.js +5 -4
- package/dist/Cache.js.map +1 -1
- package/dist/Channel.d.ts +97 -11
- package/dist/Channel.d.ts.map +1 -1
- package/dist/Channel.js +72 -29
- package/dist/Channel.js.map +1 -1
- package/dist/Chunk.d.ts +54 -247
- package/dist/Chunk.d.ts.map +1 -1
- package/dist/Chunk.js +36 -67
- package/dist/Chunk.js.map +1 -1
- package/dist/Effect.d.ts +337 -437
- package/dist/Effect.d.ts.map +1 -1
- package/dist/Effect.js +118 -134
- package/dist/Effect.js.map +1 -1
- package/dist/Filter.d.ts +0 -33
- package/dist/Filter.d.ts.map +1 -1
- package/dist/Filter.js +0 -13
- package/dist/Filter.js.map +1 -1
- package/dist/HashMap.d.ts +15 -14
- package/dist/HashMap.d.ts.map +1 -1
- package/dist/HashMap.js +4 -4
- package/dist/HashMap.js.map +1 -1
- package/dist/Iterable.d.ts +40 -39
- package/dist/Iterable.d.ts.map +1 -1
- package/dist/Iterable.js +94 -22
- package/dist/Iterable.js.map +1 -1
- package/dist/Option.d.ts +22 -15
- package/dist/Option.d.ts.map +1 -1
- package/dist/Option.js +14 -7
- package/dist/Option.js.map +1 -1
- package/dist/Pull.d.ts.map +1 -1
- package/dist/Pull.js +1 -1
- package/dist/Pull.js.map +1 -1
- package/dist/Record.d.ts +24 -120
- package/dist/Record.d.ts.map +1 -1
- package/dist/Record.js +21 -41
- package/dist/Record.js.map +1 -1
- package/dist/Sink.d.ts +11 -11
- package/dist/Sink.d.ts.map +1 -1
- package/dist/Sink.js +53 -6
- package/dist/Sink.js.map +1 -1
- package/dist/Stream.d.ts +198 -386
- package/dist/Stream.d.ts.map +1 -1
- package/dist/Stream.js +103 -59
- package/dist/Stream.js.map +1 -1
- package/dist/Trie.d.ts +18 -17
- package/dist/Trie.d.ts.map +1 -1
- package/dist/Trie.js +5 -5
- package/dist/Trie.js.map +1 -1
- package/dist/TxChunk.d.ts +37 -37
- package/dist/TxChunk.d.ts.map +1 -1
- package/dist/TxChunk.js +3 -3
- package/dist/TxChunk.js.map +1 -1
- package/dist/TxDeferred.d.ts +328 -0
- package/dist/TxDeferred.d.ts.map +1 -0
- package/dist/TxDeferred.js +196 -0
- package/dist/TxDeferred.js.map +1 -0
- package/dist/TxHashMap.d.ts +84 -83
- package/dist/TxHashMap.d.ts.map +1 -1
- package/dist/TxHashMap.js +24 -24
- package/dist/TxHashMap.js.map +1 -1
- package/dist/TxHashSet.d.ts +35 -35
- package/dist/TxHashSet.d.ts.map +1 -1
- package/dist/TxHashSet.js +14 -14
- package/dist/TxHashSet.js.map +1 -1
- package/dist/TxPriorityQueue.d.ts +609 -0
- package/dist/TxPriorityQueue.d.ts.map +1 -0
- package/dist/TxPriorityQueue.js +415 -0
- package/dist/TxPriorityQueue.js.map +1 -0
- package/dist/TxPubSub.d.ts +585 -0
- package/dist/TxPubSub.d.ts.map +1 -0
- package/dist/TxPubSub.js +521 -0
- package/dist/TxPubSub.js.map +1 -0
- package/dist/TxQueue.d.ts +32 -32
- package/dist/TxQueue.d.ts.map +1 -1
- package/dist/TxQueue.js +26 -26
- package/dist/TxQueue.js.map +1 -1
- package/dist/TxReentrantLock.d.ts +523 -0
- package/dist/TxReentrantLock.d.ts.map +1 -0
- package/dist/TxReentrantLock.js +504 -0
- package/dist/TxReentrantLock.js.map +1 -0
- package/dist/TxRef.d.ts +34 -34
- package/dist/TxRef.d.ts.map +1 -1
- package/dist/TxRef.js +21 -14
- package/dist/TxRef.js.map +1 -1
- package/dist/TxSemaphore.d.ts +8 -8
- package/dist/TxSemaphore.d.ts.map +1 -1
- package/dist/TxSemaphore.js +7 -7
- package/dist/TxSemaphore.js.map +1 -1
- package/dist/TxSubscriptionRef.d.ts +508 -0
- package/dist/TxSubscriptionRef.d.ts.map +1 -0
- package/dist/TxSubscriptionRef.js +293 -0
- package/dist/TxSubscriptionRef.js.map +1 -0
- package/dist/index.d.ts +40 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +40 -0
- package/dist/index.js.map +1 -1
- package/dist/internal/effect.js +99 -42
- package/dist/internal/effect.js.map +1 -1
- package/dist/internal/hashMap.js +3 -2
- package/dist/internal/hashMap.js.map +1 -1
- package/dist/internal/trie.js +5 -4
- package/dist/internal/trie.js.map +1 -1
- package/dist/unstable/ai/Tool.d.ts.map +1 -1
- package/dist/unstable/ai/Tool.js +0 -9
- package/dist/unstable/ai/Tool.js.map +1 -1
- package/dist/unstable/cli/Command.d.ts +1 -1
- package/dist/unstable/cli/Command.d.ts.map +1 -1
- package/dist/unstable/cli/Command.js +1 -1
- package/dist/unstable/cli/Command.js.map +1 -1
- package/dist/unstable/cluster/K8sHttpClient.js +4 -4
- package/dist/unstable/cluster/K8sHttpClient.js.map +1 -1
- package/dist/unstable/cluster/Sharding.js +1 -1
- package/dist/unstable/cluster/Sharding.js.map +1 -1
- package/dist/unstable/encoding/Sse.js +1 -1
- package/dist/unstable/encoding/Sse.js.map +1 -1
- package/dist/unstable/rpc/RpcServer.d.ts.map +1 -1
- package/dist/unstable/rpc/RpcServer.js +1 -2
- package/dist/unstable/rpc/RpcServer.js.map +1 -1
- package/dist/unstable/socket/Socket.d.ts.map +1 -1
- package/dist/unstable/socket/Socket.js +3 -3
- package/dist/unstable/socket/Socket.js.map +1 -1
- package/package.json +1 -1
- package/src/Array.ts +190 -342
- package/src/Cache.ts +6 -5
- package/src/Channel.ts +506 -102
- package/src/Chunk.ts +81 -268
- package/src/Effect.ts +437 -518
- package/src/Filter.ts +0 -57
- package/src/HashMap.ts +15 -14
- package/src/Iterable.ts +105 -50
- package/src/Option.ts +30 -20
- package/src/Pull.ts +1 -1
- package/src/Record.ts +43 -152
- package/src/Sink.ts +75 -23
- package/src/Stream.ts +442 -502
- package/src/Trie.ts +18 -17
- package/src/TxChunk.ts +72 -53
- package/src/TxDeferred.ts +394 -0
- package/src/TxHashMap.ts +332 -285
- package/src/TxHashSet.ts +111 -116
- package/src/TxPriorityQueue.ts +767 -0
- package/src/TxPubSub.ts +789 -0
- package/src/TxQueue.ts +241 -251
- package/src/TxReentrantLock.ts +753 -0
- package/src/TxRef.ts +50 -38
- package/src/TxSemaphore.ts +29 -32
- package/src/TxSubscriptionRef.ts +639 -0
- package/src/index.ts +45 -0
- package/src/internal/effect.ts +368 -163
- package/src/internal/hashMap.ts +7 -5
- package/src/internal/trie.ts +16 -9
- package/src/unstable/ai/Tool.ts +0 -9
- package/src/unstable/cli/Command.ts +6 -4
- package/src/unstable/cluster/K8sHttpClient.ts +4 -4
- package/src/unstable/cluster/Sharding.ts +1 -1
- package/src/unstable/encoding/Sse.ts +1 -1
- package/src/unstable/rpc/RpcServer.ts +1 -7
- package/src/unstable/socket/Socket.ts +9 -11
package/src/TxPubSub.ts
ADDED
|
@@ -0,0 +1,789 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TxPubSub is a transactional publish/subscribe hub that provides Software Transactional Memory
|
|
3
|
+
* (STM) semantics for message broadcasting. Publishers broadcast messages to all current
|
|
4
|
+
* subscribers, with each subscriber receiving its own copy of every published message.
|
|
5
|
+
*
|
|
6
|
+
* Supports multiple queue strategies: bounded, unbounded, dropping, and sliding.
|
|
7
|
+
*
|
|
8
|
+
* @since 4.0.0
|
|
9
|
+
*/
|
|
10
|
+
import * as Effect from "./Effect.ts"
|
|
11
|
+
import { dual } from "./Function.ts"
|
|
12
|
+
import type { Inspectable } from "./Inspectable.ts"
|
|
13
|
+
import { NodeInspectSymbol, toJson } from "./Inspectable.ts"
|
|
14
|
+
import type { Pipeable } from "./Pipeable.ts"
|
|
15
|
+
import { pipeArguments } from "./Pipeable.ts"
|
|
16
|
+
import { hasProperty } from "./Predicate.ts"
|
|
17
|
+
import type * as Scope from "./Scope.ts"
|
|
18
|
+
import * as TxQueue from "./TxQueue.ts"
|
|
19
|
+
import * as TxRef from "./TxRef.ts"
|
|
20
|
+
|
|
21
|
+
const TypeId = "~effect/transactions/TxPubSub"
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* A TxPubSub represents a transactional publish/subscribe hub that broadcasts messages
|
|
25
|
+
* to all current subscribers using Software Transactional Memory (STM) semantics.
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```ts
|
|
29
|
+
* import { Effect, TxPubSub, TxQueue } from "effect"
|
|
30
|
+
*
|
|
31
|
+
* const program = Effect.gen(function*() {
|
|
32
|
+
* const hub = yield* TxPubSub.unbounded<string>()
|
|
33
|
+
*
|
|
34
|
+
* yield* Effect.scoped(
|
|
35
|
+
* Effect.gen(function*() {
|
|
36
|
+
* const sub = yield* TxPubSub.subscribe(hub)
|
|
37
|
+
* yield* TxPubSub.publish(hub, "hello")
|
|
38
|
+
* const msg = yield* TxQueue.take(sub)
|
|
39
|
+
* console.log(msg) // "hello"
|
|
40
|
+
* })
|
|
41
|
+
* )
|
|
42
|
+
* })
|
|
43
|
+
* ```
|
|
44
|
+
*
|
|
45
|
+
* @since 4.0.0
|
|
46
|
+
* @category models
|
|
47
|
+
*/
|
|
48
|
+
export interface TxPubSub<in out A> extends Inspectable, Pipeable {
|
|
49
|
+
readonly [TypeId]: typeof TypeId
|
|
50
|
+
/** @internal */
|
|
51
|
+
readonly subscribersRef: TxRef.TxRef<Array<TxQueue.TxQueue<A>>>
|
|
52
|
+
/** @internal */
|
|
53
|
+
readonly shutdownRef: TxRef.TxRef<boolean>
|
|
54
|
+
readonly strategy: "bounded" | "unbounded" | "dropping" | "sliding"
|
|
55
|
+
readonly capacity: number
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const TxPubSubProto: Omit<TxPubSub<any>, typeof TypeId | "subscribersRef" | "shutdownRef" | "strategy" | "capacity"> = {
|
|
59
|
+
[NodeInspectSymbol](this: TxPubSub<unknown>) {
|
|
60
|
+
return toJson(this)
|
|
61
|
+
},
|
|
62
|
+
toJSON(this: TxPubSub<unknown>) {
|
|
63
|
+
return {
|
|
64
|
+
_id: "TxPubSub",
|
|
65
|
+
strategy: this.strategy,
|
|
66
|
+
capacity: this.capacity
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
toString(this: TxPubSub<unknown>) {
|
|
70
|
+
return `TxPubSub(${this.strategy}, ${this.capacity})`
|
|
71
|
+
},
|
|
72
|
+
pipe() {
|
|
73
|
+
return pipeArguments(this, arguments)
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const makeTxPubSub = <A>(
|
|
78
|
+
subscribersRef: TxRef.TxRef<Array<TxQueue.TxQueue<A>>>,
|
|
79
|
+
shutdownRef: TxRef.TxRef<boolean>,
|
|
80
|
+
strategy: "bounded" | "unbounded" | "dropping" | "sliding",
|
|
81
|
+
cap: number
|
|
82
|
+
): TxPubSub<A> => {
|
|
83
|
+
const self = Object.create(TxPubSubProto)
|
|
84
|
+
self[TypeId] = TypeId
|
|
85
|
+
self.subscribersRef = subscribersRef
|
|
86
|
+
self.shutdownRef = shutdownRef
|
|
87
|
+
self.strategy = strategy
|
|
88
|
+
self.capacity = cap
|
|
89
|
+
return self
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// =============================================================================
|
|
93
|
+
// Constructors
|
|
94
|
+
// =============================================================================
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Creates a bounded TxPubSub with the specified capacity. When a subscriber's
|
|
98
|
+
* queue is full, the publisher will retry the transaction until space is available.
|
|
99
|
+
*
|
|
100
|
+
* @example
|
|
101
|
+
* ```ts
|
|
102
|
+
* import { Effect, TxPubSub, TxQueue } from "effect"
|
|
103
|
+
*
|
|
104
|
+
* const program = Effect.gen(function*() {
|
|
105
|
+
* const hub = yield* TxPubSub.bounded<number>(16)
|
|
106
|
+
*
|
|
107
|
+
* yield* Effect.scoped(
|
|
108
|
+
* Effect.gen(function*() {
|
|
109
|
+
* const sub = yield* TxPubSub.subscribe(hub)
|
|
110
|
+
* yield* TxPubSub.publish(hub, 42)
|
|
111
|
+
* const value = yield* TxQueue.take(sub)
|
|
112
|
+
* console.log(value) // 42
|
|
113
|
+
* })
|
|
114
|
+
* )
|
|
115
|
+
* })
|
|
116
|
+
* ```
|
|
117
|
+
*
|
|
118
|
+
* @since 4.0.0
|
|
119
|
+
* @category constructors
|
|
120
|
+
*/
|
|
121
|
+
export const bounded = <A = never>(capacity: number): Effect.Effect<TxPubSub<A>, never, Effect.Transaction> =>
|
|
122
|
+
Effect.gen(function*() {
|
|
123
|
+
const subscribersRef = yield* TxRef.make<Array<TxQueue.TxQueue<A>>>([])
|
|
124
|
+
const shutdownRef = yield* TxRef.make(false)
|
|
125
|
+
return makeTxPubSub(subscribersRef, shutdownRef, "bounded", capacity)
|
|
126
|
+
})
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Creates a dropping TxPubSub with the specified capacity. When a subscriber's
|
|
130
|
+
* queue is full, the message is dropped for that subscriber.
|
|
131
|
+
*
|
|
132
|
+
* @example
|
|
133
|
+
* ```ts
|
|
134
|
+
* import { Effect, TxPubSub, TxQueue } from "effect"
|
|
135
|
+
*
|
|
136
|
+
* const program = Effect.gen(function*() {
|
|
137
|
+
* const hub = yield* TxPubSub.dropping<number>(2)
|
|
138
|
+
*
|
|
139
|
+
* yield* Effect.scoped(
|
|
140
|
+
* Effect.gen(function*() {
|
|
141
|
+
* const sub = yield* TxPubSub.subscribe(hub)
|
|
142
|
+
* yield* TxPubSub.publish(hub, 1)
|
|
143
|
+
* yield* TxPubSub.publish(hub, 2)
|
|
144
|
+
* yield* TxPubSub.publish(hub, 3) // dropped
|
|
145
|
+
* const v1 = yield* TxQueue.take(sub)
|
|
146
|
+
* const v2 = yield* TxQueue.take(sub)
|
|
147
|
+
* console.log(v1, v2) // 1 2
|
|
148
|
+
* })
|
|
149
|
+
* )
|
|
150
|
+
* })
|
|
151
|
+
* ```
|
|
152
|
+
*
|
|
153
|
+
* @since 4.0.0
|
|
154
|
+
* @category constructors
|
|
155
|
+
*/
|
|
156
|
+
export const dropping = <A = never>(capacity: number): Effect.Effect<TxPubSub<A>, never, Effect.Transaction> =>
|
|
157
|
+
Effect.gen(function*() {
|
|
158
|
+
const subscribersRef = yield* TxRef.make<Array<TxQueue.TxQueue<A>>>([])
|
|
159
|
+
const shutdownRef = yield* TxRef.make(false)
|
|
160
|
+
return makeTxPubSub(subscribersRef, shutdownRef, "dropping", capacity)
|
|
161
|
+
})
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Creates a sliding TxPubSub with the specified capacity. When a subscriber's
|
|
165
|
+
* queue is full, the oldest message in that subscriber's queue is dropped.
|
|
166
|
+
*
|
|
167
|
+
* @example
|
|
168
|
+
* ```ts
|
|
169
|
+
* import { Effect, TxPubSub, TxQueue } from "effect"
|
|
170
|
+
*
|
|
171
|
+
* const program = Effect.gen(function*() {
|
|
172
|
+
* const hub = yield* TxPubSub.sliding<number>(2)
|
|
173
|
+
*
|
|
174
|
+
* yield* Effect.scoped(
|
|
175
|
+
* Effect.gen(function*() {
|
|
176
|
+
* const sub = yield* TxPubSub.subscribe(hub)
|
|
177
|
+
* yield* TxPubSub.publish(hub, 1)
|
|
178
|
+
* yield* TxPubSub.publish(hub, 2)
|
|
179
|
+
* yield* TxPubSub.publish(hub, 3) // evicts 1
|
|
180
|
+
* const v1 = yield* TxQueue.take(sub)
|
|
181
|
+
* console.log(v1) // 2
|
|
182
|
+
* })
|
|
183
|
+
* )
|
|
184
|
+
* })
|
|
185
|
+
* ```
|
|
186
|
+
*
|
|
187
|
+
* @since 4.0.0
|
|
188
|
+
* @category constructors
|
|
189
|
+
*/
|
|
190
|
+
export const sliding = <A = never>(capacity: number): Effect.Effect<TxPubSub<A>, never, Effect.Transaction> =>
|
|
191
|
+
Effect.gen(function*() {
|
|
192
|
+
const subscribersRef = yield* TxRef.make<Array<TxQueue.TxQueue<A>>>([])
|
|
193
|
+
const shutdownRef = yield* TxRef.make(false)
|
|
194
|
+
return makeTxPubSub(subscribersRef, shutdownRef, "sliding", capacity)
|
|
195
|
+
})
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Creates an unbounded TxPubSub with unlimited capacity. Messages are always accepted.
|
|
199
|
+
*
|
|
200
|
+
* @example
|
|
201
|
+
* ```ts
|
|
202
|
+
* import { Effect, TxPubSub, TxQueue } from "effect"
|
|
203
|
+
*
|
|
204
|
+
* const program = Effect.gen(function*() {
|
|
205
|
+
* const hub = yield* TxPubSub.unbounded<string>()
|
|
206
|
+
*
|
|
207
|
+
* yield* Effect.scoped(
|
|
208
|
+
* Effect.gen(function*() {
|
|
209
|
+
* const sub = yield* TxPubSub.subscribe(hub)
|
|
210
|
+
* yield* TxPubSub.publish(hub, "msg")
|
|
211
|
+
* const msg = yield* TxQueue.take(sub)
|
|
212
|
+
* console.log(msg) // "msg"
|
|
213
|
+
* })
|
|
214
|
+
* )
|
|
215
|
+
* })
|
|
216
|
+
* ```
|
|
217
|
+
*
|
|
218
|
+
* @since 4.0.0
|
|
219
|
+
* @category constructors
|
|
220
|
+
*/
|
|
221
|
+
export const unbounded = <A = never>(): Effect.Effect<TxPubSub<A>, never, Effect.Transaction> =>
|
|
222
|
+
Effect.gen(function*() {
|
|
223
|
+
const subscribersRef = yield* TxRef.make<Array<TxQueue.TxQueue<A>>>([])
|
|
224
|
+
const shutdownRef = yield* TxRef.make(false)
|
|
225
|
+
return makeTxPubSub(subscribersRef, shutdownRef, "unbounded", Number.POSITIVE_INFINITY)
|
|
226
|
+
})
|
|
227
|
+
|
|
228
|
+
// =============================================================================
|
|
229
|
+
// Getters
|
|
230
|
+
// =============================================================================
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Returns the capacity of the TxPubSub.
|
|
234
|
+
*
|
|
235
|
+
* @example
|
|
236
|
+
* ```ts
|
|
237
|
+
* import { Effect, TxPubSub } from "effect"
|
|
238
|
+
*
|
|
239
|
+
* const program = Effect.gen(function*() {
|
|
240
|
+
* const hub = yield* TxPubSub.bounded<number>(16)
|
|
241
|
+
* console.log(TxPubSub.capacity(hub)) // 16
|
|
242
|
+
* })
|
|
243
|
+
* ```
|
|
244
|
+
*
|
|
245
|
+
* @since 4.0.0
|
|
246
|
+
* @category getters
|
|
247
|
+
*/
|
|
248
|
+
export const capacity = <A>(self: TxPubSub<A>): number => self.capacity
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Returns the current number of messages across all subscriber queues (the max).
|
|
252
|
+
*
|
|
253
|
+
* @example
|
|
254
|
+
* ```ts
|
|
255
|
+
* import { Effect, TxPubSub, TxQueue } from "effect"
|
|
256
|
+
*
|
|
257
|
+
* const program = Effect.gen(function*() {
|
|
258
|
+
* const hub = yield* TxPubSub.unbounded<number>()
|
|
259
|
+
*
|
|
260
|
+
* yield* Effect.scoped(
|
|
261
|
+
* Effect.gen(function*() {
|
|
262
|
+
* const sub = yield* TxPubSub.subscribe(hub)
|
|
263
|
+
* yield* TxPubSub.publish(hub, 1)
|
|
264
|
+
* yield* TxPubSub.publish(hub, 2)
|
|
265
|
+
* const s = yield* TxPubSub.size(hub)
|
|
266
|
+
* console.log(s) // 2
|
|
267
|
+
* })
|
|
268
|
+
* )
|
|
269
|
+
* })
|
|
270
|
+
* ```
|
|
271
|
+
*
|
|
272
|
+
* @since 4.0.0
|
|
273
|
+
* @category getters
|
|
274
|
+
*/
|
|
275
|
+
export const size = <A>(self: TxPubSub<A>): Effect.Effect<number, never, Effect.Transaction> =>
|
|
276
|
+
Effect.gen(function*() {
|
|
277
|
+
const subscribers = yield* TxRef.get(self.subscribersRef)
|
|
278
|
+
let maxSize = 0
|
|
279
|
+
for (const queue of subscribers) {
|
|
280
|
+
const s = yield* TxQueue.size(queue)
|
|
281
|
+
if (s > maxSize) maxSize = s
|
|
282
|
+
}
|
|
283
|
+
return maxSize
|
|
284
|
+
})
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* Checks if the TxPubSub has no pending messages (all subscriber queues are empty).
|
|
288
|
+
*
|
|
289
|
+
* @example
|
|
290
|
+
* ```ts
|
|
291
|
+
* import { Effect, TxPubSub } from "effect"
|
|
292
|
+
*
|
|
293
|
+
* const program = Effect.gen(function*() {
|
|
294
|
+
* const hub = yield* TxPubSub.unbounded<number>()
|
|
295
|
+
* const empty = yield* TxPubSub.isEmpty(hub)
|
|
296
|
+
* console.log(empty) // true
|
|
297
|
+
* })
|
|
298
|
+
* ```
|
|
299
|
+
*
|
|
300
|
+
* @since 4.0.0
|
|
301
|
+
* @category getters
|
|
302
|
+
*/
|
|
303
|
+
export const isEmpty = <A>(self: TxPubSub<A>): Effect.Effect<boolean, never, Effect.Transaction> =>
|
|
304
|
+
Effect.map(size(self), (s) => s === 0)
|
|
305
|
+
|
|
306
|
+
/**
|
|
307
|
+
* Checks if any subscriber queue is at capacity.
|
|
308
|
+
*
|
|
309
|
+
* @example
|
|
310
|
+
* ```ts
|
|
311
|
+
* import { Effect, TxPubSub } from "effect"
|
|
312
|
+
*
|
|
313
|
+
* const program = Effect.gen(function*() {
|
|
314
|
+
* const hub = yield* TxPubSub.bounded<number>(2)
|
|
315
|
+
* const full = yield* TxPubSub.isFull(hub)
|
|
316
|
+
* console.log(full) // false
|
|
317
|
+
* })
|
|
318
|
+
* ```
|
|
319
|
+
*
|
|
320
|
+
* @since 4.0.0
|
|
321
|
+
* @category getters
|
|
322
|
+
*/
|
|
323
|
+
export const isFull = <A>(self: TxPubSub<A>): Effect.Effect<boolean, never, Effect.Transaction> =>
|
|
324
|
+
Effect.gen(function*() {
|
|
325
|
+
if (self.capacity === Number.POSITIVE_INFINITY) return false
|
|
326
|
+
const subscribers = yield* TxRef.get(self.subscribersRef)
|
|
327
|
+
for (const queue of subscribers) {
|
|
328
|
+
if (yield* TxQueue.isFull(queue)) return true
|
|
329
|
+
}
|
|
330
|
+
return false
|
|
331
|
+
})
|
|
332
|
+
|
|
333
|
+
/**
|
|
334
|
+
* Checks if the TxPubSub has been shut down.
|
|
335
|
+
*
|
|
336
|
+
* @example
|
|
337
|
+
* ```ts
|
|
338
|
+
* import { Effect, TxPubSub } from "effect"
|
|
339
|
+
*
|
|
340
|
+
* const program = Effect.gen(function*() {
|
|
341
|
+
* const hub = yield* TxPubSub.unbounded<number>()
|
|
342
|
+
* console.log(yield* TxPubSub.isShutdown(hub)) // false
|
|
343
|
+
* yield* TxPubSub.shutdown(hub)
|
|
344
|
+
* console.log(yield* TxPubSub.isShutdown(hub)) // true
|
|
345
|
+
* })
|
|
346
|
+
* ```
|
|
347
|
+
*
|
|
348
|
+
* @since 4.0.0
|
|
349
|
+
* @category getters
|
|
350
|
+
*/
|
|
351
|
+
export const isShutdown = <A>(self: TxPubSub<A>): Effect.Effect<boolean, never, Effect.Transaction> =>
|
|
352
|
+
TxRef.get(self.shutdownRef)
|
|
353
|
+
|
|
354
|
+
// =============================================================================
|
|
355
|
+
// Mutations
|
|
356
|
+
// =============================================================================
|
|
357
|
+
|
|
358
|
+
/**
|
|
359
|
+
* Publishes a message to all current subscribers.
|
|
360
|
+
*
|
|
361
|
+
* Returns `true` if the message was delivered to all subscribers, or `false` if
|
|
362
|
+
* the hub is shut down or the message was dropped for any subscriber (dropping strategy).
|
|
363
|
+
*
|
|
364
|
+
* For bounded strategy, retries the transaction if any subscriber queue is full.
|
|
365
|
+
* For sliding strategy, drops oldest messages in full subscriber queues.
|
|
366
|
+
* For dropping strategy, drops the message for full subscriber queues and returns `false`.
|
|
367
|
+
*
|
|
368
|
+
* @example
|
|
369
|
+
* ```ts
|
|
370
|
+
* import { Effect, TxPubSub, TxQueue } from "effect"
|
|
371
|
+
*
|
|
372
|
+
* const program = Effect.gen(function*() {
|
|
373
|
+
* const hub = yield* TxPubSub.unbounded<string>()
|
|
374
|
+
*
|
|
375
|
+
* // No subscribers - publish is a no-op
|
|
376
|
+
* const r1 = yield* TxPubSub.publish(hub, "no one listening")
|
|
377
|
+
* console.log(r1) // true
|
|
378
|
+
*
|
|
379
|
+
* yield* Effect.scoped(
|
|
380
|
+
* Effect.gen(function*() {
|
|
381
|
+
* const sub = yield* TxPubSub.subscribe(hub)
|
|
382
|
+
* yield* TxPubSub.publish(hub, "hello")
|
|
383
|
+
* const msg = yield* TxQueue.take(sub)
|
|
384
|
+
* console.log(msg) // "hello"
|
|
385
|
+
* })
|
|
386
|
+
* )
|
|
387
|
+
* })
|
|
388
|
+
* ```
|
|
389
|
+
*
|
|
390
|
+
* @since 4.0.0
|
|
391
|
+
* @category mutations
|
|
392
|
+
*/
|
|
393
|
+
export const publish: {
|
|
394
|
+
// =============================================================================
|
|
395
|
+
// Mutations
|
|
396
|
+
// =============================================================================
|
|
397
|
+
|
|
398
|
+
/**
|
|
399
|
+
* Publishes a message to all current subscribers.
|
|
400
|
+
*
|
|
401
|
+
* Returns `true` if the message was delivered to all subscribers, or `false` if
|
|
402
|
+
* the hub is shut down or the message was dropped for any subscriber (dropping strategy).
|
|
403
|
+
*
|
|
404
|
+
* For bounded strategy, retries the transaction if any subscriber queue is full.
|
|
405
|
+
* For sliding strategy, drops oldest messages in full subscriber queues.
|
|
406
|
+
* For dropping strategy, drops the message for full subscriber queues and returns `false`.
|
|
407
|
+
*
|
|
408
|
+
* @example
|
|
409
|
+
* ```ts
|
|
410
|
+
* import { Effect, TxPubSub, TxQueue } from "effect"
|
|
411
|
+
*
|
|
412
|
+
* const program = Effect.gen(function*() {
|
|
413
|
+
* const hub = yield* TxPubSub.unbounded<string>()
|
|
414
|
+
*
|
|
415
|
+
* // No subscribers - publish is a no-op
|
|
416
|
+
* const r1 = yield* TxPubSub.publish(hub, "no one listening")
|
|
417
|
+
* console.log(r1) // true
|
|
418
|
+
*
|
|
419
|
+
* yield* Effect.scoped(
|
|
420
|
+
* Effect.gen(function*() {
|
|
421
|
+
* const sub = yield* TxPubSub.subscribe(hub)
|
|
422
|
+
* yield* TxPubSub.publish(hub, "hello")
|
|
423
|
+
* const msg = yield* TxQueue.take(sub)
|
|
424
|
+
* console.log(msg) // "hello"
|
|
425
|
+
* })
|
|
426
|
+
* )
|
|
427
|
+
* })
|
|
428
|
+
* ```
|
|
429
|
+
*
|
|
430
|
+
* @since 4.0.0
|
|
431
|
+
* @category mutations
|
|
432
|
+
*/
|
|
433
|
+
<A>(value: A): (self: TxPubSub<A>) => Effect.Effect<boolean>
|
|
434
|
+
// =============================================================================
|
|
435
|
+
// Mutations
|
|
436
|
+
// =============================================================================
|
|
437
|
+
|
|
438
|
+
/**
|
|
439
|
+
* Publishes a message to all current subscribers.
|
|
440
|
+
*
|
|
441
|
+
* Returns `true` if the message was delivered to all subscribers, or `false` if
|
|
442
|
+
* the hub is shut down or the message was dropped for any subscriber (dropping strategy).
|
|
443
|
+
*
|
|
444
|
+
* For bounded strategy, retries the transaction if any subscriber queue is full.
|
|
445
|
+
* For sliding strategy, drops oldest messages in full subscriber queues.
|
|
446
|
+
* For dropping strategy, drops the message for full subscriber queues and returns `false`.
|
|
447
|
+
*
|
|
448
|
+
* @example
|
|
449
|
+
* ```ts
|
|
450
|
+
* import { Effect, TxPubSub, TxQueue } from "effect"
|
|
451
|
+
*
|
|
452
|
+
* const program = Effect.gen(function*() {
|
|
453
|
+
* const hub = yield* TxPubSub.unbounded<string>()
|
|
454
|
+
*
|
|
455
|
+
* // No subscribers - publish is a no-op
|
|
456
|
+
* const r1 = yield* TxPubSub.publish(hub, "no one listening")
|
|
457
|
+
* console.log(r1) // true
|
|
458
|
+
*
|
|
459
|
+
* yield* Effect.scoped(
|
|
460
|
+
* Effect.gen(function*() {
|
|
461
|
+
* const sub = yield* TxPubSub.subscribe(hub)
|
|
462
|
+
* yield* TxPubSub.publish(hub, "hello")
|
|
463
|
+
* const msg = yield* TxQueue.take(sub)
|
|
464
|
+
* console.log(msg) // "hello"
|
|
465
|
+
* })
|
|
466
|
+
* )
|
|
467
|
+
* })
|
|
468
|
+
* ```
|
|
469
|
+
*
|
|
470
|
+
* @since 4.0.0
|
|
471
|
+
* @category mutations
|
|
472
|
+
*/
|
|
473
|
+
<A>(self: TxPubSub<A>, value: A): Effect.Effect<boolean>
|
|
474
|
+
} = dual(
|
|
475
|
+
2,
|
|
476
|
+
<A>(self: TxPubSub<A>, value: A): Effect.Effect<boolean, never, Effect.Transaction> =>
|
|
477
|
+
Effect.gen(function*() {
|
|
478
|
+
if (yield* TxRef.get(self.shutdownRef)) return false
|
|
479
|
+
|
|
480
|
+
const subscribers = yield* TxRef.get(self.subscribersRef)
|
|
481
|
+
let allAccepted = true
|
|
482
|
+
|
|
483
|
+
for (const queue of subscribers) {
|
|
484
|
+
const accepted = yield* TxQueue.offer(queue, value)
|
|
485
|
+
if (!accepted) allAccepted = false
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
return allAccepted
|
|
489
|
+
})
|
|
490
|
+
)
|
|
491
|
+
|
|
492
|
+
/**
|
|
493
|
+
* Publishes all messages from an iterable to all current subscribers.
|
|
494
|
+
*
|
|
495
|
+
* Returns `true` if all messages were delivered to all subscribers.
|
|
496
|
+
*
|
|
497
|
+
* @example
|
|
498
|
+
* ```ts
|
|
499
|
+
* import { Effect, TxPubSub, TxQueue } from "effect"
|
|
500
|
+
*
|
|
501
|
+
* const program = Effect.gen(function*() {
|
|
502
|
+
* const hub = yield* TxPubSub.unbounded<number>()
|
|
503
|
+
*
|
|
504
|
+
* yield* Effect.scoped(
|
|
505
|
+
* Effect.gen(function*() {
|
|
506
|
+
* const sub = yield* TxPubSub.subscribe(hub)
|
|
507
|
+
* yield* TxPubSub.publishAll(hub, [1, 2, 3])
|
|
508
|
+
* const v1 = yield* TxQueue.take(sub)
|
|
509
|
+
* const v2 = yield* TxQueue.take(sub)
|
|
510
|
+
* const v3 = yield* TxQueue.take(sub)
|
|
511
|
+
* console.log(v1, v2, v3) // 1 2 3
|
|
512
|
+
* })
|
|
513
|
+
* )
|
|
514
|
+
* })
|
|
515
|
+
* ```
|
|
516
|
+
*
|
|
517
|
+
* @since 4.0.0
|
|
518
|
+
* @category mutations
|
|
519
|
+
*/
|
|
520
|
+
export const publishAll: {
|
|
521
|
+
/**
|
|
522
|
+
* Publishes all messages from an iterable to all current subscribers.
|
|
523
|
+
*
|
|
524
|
+
* Returns `true` if all messages were delivered to all subscribers.
|
|
525
|
+
*
|
|
526
|
+
* @example
|
|
527
|
+
* ```ts
|
|
528
|
+
* import { Effect, TxPubSub, TxQueue } from "effect"
|
|
529
|
+
*
|
|
530
|
+
* const program = Effect.gen(function*() {
|
|
531
|
+
* const hub = yield* TxPubSub.unbounded<number>()
|
|
532
|
+
*
|
|
533
|
+
* yield* Effect.scoped(
|
|
534
|
+
* Effect.gen(function*() {
|
|
535
|
+
* const sub = yield* TxPubSub.subscribe(hub)
|
|
536
|
+
* yield* TxPubSub.publishAll(hub, [1, 2, 3])
|
|
537
|
+
* const v1 = yield* TxQueue.take(sub)
|
|
538
|
+
* const v2 = yield* TxQueue.take(sub)
|
|
539
|
+
* const v3 = yield* TxQueue.take(sub)
|
|
540
|
+
* console.log(v1, v2, v3) // 1 2 3
|
|
541
|
+
* })
|
|
542
|
+
* )
|
|
543
|
+
* })
|
|
544
|
+
* ```
|
|
545
|
+
*
|
|
546
|
+
* @since 4.0.0
|
|
547
|
+
* @category mutations
|
|
548
|
+
*/
|
|
549
|
+
<A>(values: Iterable<A>): (self: TxPubSub<A>) => Effect.Effect<boolean>
|
|
550
|
+
/**
|
|
551
|
+
* Publishes all messages from an iterable to all current subscribers.
|
|
552
|
+
*
|
|
553
|
+
* Returns `true` if all messages were delivered to all subscribers.
|
|
554
|
+
*
|
|
555
|
+
* @example
|
|
556
|
+
* ```ts
|
|
557
|
+
* import { Effect, TxPubSub, TxQueue } from "effect"
|
|
558
|
+
*
|
|
559
|
+
* const program = Effect.gen(function*() {
|
|
560
|
+
* const hub = yield* TxPubSub.unbounded<number>()
|
|
561
|
+
*
|
|
562
|
+
* yield* Effect.scoped(
|
|
563
|
+
* Effect.gen(function*() {
|
|
564
|
+
* const sub = yield* TxPubSub.subscribe(hub)
|
|
565
|
+
* yield* TxPubSub.publishAll(hub, [1, 2, 3])
|
|
566
|
+
* const v1 = yield* TxQueue.take(sub)
|
|
567
|
+
* const v2 = yield* TxQueue.take(sub)
|
|
568
|
+
* const v3 = yield* TxQueue.take(sub)
|
|
569
|
+
* console.log(v1, v2, v3) // 1 2 3
|
|
570
|
+
* })
|
|
571
|
+
* )
|
|
572
|
+
* })
|
|
573
|
+
* ```
|
|
574
|
+
*
|
|
575
|
+
* @since 4.0.0
|
|
576
|
+
* @category mutations
|
|
577
|
+
*/
|
|
578
|
+
<A>(self: TxPubSub<A>, values: Iterable<A>): Effect.Effect<boolean>
|
|
579
|
+
} = dual(
|
|
580
|
+
2,
|
|
581
|
+
<A>(self: TxPubSub<A>, values: Iterable<A>): Effect.Effect<boolean, never, Effect.Transaction> =>
|
|
582
|
+
Effect.gen(function*() {
|
|
583
|
+
if (yield* TxRef.get(self.shutdownRef)) return false
|
|
584
|
+
|
|
585
|
+
let allAccepted = true
|
|
586
|
+
for (const value of values) {
|
|
587
|
+
const accepted = yield* publish(self, value)
|
|
588
|
+
if (!accepted) allAccepted = false
|
|
589
|
+
}
|
|
590
|
+
return allAccepted
|
|
591
|
+
})
|
|
592
|
+
)
|
|
593
|
+
|
|
594
|
+
/**
|
|
595
|
+
* Subscribes to the TxPubSub, returning a TxQueue that receives all messages
|
|
596
|
+
* published after subscription. The subscription is automatically removed when
|
|
597
|
+
* the scope is closed.
|
|
598
|
+
*
|
|
599
|
+
* @example
|
|
600
|
+
* ```ts
|
|
601
|
+
* import { Effect, TxPubSub, TxQueue } from "effect"
|
|
602
|
+
*
|
|
603
|
+
* const program = Effect.gen(function*() {
|
|
604
|
+
* const hub = yield* TxPubSub.unbounded<string>()
|
|
605
|
+
*
|
|
606
|
+
* yield* Effect.scoped(
|
|
607
|
+
* Effect.gen(function*() {
|
|
608
|
+
* const sub1 = yield* TxPubSub.subscribe(hub)
|
|
609
|
+
* const sub2 = yield* TxPubSub.subscribe(hub)
|
|
610
|
+
*
|
|
611
|
+
* yield* TxPubSub.publish(hub, "broadcast")
|
|
612
|
+
*
|
|
613
|
+
* const msg1 = yield* TxQueue.take(sub1)
|
|
614
|
+
* const msg2 = yield* TxQueue.take(sub2)
|
|
615
|
+
* console.log(msg1, msg2) // "broadcast" "broadcast"
|
|
616
|
+
* })
|
|
617
|
+
* )
|
|
618
|
+
* })
|
|
619
|
+
* ```
|
|
620
|
+
*
|
|
621
|
+
* @since 4.0.0
|
|
622
|
+
* @category mutations
|
|
623
|
+
*/
|
|
624
|
+
export const subscribe = <A>(self: TxPubSub<A>): Effect.Effect<TxQueue.TxQueue<A>, never, Scope.Scope> =>
|
|
625
|
+
Effect.acquireRelease(
|
|
626
|
+
Effect.transaction(acquireSubscriber(self)),
|
|
627
|
+
(queue) => Effect.transaction(releaseSubscriber(self, queue))
|
|
628
|
+
)
|
|
629
|
+
|
|
630
|
+
/**
|
|
631
|
+
* Creates a subscriber queue and registers it with the pub/sub.
|
|
632
|
+
*
|
|
633
|
+
* This is the transactional acquire step of `subscribe`, exposed so that
|
|
634
|
+
* callers can compose it with other Tx operations in a single transaction
|
|
635
|
+
* (e.g. `TxSubscriptionRef.changes`).
|
|
636
|
+
*
|
|
637
|
+
* @since 4.0.0
|
|
638
|
+
* @category mutations
|
|
639
|
+
*/
|
|
640
|
+
export const acquireSubscriber = <A>(
|
|
641
|
+
self: TxPubSub<A>
|
|
642
|
+
): Effect.Effect<TxQueue.TxQueue<A>, never, Effect.Transaction> =>
|
|
643
|
+
Effect.gen(function*() {
|
|
644
|
+
const queue = yield* makeSubscriberQueue<A>(self.strategy, self.capacity)
|
|
645
|
+
yield* TxRef.update(self.subscribersRef, (subs) => [...subs, queue])
|
|
646
|
+
return queue
|
|
647
|
+
})
|
|
648
|
+
|
|
649
|
+
/**
|
|
650
|
+
* Removes a subscriber queue from the pub/sub and shuts it down.
|
|
651
|
+
*
|
|
652
|
+
* This is the transactional release step of `subscribe`, exposed so that
|
|
653
|
+
* callers can compose it with other Tx operations in a single transaction.
|
|
654
|
+
*
|
|
655
|
+
* @since 4.0.0
|
|
656
|
+
* @category mutations
|
|
657
|
+
*/
|
|
658
|
+
export const releaseSubscriber: {
|
|
659
|
+
/**
|
|
660
|
+
* Removes a subscriber queue from the pub/sub and shuts it down.
|
|
661
|
+
*
|
|
662
|
+
* This is the transactional release step of `subscribe`, exposed so that
|
|
663
|
+
* callers can compose it with other Tx operations in a single transaction.
|
|
664
|
+
*
|
|
665
|
+
* @since 4.0.0
|
|
666
|
+
* @category mutations
|
|
667
|
+
*/
|
|
668
|
+
<A>(queue: TxQueue.TxQueue<A>): (self: TxPubSub<A>) => Effect.Effect<void, never, Effect.Transaction>
|
|
669
|
+
/**
|
|
670
|
+
* Removes a subscriber queue from the pub/sub and shuts it down.
|
|
671
|
+
*
|
|
672
|
+
* This is the transactional release step of `subscribe`, exposed so that
|
|
673
|
+
* callers can compose it with other Tx operations in a single transaction.
|
|
674
|
+
*
|
|
675
|
+
* @since 4.0.0
|
|
676
|
+
* @category mutations
|
|
677
|
+
*/
|
|
678
|
+
<A>(self: TxPubSub<A>, queue: TxQueue.TxQueue<A>): Effect.Effect<void, never, Effect.Transaction>
|
|
679
|
+
} = dual(
|
|
680
|
+
2,
|
|
681
|
+
<A>(
|
|
682
|
+
self: TxPubSub<A>,
|
|
683
|
+
queue: TxQueue.TxQueue<A>
|
|
684
|
+
): Effect.Effect<void, never, Effect.Transaction> =>
|
|
685
|
+
Effect.gen(function*() {
|
|
686
|
+
yield* TxRef.update(self.subscribersRef, (subs) => subs.filter((q) => q !== queue))
|
|
687
|
+
yield* TxQueue.shutdown(queue)
|
|
688
|
+
})
|
|
689
|
+
)
|
|
690
|
+
|
|
691
|
+
const makeSubscriberQueue = <A>(
|
|
692
|
+
strategy: "bounded" | "unbounded" | "dropping" | "sliding",
|
|
693
|
+
cap: number
|
|
694
|
+
): Effect.Effect<TxQueue.TxQueue<A>, never, Effect.Transaction> => {
|
|
695
|
+
switch (strategy) {
|
|
696
|
+
case "bounded":
|
|
697
|
+
return TxQueue.bounded<A>(cap)
|
|
698
|
+
case "dropping":
|
|
699
|
+
return TxQueue.dropping<A>(cap)
|
|
700
|
+
case "sliding":
|
|
701
|
+
return TxQueue.sliding<A>(cap)
|
|
702
|
+
case "unbounded":
|
|
703
|
+
return TxQueue.unbounded<A>()
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
/**
|
|
708
|
+
* Shuts down the TxPubSub and all subscriber queues. Subsequent publish operations
|
|
709
|
+
* will return `false`. Subsequent subscribe operations will receive an already-shutdown queue.
|
|
710
|
+
*
|
|
711
|
+
* @example
|
|
712
|
+
* ```ts
|
|
713
|
+
* import { Effect, TxPubSub } from "effect"
|
|
714
|
+
*
|
|
715
|
+
* const program = Effect.gen(function*() {
|
|
716
|
+
* const hub = yield* TxPubSub.unbounded<number>()
|
|
717
|
+
* yield* TxPubSub.shutdown(hub)
|
|
718
|
+
*
|
|
719
|
+
* const shut = yield* TxPubSub.isShutdown(hub)
|
|
720
|
+
* console.log(shut) // true
|
|
721
|
+
*
|
|
722
|
+
* const accepted = yield* TxPubSub.publish(hub, 1)
|
|
723
|
+
* console.log(accepted) // false
|
|
724
|
+
* })
|
|
725
|
+
* ```
|
|
726
|
+
*
|
|
727
|
+
* @since 4.0.0
|
|
728
|
+
* @category mutations
|
|
729
|
+
*/
|
|
730
|
+
export const shutdown = <A>(self: TxPubSub<A>): Effect.Effect<void, never, Effect.Transaction> =>
|
|
731
|
+
Effect.gen(function*() {
|
|
732
|
+
const alreadyShutdown = yield* TxRef.get(self.shutdownRef)
|
|
733
|
+
if (alreadyShutdown) return
|
|
734
|
+
|
|
735
|
+
yield* TxRef.set(self.shutdownRef, true)
|
|
736
|
+
const subscribers = yield* TxRef.get(self.subscribersRef)
|
|
737
|
+
for (const queue of subscribers) {
|
|
738
|
+
yield* TxQueue.shutdown(queue)
|
|
739
|
+
}
|
|
740
|
+
})
|
|
741
|
+
|
|
742
|
+
/**
|
|
743
|
+
* Waits for the TxPubSub to be shut down.
|
|
744
|
+
*
|
|
745
|
+
* @example
|
|
746
|
+
* ```ts
|
|
747
|
+
* import { Effect, TxPubSub } from "effect"
|
|
748
|
+
*
|
|
749
|
+
* const program = Effect.gen(function*() {
|
|
750
|
+
* const hub = yield* TxPubSub.unbounded<number>()
|
|
751
|
+
*
|
|
752
|
+
* const fiber = yield* Effect.forkChild(TxPubSub.awaitShutdown(hub))
|
|
753
|
+
* yield* TxPubSub.shutdown(hub)
|
|
754
|
+
* yield* fiber.await
|
|
755
|
+
* })
|
|
756
|
+
* ```
|
|
757
|
+
*
|
|
758
|
+
* @since 4.0.0
|
|
759
|
+
* @category mutations
|
|
760
|
+
*/
|
|
761
|
+
export const awaitShutdown = <A>(self: TxPubSub<A>): Effect.Effect<void, never, Effect.Transaction> =>
|
|
762
|
+
Effect.gen(function*() {
|
|
763
|
+
const shut = yield* TxRef.get(self.shutdownRef)
|
|
764
|
+
if (shut) return
|
|
765
|
+
return yield* Effect.retryTransaction
|
|
766
|
+
})
|
|
767
|
+
|
|
768
|
+
// =============================================================================
|
|
769
|
+
// Guards
|
|
770
|
+
// =============================================================================
|
|
771
|
+
|
|
772
|
+
/**
|
|
773
|
+
* Checks if the given value is a TxPubSub.
|
|
774
|
+
*
|
|
775
|
+
* @example
|
|
776
|
+
* ```ts
|
|
777
|
+
* import { TxPubSub } from "effect"
|
|
778
|
+
*
|
|
779
|
+
* declare const someValue: unknown
|
|
780
|
+
*
|
|
781
|
+
* if (TxPubSub.isTxPubSub(someValue)) {
|
|
782
|
+
* console.log("This is a TxPubSub")
|
|
783
|
+
* }
|
|
784
|
+
* ```
|
|
785
|
+
*
|
|
786
|
+
* @since 4.0.0
|
|
787
|
+
* @category guards
|
|
788
|
+
*/
|
|
789
|
+
export const isTxPubSub = (u: unknown): u is TxPubSub<unknown> => hasProperty(u, TypeId)
|