@@ -28,6 +28,7 @@ export interface AtomicPubSub<in out A> {
28
28
publishAll ( elements : Iterable < A > ) : Chunk . Chunk < A >
29
29
slide ( ) : void
30
30
subscribe ( ) : Subscription < A >
31
+ replayWindow ( ) : ReplayWindow < A >
31
32
}
32
33
33
34
/** @internal */
@@ -73,32 +74,49 @@ const removeSubscribers = <A>(
73
74
}
74
75
75
76
/** @internal */
76
- export const bounded = < A > ( requestedCapacity : number ) : Effect . Effect < PubSub . PubSub < A > > =>
77
- pipe (
78
- core . sync ( ( ) => makeBoundedPubSub < A > ( requestedCapacity ) ) ,
79
- core . flatMap ( ( atomicPubSub ) => makePubSub ( atomicPubSub , new BackPressureStrategy ( ) ) )
80
- )
77
+ export const bounded = < A > (
78
+ capacity : number | {
79
+ readonly capacity : number
80
+ readonly replay ?: number | undefined
81
+ }
82
+ ) : Effect . Effect < PubSub . PubSub < A > > =>
83
+ core . suspend ( ( ) => {
84
+ const pubsub = makeBoundedPubSub < A > ( capacity )
85
+ return makePubSub ( pubsub , new BackPressureStrategy ( ) )
86
+ } )
81
87
82
88
/** @internal */
83
- export const dropping = < A > ( requestedCapacity : number ) : Effect . Effect < PubSub . PubSub < A > > =>
84
- pipe (
85
- core . sync ( ( ) => makeBoundedPubSub < A > ( requestedCapacity ) ) ,
86
- core . flatMap ( ( atomicPubSub ) => makePubSub ( atomicPubSub , new DroppingStrategy ( ) ) )
87
- )
89
+ export const dropping = < A > (
90
+ capacity : number | {
91
+ readonly capacity : number
92
+ readonly replay ?: number | undefined
93
+ }
94
+ ) : Effect . Effect < PubSub . PubSub < A > > =>
95
+ core . suspend ( ( ) => {
96
+ const pubsub = makeBoundedPubSub < A > ( capacity )
97
+ return makePubSub ( pubsub , new DroppingStrategy ( ) )
98
+ } )
88
99
89
100
/** @internal */
90
- export const sliding = < A > ( requestedCapacity : number ) : Effect . Effect < PubSub . PubSub < A > > =>
91
- pipe (
92
- core . sync ( ( ) => makeBoundedPubSub < A > ( requestedCapacity ) ) ,
93
- core . flatMap ( ( atomicPubSub ) => makePubSub ( atomicPubSub , new SlidingStrategy ( ) ) )
94
- )
101
+ export const sliding = < A > (
102
+ capacity : number | {
103
+ readonly capacity : number
104
+ readonly replay ?: number | undefined
105
+ }
106
+ ) : Effect . Effect < PubSub . PubSub < A > > =>
107
+ core . suspend ( ( ) => {
108
+ const pubsub = makeBoundedPubSub < A > ( capacity )
109
+ return makePubSub ( pubsub , new SlidingStrategy ( ) )
110
+ } )
95
111
96
112
/** @internal */
97
- export const unbounded = < A > ( ) : Effect . Effect < PubSub . PubSub < A > > =>
98
- pipe (
99
- core . sync ( ( ) => makeUnboundedPubSub < A > ( ) ) ,
100
- core . flatMap ( ( atomicPubSub ) => makePubSub ( atomicPubSub , new DroppingStrategy ( ) ) )
101
- )
113
+ export const unbounded = < A > ( options ?: {
114
+ readonly replay ?: number | undefined
115
+ } ) : Effect . Effect < PubSub . PubSub < A > > =>
116
+ core . suspend ( ( ) => {
117
+ const pubsub = makeUnboundedPubSub < A > ( options )
118
+ return makePubSub ( pubsub , new DroppingStrategy ( ) )
119
+ } )
102
120
103
121
/** @internal */
104
122
export const capacity = < A > ( self : PubSub . PubSub < A > ) : number => self . capacity ( )
@@ -138,21 +156,28 @@ export const subscribe = <A>(self: PubSub.PubSub<A>): Effect.Effect<Queue.Dequeu
138
156
self . subscribe
139
157
140
158
/** @internal */
141
- const makeBoundedPubSub = < A > ( requestedCapacity : number ) : AtomicPubSub < A > => {
142
- ensureCapacity ( requestedCapacity )
143
- if ( requestedCapacity === 1 ) {
144
- return new BoundedPubSubSingle ( )
145
- } else if ( nextPow2 ( requestedCapacity ) === requestedCapacity ) {
146
- return new BoundedPubSubPow2 ( requestedCapacity )
159
+ const makeBoundedPubSub = < A > (
160
+ capacity : number | {
161
+ readonly capacity : number
162
+ readonly replay ?: number | undefined
163
+ }
164
+ ) : AtomicPubSub < A > => {
165
+ const options = typeof capacity === "number" ? { capacity } : capacity
166
+ ensureCapacity ( options . capacity )
167
+ const replayBuffer = options . replay && options . replay > 0 ? new ReplayBuffer < A > ( Math . ceil ( options . replay ) ) : undefined
168
+ if ( options . capacity === 1 ) {
169
+ return new BoundedPubSubSingle ( replayBuffer )
170
+ } else if ( nextPow2 ( options . capacity ) === options . capacity ) {
171
+ return new BoundedPubSubPow2 ( options . capacity , replayBuffer )
147
172
} else {
148
- return new BoundedPubSubArb ( requestedCapacity )
173
+ return new BoundedPubSubArb ( options . capacity , replayBuffer )
149
174
}
150
175
}
151
176
152
177
/** @internal */
153
- const makeUnboundedPubSub = < A > ( ) : AtomicPubSub < A > => {
154
- return new UnboundedPubSub ( )
155
- }
178
+ const makeUnboundedPubSub = < A > ( options ?: {
179
+ readonly replay ?: number | undefined
180
+ } ) : AtomicPubSub < A > => new UnboundedPubSub ( options ?. replay ? new ReplayBuffer ( options . replay ) : undefined )
156
181
157
182
/** @internal */
158
183
const makeSubscription = < A > (
@@ -180,17 +205,17 @@ export const unsafeMakeSubscription = <A>(
180
205
shutdownHook : Deferred . Deferred < void > ,
181
206
shutdownFlag : MutableRef . MutableRef < boolean > ,
182
207
strategy : PubSubStrategy < A >
183
- ) : Queue . Dequeue < A > => {
184
- return new SubscriptionImpl (
208
+ ) : Queue . Dequeue < A > =>
209
+ new SubscriptionImpl (
185
210
pubsub ,
186
211
subscribers ,
187
212
subscription ,
188
213
pollers ,
189
214
shutdownHook ,
190
215
shutdownFlag ,
191
- strategy
216
+ strategy ,
217
+ pubsub . replayWindow ( )
192
218
)
193
- }
194
219
195
220
/** @internal */
196
221
class BoundedPubSubArb < in out A > implements AtomicPubSub < A > {
@@ -200,12 +225,13 @@ class BoundedPubSubArb<in out A> implements AtomicPubSub<A> {
200
225
subscriberCount = 0
201
226
subscribersIndex = 0
202
227
203
- readonly capacity : number
228
+ constructor ( readonly capacity : number , readonly replayBuffer : ReplayBuffer < A > | undefined ) {
229
+ this . array = Array . from ( { length : capacity } )
230
+ this . subscribers = Array . from ( { length : capacity } )
231
+ }
204
232
205
- constructor ( requestedCapacity : number ) {
206
- this . array = Array . from ( { length : requestedCapacity } )
207
- this . subscribers = Array . from ( { length : requestedCapacity } )
208
- this . capacity = requestedCapacity
233
+ replayWindow ( ) : ReplayWindow < A > {
234
+ return this . replayBuffer ? new ReplayWindowImpl ( this . replayBuffer ) : emptyReplayWindow
209
235
}
210
236
211
237
isEmpty ( ) : boolean {
@@ -230,11 +256,17 @@ class BoundedPubSubArb<in out A> implements AtomicPubSub<A> {
230
256
this . subscribers [ index ] = this . subscriberCount
231
257
this . publisherIndex += 1
232
258
}
259
+ if ( this . replayBuffer ) {
260
+ this . replayBuffer . offer ( value )
261
+ }
233
262
return true
234
263
}
235
264
236
265
publishAll ( elements : Iterable < A > ) : Chunk . Chunk < A > {
237
266
if ( this . subscriberCount === 0 ) {
267
+ if ( this . replayBuffer ) {
268
+ this . replayBuffer . offerAll ( elements )
269
+ }
238
270
return Chunk . empty ( )
239
271
}
240
272
const chunk = Chunk . fromIterable ( elements )
@@ -253,6 +285,9 @@ class BoundedPubSubArb<in out A> implements AtomicPubSub<A> {
253
285
this . array [ index ] = a
254
286
this . subscribers [ index ] = this . subscriberCount
255
287
this . publisherIndex += 1
288
+ if ( this . replayBuffer ) {
289
+ this . replayBuffer . offer ( a )
290
+ }
256
291
}
257
292
return Chunk . drop ( chunk , iteratorIndex )
258
293
}
@@ -264,6 +299,9 @@ class BoundedPubSubArb<in out A> implements AtomicPubSub<A> {
264
299
this . subscribers [ index ] = 0
265
300
this . subscribersIndex += 1
266
301
}
302
+ if ( this . replayBuffer ) {
303
+ this . replayBuffer . slide ( )
304
+ }
267
305
}
268
306
269
307
subscribe ( ) : Subscription < A > {
@@ -368,13 +406,14 @@ class BoundedPubSubPow2<in out A> implements AtomicPubSub<A> {
368
406
subscriberCount = 0
369
407
subscribersIndex = 0
370
408
371
- readonly capacity : number
409
+ constructor ( readonly capacity : number , readonly replayBuffer : ReplayBuffer < A > | undefined ) {
410
+ this . array = Array . from ( { length : capacity } )
411
+ this . mask = capacity - 1
412
+ this . subscribers = Array . from ( { length : capacity } )
413
+ }
372
414
373
- constructor ( requestedCapacity : number ) {
374
- this . array = Array . from ( { length : requestedCapacity } )
375
- this . mask = requestedCapacity - 1
376
- this . subscribers = Array . from ( { length : requestedCapacity } )
377
- this . capacity = requestedCapacity
415
+ replayWindow ( ) : ReplayWindow < A > {
416
+ return this . replayBuffer ? new ReplayWindowImpl ( this . replayBuffer ) : emptyReplayWindow
378
417
}
379
418
380
419
isEmpty ( ) : boolean {
@@ -399,11 +438,17 @@ class BoundedPubSubPow2<in out A> implements AtomicPubSub<A> {
399
438
this . subscribers [ index ] = this . subscriberCount
400
439
this . publisherIndex += 1
401
440
}
441
+ if ( this . replayBuffer ) {
442
+ this . replayBuffer . offer ( value )
443
+ }
402
444
return true
403
445
}
404
446
405
447
publishAll ( elements : Iterable < A > ) : Chunk . Chunk < A > {
406
448
if ( this . subscriberCount === 0 ) {
449
+ if ( this . replayBuffer ) {
450
+ this . replayBuffer . offerAll ( elements )
451
+ }
407
452
return Chunk . empty ( )
408
453
}
409
454
const chunk = Chunk . fromIterable ( elements )
@@ -422,6 +467,9 @@ class BoundedPubSubPow2<in out A> implements AtomicPubSub<A> {
422
467
this . array [ index ] = elem
423
468
this . subscribers [ index ] = this . subscriberCount
424
469
this . publisherIndex += 1
470
+ if ( this . replayBuffer ) {
471
+ this . replayBuffer . offer ( elem )
472
+ }
425
473
}
426
474
return Chunk . drop ( chunk , iteratorIndex )
427
475
}
@@ -433,6 +481,9 @@ class BoundedPubSubPow2<in out A> implements AtomicPubSub<A> {
433
481
this . subscribers [ index ] = 0
434
482
this . subscribersIndex += 1
435
483
}
484
+ if ( this . replayBuffer ) {
485
+ this . replayBuffer . slide ( )
486
+ }
436
487
}
437
488
438
489
subscribe ( ) : Subscription < A > {
@@ -536,6 +587,11 @@ class BoundedPubSubSingle<in out A> implements AtomicPubSub<A> {
536
587
value : A = AbsentValue as unknown as A
537
588
538
589
readonly capacity = 1
590
+ constructor ( readonly replayBuffer : ReplayBuffer < A > | undefined ) { }
591
+
592
+ replayWindow ( ) : ReplayWindow < A > {
593
+ return this . replayBuffer ? new ReplayWindowImpl ( this . replayBuffer ) : emptyReplayWindow
594
+ }
539
595
540
596
pipe ( ) {
541
597
return pipeArguments ( this , arguments )
@@ -562,11 +618,17 @@ class BoundedPubSubSingle<in out A> implements AtomicPubSub<A> {
562
618
this . subscribers = this . subscriberCount
563
619
this . publisherIndex += 1
564
620
}
621
+ if ( this . replayBuffer ) {
622
+ this . replayBuffer . offer ( value )
623
+ }
565
624
return true
566
625
}
567
626
568
627
publishAll ( elements : Iterable < A > ) : Chunk . Chunk < A > {
569
628
if ( this . subscriberCount === 0 ) {
629
+ if ( this . replayBuffer ) {
630
+ this . replayBuffer . offerAll ( elements )
631
+ }
570
632
return Chunk . empty ( )
571
633
}
572
634
const chunk = Chunk . fromIterable ( elements )
@@ -585,6 +647,9 @@ class BoundedPubSubSingle<in out A> implements AtomicPubSub<A> {
585
647
this . subscribers = 0
586
648
this . value = AbsentValue as unknown as A
587
649
}
650
+ if ( this . replayBuffer ) {
651
+ this . replayBuffer . slide ( )
652
+ }
588
653
}
589
654
590
655
subscribe ( ) : Subscription < A > {
@@ -673,6 +738,11 @@ class UnboundedPubSub<in out A> implements AtomicPubSub<A> {
673
738
subscribersIndex = 0
674
739
675
740
readonly capacity = Number . MAX_SAFE_INTEGER
741
+ constructor ( readonly replayBuffer : ReplayBuffer < A > | undefined ) { }
742
+
743
+ replayWindow ( ) : ReplayWindow < A > {
744
+ return this . replayBuffer ? new ReplayWindowImpl ( this . replayBuffer ) : emptyReplayWindow
745
+ }
676
746
677
747
isEmpty ( ) : boolean {
678
748
return this . publisherHead === this . publisherTail
@@ -697,6 +767,9 @@ class UnboundedPubSub<in out A> implements AtomicPubSub<A> {
697
767
this . publisherTail = this . publisherTail . next
698
768
this . publisherIndex += 1
699
769
}
770
+ if ( this . replayBuffer ) {
771
+ this . replayBuffer . offer ( value )
772
+ }
700
773
return true
701
774
}
702
775
@@ -705,6 +778,8 @@ class UnboundedPubSub<in out A> implements AtomicPubSub<A> {
705
778
for ( const a of elements ) {
706
779
this . publish ( a )
707
780
}
781
+ } else if ( this . replayBuffer ) {
782
+ this . replayBuffer . offerAll ( elements )
708
783
}
709
784
return Chunk . empty ( )
710
785
}
@@ -715,6 +790,9 @@ class UnboundedPubSub<in out A> implements AtomicPubSub<A> {
715
790
this . publisherHead . value = AbsentValue
716
791
this . subscribersIndex += 1
717
792
}
793
+ if ( this . replayBuffer ) {
794
+ this . replayBuffer . slide ( )
795
+ }
718
796
}
719
797
720
798
subscribe ( ) : Subscription < A > {
@@ -841,9 +919,9 @@ class SubscriptionImpl<in out A> implements Queue.Dequeue<A> {
841
919
readonly pollers : MutableQueue . MutableQueue < Deferred . Deferred < A > > ,
842
920
readonly shutdownHook : Deferred . Deferred < void > ,
843
921
readonly shutdownFlag : MutableRef . MutableRef < boolean > ,
844
- readonly strategy : PubSubStrategy < A >
845
- ) {
846
- }
922
+ readonly strategy : PubSubStrategy < A > ,
923
+ readonly replayWindow : ReplayWindow < A >
924
+ ) { }
847
925
848
926
pipe ( ) {
849
927
return pipeArguments ( this , arguments )
@@ -861,19 +939,23 @@ class SubscriptionImpl<in out A> implements Queue.Dequeue<A> {
861
939
return core . suspend ( ( ) =>
862
940
MutableRef . get ( this . shutdownFlag )
863
941
? core . interrupt
864
- : core . succeed ( this . subscription . size ( ) )
942
+ : core . succeed ( this . subscription . size ( ) + this . replayWindow . remaining )
865
943
)
866
944
}
867
945
868
946
unsafeSize ( ) : Option . Option < number > {
869
947
if ( MutableRef . get ( this . shutdownFlag ) ) {
870
948
return Option . none ( )
871
949
}
872
- return Option . some ( this . subscription . size ( ) )
950
+ return Option . some ( this . subscription . size ( ) + this . replayWindow . remaining )
873
951
}
874
952
875
953
get isFull ( ) : Effect . Effect < boolean > {
876
- return core . map ( this . size , ( size ) => size === this . capacity ( ) )
954
+ return core . suspend ( ( ) =>
955
+ MutableRef . get ( this . shutdownFlag )
956
+ ? core . interrupt
957
+ : core . succeed ( this . subscription . size ( ) === this . capacity ( ) )
958
+ )
877
959
}
878
960
879
961
get isEmpty ( ) : Effect . Effect < boolean > {
@@ -915,6 +997,10 @@ class SubscriptionImpl<in out A> implements Queue.Dequeue<A> {
915
997
if ( MutableRef . get ( this . shutdownFlag ) ) {
916
998
return core . interrupt
917
999
}
1000
+ if ( this . replayWindow . remaining > 0 ) {
1001
+ const message = this . replayWindow . take ( ) !
1002
+ return core . succeed ( message )
1003
+ }
918
1004
const message = MutableQueue . isEmpty ( this . pollers )
919
1005
? this . subscription . poll ( MutableQueue . EmptyMutableQueue )
920
1006
: MutableQueue . EmptyMutableQueue
@@ -950,6 +1036,9 @@ class SubscriptionImpl<in out A> implements Queue.Dequeue<A> {
950
1036
? unsafePollAllSubscription ( this . subscription )
951
1037
: Chunk . empty ( )
952
1038
this . strategy . unsafeOnPubSubEmptySpace ( this . pubsub , this . subscribers )
1039
+ if ( this . replayWindow . remaining > 0 ) {
1040
+ return core . succeed ( Chunk . appendAll ( this . replayWindow . takeAll ( ) , as ) )
1041
+ }
953
1042
return core . succeed ( as )
954
1043
} )
955
1044
}
@@ -959,11 +1048,19 @@ class SubscriptionImpl<in out A> implements Queue.Dequeue<A> {
959
1048
if ( MutableRef . get ( this . shutdownFlag ) ) {
960
1049
return core . interrupt
961
1050
}
1051
+ let replay : Chunk . Chunk < A > | undefined = undefined
1052
+ if ( this . replayWindow . remaining >= max ) {
1053
+ const as = this . replayWindow . takeN ( max )
1054
+ return core . succeed ( as )
1055
+ } else if ( this . replayWindow . remaining > 0 ) {
1056
+ replay = this . replayWindow . takeAll ( )
1057
+ max = max - replay . length
1058
+ }
962
1059
const as = MutableQueue . isEmpty ( this . pollers )
963
1060
? unsafePollN ( this . subscription , max )
964
1061
: Chunk . empty ( )
965
1062
this . strategy . unsafeOnPubSubEmptySpace ( this . pubsub , this . subscribers )
966
- return core . succeed ( as )
1063
+ return replay ? core . succeed ( Chunk . appendAll ( replay , as ) ) : core . succeed ( as )
967
1064
} )
968
1065
}
969
1066
@@ -1019,8 +1116,7 @@ class PubSubImpl<in out A> implements PubSub.PubSub<A> {
1019
1116
readonly shutdownHook : Deferred . Deferred < void > ,
1020
1117
readonly shutdownFlag : MutableRef . MutableRef < boolean > ,
1021
1118
readonly strategy : PubSubStrategy < A >
1022
- ) {
1023
- }
1119
+ ) { }
1024
1120
1025
1121
capacity ( ) : number {
1026
1122
return this . pubsub . capacity
@@ -1075,7 +1171,7 @@ class PubSubImpl<in out A> implements PubSub.PubSub<A> {
1075
1171
return core . interrupt
1076
1172
}
1077
1173
1078
- if ( ( this . pubsub as AtomicPubSub < unknown > ) . publish ( value ) ) {
1174
+ if ( this . pubsub . publish ( value ) ) {
1079
1175
this . strategy . unsafeCompleteSubscribers ( this . pubsub , this . subscribers )
1080
1176
return core . succeed ( true )
1081
1177
}
@@ -1179,9 +1275,7 @@ export const unsafeMakePubSub = <A>(
1179
1275
shutdownHook : Deferred . Deferred < void > ,
1180
1276
shutdownFlag : MutableRef . MutableRef < boolean > ,
1181
1277
strategy : PubSubStrategy < A >
1182
- ) : PubSub . PubSub < A > => {
1183
- return new PubSubImpl ( pubsub , subscribers , scope , shutdownHook , shutdownFlag , strategy )
1184
- }
1278
+ ) : PubSub . PubSub < A > => new PubSubImpl ( pubsub , subscribers , scope , shutdownHook , shutdownFlag , strategy )
1185
1279
1186
1280
/** @internal */
1187
1281
const ensureCapacity = ( capacity : number ) : void => {
@@ -1562,3 +1656,100 @@ const unsafeStrategyCompleteSubscribers = <A>(
1562
1656
}
1563
1657
}
1564
1658
}
1659
+
1660
+ interface ReplayNode < A > {
1661
+ value : A | AbsentValue
1662
+ next : ReplayNode < A > | null
1663
+ }
1664
+
1665
+ class ReplayBuffer < A > {
1666
+ constructor ( readonly capacity : number ) { }
1667
+
1668
+ head : ReplayNode < A > = { value : AbsentValue , next : null }
1669
+ tail : ReplayNode < A > = this . head
1670
+ size = 0
1671
+ index = 0
1672
+
1673
+ slide ( ) {
1674
+ this . index ++
1675
+ }
1676
+ offer ( a : A ) : void {
1677
+ this . tail . value = a
1678
+ this . tail . next = {
1679
+ value : AbsentValue ,
1680
+ next : null
1681
+ }
1682
+ this . tail = this . tail . next
1683
+ if ( this . size === this . capacity ) {
1684
+ this . head = this . head . next !
1685
+ } else {
1686
+ this . size += 1
1687
+ }
1688
+ }
1689
+ offerAll ( as : Iterable < A > ) : void {
1690
+ for ( const a of as ) {
1691
+ this . offer ( a )
1692
+ }
1693
+ }
1694
+ }
1695
+
1696
+ interface ReplayWindow < A > {
1697
+ take ( ) : A | undefined
1698
+ takeN ( n : number ) : Chunk . Chunk < A >
1699
+ takeAll ( ) : Chunk . Chunk < A >
1700
+ readonly remaining : number
1701
+ }
1702
+
1703
+ class ReplayWindowImpl < A > implements ReplayWindow < A > {
1704
+ head : ReplayNode < A >
1705
+ index : number
1706
+ remaining : number
1707
+ constructor ( readonly buffer : ReplayBuffer < A > ) {
1708
+ this . index = buffer . index
1709
+ this . remaining = buffer . size
1710
+ this . head = buffer . head
1711
+ }
1712
+ fastForward ( ) {
1713
+ while ( this . index < this . buffer . index ) {
1714
+ this . head = this . head . next !
1715
+ this . index ++
1716
+ }
1717
+ }
1718
+ take ( ) : A | undefined {
1719
+ if ( this . remaining === 0 ) {
1720
+ return undefined
1721
+ } else if ( this . index < this . buffer . index ) {
1722
+ this . fastForward ( )
1723
+ }
1724
+ this . remaining --
1725
+ const value = this . head . value
1726
+ this . head = this . head . next !
1727
+ return value as A
1728
+ }
1729
+ takeN ( n : number ) : Chunk . Chunk < A > {
1730
+ if ( this . remaining === 0 ) {
1731
+ return Chunk . empty ( )
1732
+ } else if ( this . index < this . buffer . index ) {
1733
+ this . fastForward ( )
1734
+ }
1735
+ const len = Math . min ( n , this . remaining )
1736
+ const items = new Array ( len )
1737
+ for ( let i = 0 ; i < len ; i ++ ) {
1738
+ const value = this . head . value as A
1739
+ this . head = this . head . next !
1740
+ items [ i ] = value
1741
+ }
1742
+ this . remaining -= len
1743
+ return Chunk . unsafeFromArray ( items )
1744
+ }
1745
+ takeAll ( ) : Chunk . Chunk < A > {
1746
+ return this . takeN ( this . remaining )
1747
+ }
1748
+ }
1749
+
1750
+ const emptyReplayWindow : ReplayWindow < never > = {
1751
+ remaining : 0 ,
1752
+ take : ( ) => undefined ,
1753
+ takeN : ( ) => Chunk . empty ( ) ,
1754
+ takeAll : ( ) => Chunk . empty ( )
1755
+ }
0 commit comments