Skip to content

Commit 02a89cd

Browse files
author
Devdutt Shenoi
authored
refactor: reuse TimeRange (#1146)
1 parent 68e12b2 commit 02a89cd

File tree

3 files changed

+272
-239
lines changed

3 files changed

+272
-239
lines changed

src/query/listing_table_builder.rs

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ use object_store::{path::Path, ObjectMeta, ObjectStore};
3434
use crate::{
3535
event::DEFAULT_TIMESTAMP_KEY,
3636
storage::{ObjectStorage, OBJECT_STORE_DATA_GRANULARITY},
37-
utils::TimePeriod,
37+
utils::time::TimeRange,
3838
};
3939

4040
use super::PartialTimeFilter;
@@ -88,12 +88,8 @@ impl ListingTableBuilder {
8888
};
8989

9090
// Generate prefixes for the given time range
91-
let prefixes = TimePeriod::new(
92-
start_time.and_utc(),
93-
end_time.and_utc(),
94-
OBJECT_STORE_DATA_GRANULARITY,
95-
)
96-
.generate_prefixes();
91+
let prefixes = TimeRange::new(start_time.and_utc(), end_time.and_utc())
92+
.generate_prefixes(OBJECT_STORE_DATA_GRANULARITY);
9793

9894
// Categorizes prefixes into "minute" and general resolve lists.
9995
let mut minute_resolve = HashMap::<String, Vec<String>>::new();

src/utils/mod.rs

Lines changed: 1 addition & 231 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ use crate::rbac::role::{Action, Permission};
3131
use crate::rbac::Users;
3232
use actix::extract_session_key_from_req;
3333
use actix_web::HttpRequest;
34-
use chrono::{DateTime, NaiveDate, NaiveDateTime, NaiveTime, Timelike, Utc};
34+
use chrono::{NaiveDate, NaiveDateTime, NaiveTime, Utc};
3535
use itertools::Itertools;
3636
use regex::Regex;
3737
use sha2::{Digest, Sha256};
@@ -85,153 +85,6 @@ pub fn minute_to_prefix(minute: u32, data_granularity: u32) -> Option<String> {
8585
))
8686
}
8787

