@@ -45,6 +45,22 @@ export const ScheduleDriverTypeId: Schedule.ScheduleDriverTypeId = Symbol.for(
4545 ScheduleDriverSymbolKey
4646) as Schedule . ScheduleDriverTypeId
4747
48+ /** @internal */
49+ const defaultIterationMetadata : Schedule . IterationMetadata = {
50+ start : 0 ,
51+ now : 0 ,
52+ input : undefined ,
53+ elapsed : Duration . zero ,
54+ elapsedSincePrevious : Duration . zero ,
55+ recurrence : 0
56+ }
57+
58+ /** @internal */
59+ export const CurrentIterationMetadata = Context . Reference < Schedule . CurrentIterationMetadata > ( ) (
60+ "effect/Schedule/CurrentIterationMetadata" ,
61+ { defaultValue : ( ) => defaultIterationMetadata }
62+ )
63+
4864const scheduleVariance = {
4965 /* c8 ignore next */
5066 _Out : ( _ : never ) => _ ,
@@ -80,6 +96,31 @@ class ScheduleImpl<S, Out, In, R> implements Schedule.Schedule<Out, In, R> {
8096 }
8197}
8298
99+ /** @internal */
100+ const updateInfo = (
101+ iterationMetaRef : Ref . Ref < Schedule . IterationMetadata > ,
102+ now : number ,
103+ input : unknown
104+ ) =>
105+ ref . update ( iterationMetaRef , ( prev ) =>
106+ ( prev . recurrence === 0 ) ?
107+ {
108+ now,
109+ input,
110+ recurrence : prev . recurrence + 1 ,
111+ elapsed : Duration . zero ,
112+ elapsedSincePrevious : Duration . zero ,
113+ start : now
114+ } :
115+ {
116+ now,
117+ input,
118+ recurrence : prev . recurrence + 1 ,
119+ elapsed : Duration . millis ( now - prev . start ) ,
120+ elapsedSincePrevious : Duration . millis ( now - prev . now ) ,
121+ start : prev . start
122+ } )
123+
83124/** @internal */
84125class ScheduleDriverImpl < Out , In , R > implements Schedule . ScheduleDriver < Out , In , R > {
85126 [ ScheduleDriverTypeId ] = scheduleDriverVariance
@@ -106,8 +147,12 @@ class ScheduleDriverImpl<Out, In, R> implements Schedule.ScheduleDriver<Out, In,
106147 } )
107148 }
108149
150+ iterationMeta = ref . unsafeMake ( defaultIterationMetadata )
151+
109152 get reset ( ) : Effect . Effect < void > {
110- return ref . set ( this . ref , [ Option . none ( ) , this . schedule . initial ] )
153+ return ref . set ( this . ref , [ Option . none ( ) , this . schedule . initial ] ) . pipe (
154+ core . zipLeft ( ref . set ( this . iterationMeta , defaultIterationMetadata ) )
155+ )
111156 }
112157
113158 next ( input : In ) : Effect . Effect < Out , Option . Option < never > , R > {
@@ -122,15 +167,22 @@ class ScheduleDriverImpl<Out, In, R> implements Schedule.ScheduleDriver<Out, In,
122167 core . flatMap ( ( [ state , out , decision ] ) => {
123168 const setState = ref . set ( this . ref , [ Option . some ( out ) , state ] as const )
124169 if ( ScheduleDecision . isDone ( decision ) ) {
125- return core . zipRight ( setState , core . fail ( Option . none ( ) ) )
170+ return setState . pipe (
171+ core . zipRight ( core . fail ( Option . none ( ) ) )
172+ )
126173 }
127174 const millis = Intervals . start ( decision . intervals ) - now
128175 if ( millis <= 0 ) {
129- return core . as ( setState , out )
176+ return setState . pipe (
177+ core . zipRight ( updateInfo ( this . iterationMeta , now , input ) ) ,
178+ core . as ( out )
179+ )
130180 }
181+ const duration = Duration . millis ( millis )
131182 return pipe (
132183 setState ,
133- core . zipRight ( effect . sleep ( Duration . millis ( millis ) ) ) ,
184+ core . zipRight ( updateInfo ( this . iterationMeta , now , input ) ) ,
185+ core . zipRight ( effect . sleep ( duration ) ) ,
134186 core . as ( out )
135187 )
136188 } )
@@ -1874,7 +1926,22 @@ export const repeatOrElse_Effect = dual<
18741926 core . flatMap ( driver ( schedule ) , ( driver ) =>
18751927 core . matchEffect ( self , {
18761928 onFailure : ( error ) => orElse ( error , Option . none ( ) ) ,
1877- onSuccess : ( value ) => repeatOrElseEffectLoop ( self , driver , orElse , value )
1929+ onSuccess : ( value ) =>
1930+ repeatOrElseEffectLoop (
1931+ effect . provideServiceEffect (
1932+ self ,
1933+ CurrentIterationMetadata ,
1934+ ref . get ( driver . iterationMeta )
1935+ ) ,
1936+ driver ,
1937+ ( error , option ) =>
1938+ effect . provideServiceEffect (
1939+ orElse ( error , option ) ,
1940+ CurrentIterationMetadata ,
1941+ ref . get ( driver . iterationMeta )
1942+ ) ,
1943+ value
1944+ )
18781945 } ) ) )
18791946
18801947/** @internal */
@@ -1883,16 +1950,15 @@ const repeatOrElseEffectLoop = <A, E, R, R1, B, C, E2, R2>(
18831950 driver : Schedule . ScheduleDriver < B , A , R1 > ,
18841951 orElse : ( error : E , option : Option . Option < B > ) => Effect . Effect < C , E2 , R2 > ,
18851952 value : A
1886- ) : Effect . Effect < B | C , E2 , R | R1 | R2 > => {
1887- return core . matchEffect ( driver . next ( value ) , {
1953+ ) : Effect . Effect < B | C , E2 , R | R1 | R2 > =>
1954+ core . matchEffect ( driver . next ( value ) , {
18881955 onFailure : ( ) => core . orDie ( driver . last ) ,
18891956 onSuccess : ( b ) =>
18901957 core . matchEffect ( self , {
18911958 onFailure : ( error ) => orElse ( error , Option . some ( b ) ) ,
18921959 onSuccess : ( value ) => repeatOrElseEffectLoop ( self , driver , orElse , value )
18931960 } )
18941961 } )
1895- }
18961962
18971963/** @internal */
18981964export const retry_Effect = dual <
@@ -1970,7 +2036,21 @@ export const retryOrElse_Effect = dual<
19702036> ( 3 , ( self , policy , orElse ) =>
19712037 core . flatMap (
19722038 driver ( policy ) ,
1973- ( driver ) => retryOrElse_EffectLoop ( self , driver , orElse )
2039+ ( driver ) =>
2040+ retryOrElse_EffectLoop (
2041+ effect . provideServiceEffect (
2042+ self ,
2043+ CurrentIterationMetadata ,
2044+ ref . get ( driver . iterationMeta )
2045+ ) ,
2046+ driver ,
2047+ ( e , out ) =>
2048+ effect . provideServiceEffect (
2049+ orElse ( e , out ) ,
2050+ CurrentIterationMetadata ,
2051+ ref . get ( driver . iterationMeta )
2052+ )
2053+ )
19742054 ) )
19752055
19762056/** @internal */
@@ -2022,7 +2102,16 @@ export const scheduleFrom_Effect = dual<
20222102> ( 3 , ( self , initial , schedule ) =>
20232103 core . flatMap (
20242104 driver ( schedule ) ,
2025- ( driver ) => scheduleFrom_EffectLoop ( self , initial , driver )
2105+ ( driver ) =>
2106+ scheduleFrom_EffectLoop (
2107+ effect . provideServiceEffect (
2108+ self ,
2109+ CurrentIterationMetadata ,
2110+ ref . get ( driver . iterationMeta )
2111+ ) ,
2112+ initial ,
2113+ driver
2114+ )
20262115 ) )
20272116
20282117/** @internal */
@@ -2033,7 +2122,11 @@ const scheduleFrom_EffectLoop = <In, E, R, R2, Out>(
20332122) : Effect . Effect < Out , E , R | R2 > =>
20342123 core . matchEffect ( driver . next ( initial ) , {
20352124 onFailure : ( ) => core . orDie ( driver . last ) ,
2036- onSuccess : ( ) => core . flatMap ( self , ( a ) => scheduleFrom_EffectLoop ( self , a , driver ) )
2125+ onSuccess : ( ) =>
2126+ core . flatMap (
2127+ self ,
2128+ ( a ) => scheduleFrom_EffectLoop ( self , a , driver )
2129+ )
20372130 } )
20382131
20392132/** @internal */
0 commit comments