Skip to content

Commit a8c2739

Browse files
authored
Merge pull request #254 from brave/epoch-fix
Update current epoch info during aggregation
2 parents df66d5a + f67a337 commit a8c2739

File tree

3 files changed

+114
-21
lines changed

3 files changed

+114
-21
lines changed

src/aggregator/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ pub async fn start_aggregation(
8585
output_measurements_to_stdout: bool,
8686
epoch_config: Arc<EpochConfig>,
8787
) -> Result<(), AggregatorError> {
88-
info!("Current epoch is {}", epoch_config.current_epoch.epoch);
88+
info!("Current epoch is {}", epoch_config.current_epoch());
8989

9090
let default_k_threshold =
9191
parse_env_var::<usize>(DEFAULT_K_THRESHOLD_ENV_KEY, DEFAULT_K_THRESHOLD_DEFAULT);

src/aggregator/report.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,8 @@ pub async fn report_measurements(
139139

140140
#[cfg(test)]
141141
mod tests {
142+
use std::sync::Mutex;
143+
142144
use calendar_duration::CalendarDuration;
143145
use serde_json::json;
144146
use time::OffsetDateTime;
@@ -151,7 +153,7 @@ mod tests {
151153
fn test_epoch_config(epoch: u8) -> EpochConfig {
152154
let epoch_length = CalendarDuration::from("1w");
153155
EpochConfig {
154-
current_epoch: CurrentEpochInfo::test_info(epoch, epoch_length),
156+
current_epoch_info: Mutex::new(CurrentEpochInfo::test_info(epoch, epoch_length)),
155157
epoch_date_field_name: "wos".to_string(),
156158
epoch_length,
157159
epoch_lifetime_count: 3,

src/epoch.rs

Lines changed: 110 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use calendar_duration::CalendarDuration;
22
use serde::Deserialize;
3-
use std::env;
3+
use std::{env, sync::Mutex};
44
use time::OffsetDateTime;
55

66
use 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")]
2727
pub 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

3434
impl 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

7285
pub 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)]
144173
mod 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

Comments
 (0)