88-
pub struct TimePeriod {
89-
start: DateTime<Utc>,
90-
end: DateTime<Utc>,
91-
data_granularity: u32,
92-
}
93-
94-
impl TimePeriod {
95-
pub fn new(start: DateTime<Utc>, end: DateTime<Utc>, data_granularity: u32) -> Self {
96-
Self {
97-
data_granularity,
98-
start,
99-
end,
100-
}
101-
}
102-
103-
pub fn generate_prefixes(&self) -> Vec<String> {
104-
let end_minute = self.end.minute() + u32::from(self.end.second() > 0);
105-
self.generate_date_prefixes(
106-
self.start.date_naive(),
107-
self.end.date_naive(),
108-
(self.start.hour(), self.start.minute()),
109-
(self.end.hour(), end_minute),
110-
)
111-
}
112-
113-
pub fn generate_minute_prefixes(
114-
&self,
115-
prefix: &str,
116-
start_minute: u32,
117-
end_minute: u32,
118-
) -> Vec<String> {
119-
if start_minute == end_minute {
120-
return vec![];
121-
}
122-
123-
let (start_block, end_block) = (
124-
start_minute / self.data_granularity,
125-
end_minute / self.data_granularity,
126-
);
127-
128-
let forbidden_block = 60 / self.data_granularity;
129-
130-
// ensure both start and end are within the same hour, else return prefix as is
131-
if end_block - start_block >= forbidden_block {
132-
return vec![prefix.to_owned()];
133-
}
134-
135-
let mut prefixes = vec![];
136-
137-
let push_prefix = |block: u32, prefixes: &mut Vec<_>| {
138-
if let Some(minute_prefix) =
139-
minute_to_prefix(block * self.data_granularity, self.data_granularity)
140-
{
141-
let prefix = prefix.to_owned() + &minute_prefix;
142-
prefixes.push(prefix);
143-
}
144-
};
145-
146-
for block in start_block..end_block {
147-
push_prefix(block, &mut prefixes);
148-
}
149-
150-
// NOTE: for block sizes larger than a minute ensure
151-
// ensure last block is considered
152-
if self.data_granularity > 1 {
153-
push_prefix(end_block, &mut prefixes);
154-
}
155-
156-
prefixes
157-
}
158-
159-
pub fn generate_hour_prefixes(
160-
&self,
161-
prefix: &str,
162-
start_hour: u32,
163-
start_minute: u32,
164-
end_hour: u32,
165-
end_minute: u32,
166-
) -> Vec<String> {
167-
// ensure both start and end are within the same day
168-
if end_hour - start_hour >= 24 {
169-
return vec![prefix.to_owned()];
170-
}
171-
172-
let mut prefixes = vec![];
173-
174-
for hour in start_hour..=end_hour {
175-
if hour == 24 {
176-
break;
177-
}
178-
let prefix = prefix.to_owned() + &hour_to_prefix(hour);
179-
let is_start = hour == start_hour;
180-
let is_end = hour == end_hour;
181-
182-
if is_start || is_end {
183-
let minute_prefixes = self.generate_minute_prefixes(
184-
&prefix,
185-
if is_start { start_minute } else { 0 },
186-
if is_end { end_minute } else { 60 },
187-
);
188-
prefixes.extend(minute_prefixes);
189-
} else {
190-
prefixes.push(prefix);
191-
}
192-
}
193-
194-
prefixes
195-
}
196-
197-
pub fn generate_date_prefixes(
198-
&self,
199-
start_date: NaiveDate,
200-
end_date: NaiveDate,
201-
start_time: (u32, u32),
202-
end_time: (u32, u32),
203-
) -> Vec<String> {
204-
let mut prefixes = vec![];
205-
let mut date = start_date;
206-
207-
while date <= end_date {
208-
let prefix = date_to_prefix(date);
209-
let is_start = date == start_date;
210-
let is_end = date == end_date;
211-
212-
if is_start || is_end {
213-
let ((start_hour, start_minute), (end_hour, end_minute)) = (
214-
if is_start { start_time } else { (0, 0) },
215-
if is_end { end_time } else { (24, 60) },
216-
);
217-
let hour_prefixes = self.generate_hour_prefixes(
218-
&prefix,
219-
start_hour,
220-
start_minute,
221-
end_hour,
222-
end_minute,
223-
);
224-
prefixes.extend(hour_prefixes);
225-
} else {
226-
prefixes.push(prefix);
227-
}
228-
date = date.succ_opt().unwrap();
229-
}
230-
231-
prefixes
232-
}
233-
}
234-
23588
pub fn get_url() -> Url {
23689
if CONFIG.options.ingestor_endpoint.is_empty() {
23790
return format!(
@@ -373,86 +226,3 @@ pub fn user_auth_for_query(
373226

374227
Ok(())
375228
}
376-
377-
#[cfg(test)]
378-
mod tests {
379-
use chrono::DateTime;
380-
use rstest::*;
381-
382-
use super::TimePeriod;
383-
384-
fn time_period_from_str(start: &str, end: &str) -> TimePeriod {
385-
TimePeriod::new(
386-
DateTime::parse_from_rfc3339(start).unwrap().into(),
387-
DateTime::parse_from_rfc3339(end).unwrap().into(),
388-
1,
389-
)
390-
}
391-
392-
#[rstest]
393-
#[case::same_minute(
394-
"2022-06-11T16:30:00+00:00", "2022-06-11T16:30:59+00:00",
395-
&["date=2022-06-11/hour=16/minute=30/"]
396-
)]
397-
#[case::same_hour_different_minute(
398-
"2022-06-11T16:57:00+00:00", "2022-06-11T16:59:00+00:00",
399-
&[
400-
"date=2022-06-11/hour=16/minute=57/",
401-
"date=2022-06-11/hour=16/minute=58/"
402-
]
403-
)]
404-
#[case::same_hour_with_00_to_59_minute_block(
405-
"2022-06-11T16:00:00+00:00", "2022-06-11T16:59:59+00:00",
406-
&["date=2022-06-11/hour=16/"]
407-
)]
408-
#[case::same_date_different_hours_coherent_minute(
409-
"2022-06-11T15:00:00+00:00", "2022-06-11T17:00:00+00:00",
410-
&[
411-
"date=2022-06-11/hour=15/",
412-
"date=2022-06-11/hour=16/"
413-
]
414-
)]
415-
#[case::same_date_different_hours_incoherent_minutes(
416-
"2022-06-11T15:59:00+00:00", "2022-06-11T16:01:00+00:00",
417-
&[
418-
"date=2022-06-11/hour=15/minute=59/",
419-
"date=2022-06-11/hour=16/minute=00/"
420-
]
421-
)]
422-
#[case::same_date_different_hours_whole_hours_between_incoherent_minutes(
423-
"2022-06-11T15:59:00+00:00", "2022-06-11T17:01:00+00:00",
424-
&[
425-
"date=2022-06-11/hour=15/minute=59/",
426-
"date=2022-06-11/hour=16/",
427-
"date=2022-06-11/hour=17/minute=00/"
428-
]
429-
)]
430-
#[case::different_date_coherent_hours_and_minutes(
431-
"2022-06-11T00:00:00+00:00", "2022-06-13T00:00:00+00:00",
432-
&[
433-
"date=2022-06-11/",
434-
"date=2022-06-12/"
435-
]
436-
)]
437-
#[case::different_date_incoherent_hours_coherent_minutes(
438-
"2022-06-11T23:00:01+00:00", "2022-06-12T01:59:59+00:00",
439-
&[
440-
"date=2022-06-11/hour=23/",
441-
"date=2022-06-12/hour=00/",
442-
"date=2022-06-12/hour=01/"
443-
]
444-
)]
445-
#[case::different_date_incoherent_hours_incoherent_minutes(
446-
"2022-06-11T23:59:59+00:00", "2022-06-12T00:01:00+00:00",
447-
&[
448-
"date=2022-06-11/hour=23/minute=59/",
449-
"date=2022-06-12/hour=00/minute=00/"
450-
]
451-
)]
452-
fn prefix_generation(#[case] start: &str, #[case] end: &str, #[case] right: &[&str]) {
453-
let time_period = time_period_from_str(start, end);
454-
let prefixes = time_period.generate_prefixes();
455-
let left = prefixes.iter().map(String::as_str).collect::<Vec<&str>>();
456-
assert_eq!(left.as_slice(), right);
457-
}
458-
}

0 commit comments

Comments
 (0)