11use calendar_duration:: CalendarDuration ;
22use serde:: Deserialize ;
3- use std:: env;
3+ use std:: { env, sync :: Mutex } ;
44use time:: OffsetDateTime ;
55
66use crate :: channel:: get_data_channel_value_from_env;
@@ -26,9 +26,9 @@ const DEFAULT_EPOCH_DATE_FIELD_NAMES: &str = "typical=wos";
2626#[ serde( rename_all = "camelCase" ) ]
2727pub struct CurrentEpochInfo {
2828 #[ serde( rename = "currentEpoch" ) ]
29- pub epoch : u8 ,
29+ epoch : u8 ,
3030 #[ serde( deserialize_with = "time::serde::rfc3339::deserialize" ) ]
31- pub next_epoch_time : OffsetDateTime ,
31+ next_epoch_time : OffsetDateTime ,
3232}
3333
3434impl CurrentEpochInfo {
@@ -61,6 +61,19 @@ impl CurrentEpochInfo {
6161 . expect ( "should be able to parse info json from randomness server" )
6262 }
6363
64+ fn update ( & mut self , epoch_duration : CalendarDuration ) {
65+ let now = OffsetDateTime :: now_utc ( ) ;
66+ while now >= self . next_epoch_time {
67+ let new_epoch = self . epoch . wrapping_add ( 1 ) ;
68+ debug ! (
69+ "Updating current epoch from {} to {}" ,
70+ self . epoch, new_epoch
71+ ) ;
72+ self . epoch = new_epoch;
73+ self . next_epoch_time = self . next_epoch_time + epoch_duration;
74+ }
75+ }
76+
6477 pub fn test_info ( test_epoch : u8 , epoch_duration : CalendarDuration ) -> Self {
6578 Self {
6679 epoch : test_epoch,
@@ -70,7 +83,7 @@ impl CurrentEpochInfo {
7083}
7184
7285pub struct EpochConfig {
73- pub current_epoch : CurrentEpochInfo ,
86+ pub current_epoch_info : Mutex < CurrentEpochInfo > ,
7487 pub epoch_date_field_name : String ,
7588 pub epoch_length : CalendarDuration ,
7689 pub epoch_lifetime_count : usize ,
@@ -103,16 +116,21 @@ impl EpochConfig {
103116 None => CurrentEpochInfo :: retrieve ( channel_name) . await ,
104117 } ;
105118 Self {
106- current_epoch,
119+ current_epoch_info : Mutex :: new ( current_epoch) ,
107120 epoch_date_field_name,
108121 epoch_length,
109122 epoch_lifetime_count,
110123 }
111124 }
112125
113126 pub fn is_epoch_expired ( & self , epoch : u8 ) -> bool {
127+ let mut current_epoch = {
128+ let mut current_epoch_info = self . current_epoch_info . lock ( ) . unwrap ( ) ;
129+ current_epoch_info. update ( self . epoch_length ) ;
130+ current_epoch_info. epoch
131+ } ;
132+
114133 let mut diff = 0 ;
115- let mut current_epoch = self . current_epoch . epoch ;
116134 if !( FIRST_EPOCH ..=LAST_EPOCH ) . contains ( & current_epoch) {
117135 return true ;
118136 }
@@ -128,9 +146,20 @@ impl EpochConfig {
128146 diff >= self . epoch_lifetime_count
129147 }
130148
149+ pub fn current_epoch ( & self ) -> u8 {
150+ let mut current_epoch_info = self . current_epoch_info . lock ( ) . unwrap ( ) ;
151+ current_epoch_info. update ( self . epoch_length ) ;
152+ current_epoch_info. epoch
153+ }
154+
131155 pub fn get_epoch_survey_date ( & self , epoch : u8 ) -> String {
132- let current_epoch_start = self . current_epoch . next_epoch_time - self . epoch_length ;
133- let epoch_delta = self . current_epoch . epoch . wrapping_sub ( epoch) ;
156+ let ( next_epoch_time, current_epoch) = {
157+ let mut current_epoch_info = self . current_epoch_info . lock ( ) . unwrap ( ) ;
158+ current_epoch_info. update ( self . epoch_length ) ;
159+ ( current_epoch_info. next_epoch_time , current_epoch_info. epoch )
160+ } ;
161+ let current_epoch_start = next_epoch_time - self . epoch_length ;
162+ let epoch_delta = current_epoch. wrapping_sub ( epoch) ;
134163
135164 let mut epoch_start_date = current_epoch_start;
136165 for _ in 0 ..epoch_delta {
@@ -142,34 +171,96 @@ impl EpochConfig {
142171
143172#[ cfg( test) ]
144173mod tests {
174+ use std:: sync:: Mutex ;
175+
145176 use super :: { CurrentEpochInfo , EpochConfig } ;
146177 use calendar_duration:: CalendarDuration ;
147- use time:: { format_description :: well_known :: Rfc3339 , OffsetDateTime } ;
178+ use time:: OffsetDateTime ;
148179
149180 fn get_epoch_config ( ) -> EpochConfig {
150181 let epoch_length = CalendarDuration :: from ( "1w" ) ;
151182 EpochConfig {
152- current_epoch : CurrentEpochInfo {
183+ current_epoch_info : Mutex :: new ( CurrentEpochInfo {
153184 epoch : 2 ,
154- next_epoch_time : OffsetDateTime :: parse ( "2023-05-08T13:00:00.000Z" , & Rfc3339 )
155- . unwrap ( )
156- . into ( ) ,
157- } ,
185+ next_epoch_time : OffsetDateTime :: now_utc ( ) + epoch_length,
186+ } ) ,
158187 epoch_date_field_name : "wos" . to_string ( ) ,
159188 epoch_length,
160189 epoch_lifetime_count : 5 ,
161190 }
162191 }
163192
193+ fn get_expected_epoch_date ( date_time : OffsetDateTime , offset : CalendarDuration ) -> String {
194+ let date = date_time - offset;
195+ date. date ( ) . to_string ( )
196+ }
197+
198+ #[ test]
199+ fn current_epoch ( ) {
200+ let epoch_config = get_epoch_config ( ) ;
201+
202+ assert_eq ! ( epoch_config. current_epoch( ) , 2 ) ;
203+ }
204+
205+ #[ test]
206+ fn epoch_update_current_epoch ( ) {
207+ let epoch_config = get_epoch_config ( ) ;
208+ let now = OffsetDateTime :: now_utc ( ) ;
209+ {
210+ let mut current_epoch_info = epoch_config. current_epoch_info . lock ( ) . unwrap ( ) ;
211+ current_epoch_info. next_epoch_time = now - CalendarDuration :: from ( "2w" ) ;
212+ current_epoch_info. epoch = 255 ;
213+ }
214+
215+ assert_eq ! ( epoch_config. current_epoch( ) , 2 ) ;
216+ assert_eq ! (
217+ epoch_config
218+ . current_epoch_info
219+ . lock( )
220+ . unwrap( )
221+ . next_epoch_time,
222+ now + CalendarDuration :: from( "1w" )
223+ ) ;
224+
225+ assert_eq ! (
226+ epoch_config. get_epoch_survey_date( 255 ) ,
227+ get_expected_epoch_date( now, CalendarDuration :: from( "3w" ) )
228+ ) ;
229+ assert_eq ! (
230+ epoch_config. get_epoch_survey_date( 2 ) ,
231+ now. date( ) . to_string( )
232+ ) ;
233+ }
234+
164235 #[ test]
165236 fn survey_date ( ) {
166237 let epoch_config = get_epoch_config ( ) ;
238+ let next_epoch_time = epoch_config
239+ . current_epoch_info
240+ . lock ( )
241+ . unwrap ( )
242+ . next_epoch_time ;
167243
168- assert_eq ! ( epoch_config. get_epoch_survey_date( 2 ) , "2023-05-01" ) ;
169- assert_eq ! ( epoch_config. get_epoch_survey_date( 1 ) , "2023-04-24" ) ;
170- assert_eq ! ( epoch_config. get_epoch_survey_date( 0 ) , "2023-04-17" ) ;
171- assert_eq ! ( epoch_config. get_epoch_survey_date( 255 ) , "2023-04-10" ) ;
172- assert_eq ! ( epoch_config. get_epoch_survey_date( 254 ) , "2023-04-03" ) ;
244+ assert_eq ! (
245+ epoch_config. get_epoch_survey_date( 2 ) ,
246+ get_expected_epoch_date( next_epoch_time, CalendarDuration :: from( "1w" ) )
247+ ) ;
248+ assert_eq ! (
249+ epoch_config. get_epoch_survey_date( 1 ) ,
250+ get_expected_epoch_date( next_epoch_time, CalendarDuration :: from( "2w" ) )
251+ ) ;
252+ assert_eq ! (
253+ epoch_config. get_epoch_survey_date( 0 ) ,
254+ get_expected_epoch_date( next_epoch_time, CalendarDuration :: from( "3w" ) )
255+ ) ;
256+ assert_eq ! (
257+ epoch_config. get_epoch_survey_date( 255 ) ,
258+ get_expected_epoch_date( next_epoch_time, CalendarDuration :: from( "4w" ) )
259+ ) ;
260+ assert_eq ! (
261+ epoch_config. get_epoch_survey_date( 254 ) ,
262+ get_expected_epoch_date( next_epoch_time, CalendarDuration :: from( "5w" ) )
263+ ) ;
173264 }
174265
175266 #[ test]
0 commit comments