adds frontend history
This commit is contained in:
@@ -1,13 +1,13 @@
|
||||
use crate::telemetry::data_item::TelemetryDataItem;
|
||||
use crate::telemetry::data_value::TelemetryDataValue;
|
||||
use chrono::{DateTime, SecondsFormat, TimeDelta, Utc};
|
||||
use log::error;
|
||||
use std::collections::VecDeque;
|
||||
use std::sync::RwLock;
|
||||
use log::error;
|
||||
use crate::telemetry::data_item::TelemetryDataItem;
|
||||
|
||||
struct SegmentData {
|
||||
values: Vec<TelemetryDataValue>,
|
||||
timestamps: Vec<DateTime<Utc>>
|
||||
timestamps: Vec<DateTime<Utc>>,
|
||||
}
|
||||
|
||||
struct HistorySegment {
|
||||
@@ -47,12 +47,18 @@ impl HistorySegment {
|
||||
data.values.insert(index, value);
|
||||
}
|
||||
|
||||
fn get(&self, from: DateTime<Utc>, to: DateTime<Utc>, maximum_resolution: TimeDelta) -> (DateTime<Utc>, Vec<TelemetryDataItem>) {
|
||||
fn get(
|
||||
&self,
|
||||
from: DateTime<Utc>,
|
||||
to: DateTime<Utc>,
|
||||
maximum_resolution: TimeDelta,
|
||||
) -> (DateTime<Utc>, Vec<TelemetryDataItem>) {
|
||||
let mut result = vec![];
|
||||
|
||||
let mut next_from = from;
|
||||
|
||||
if from < self.end && self.start < to { // If there is overlap with the range
|
||||
if from < self.end && self.start < to {
|
||||
// If there is overlap with the range
|
||||
let data = self.data.read().unwrap_or_else(|err| {
|
||||
error!("HistorySegment::get - data was poisoned: {}", err);
|
||||
let lock = err.into_inner();
|
||||
@@ -73,17 +79,25 @@ impl HistorySegment {
|
||||
let t = data.timestamps[i];
|
||||
if t >= next_from {
|
||||
let time_since_next_from = t - next_from;
|
||||
next_from = match (time_since_next_from.num_nanoseconds(), maximum_resolution.num_nanoseconds()) {
|
||||
next_from = match (
|
||||
time_since_next_from.num_nanoseconds(),
|
||||
maximum_resolution.num_nanoseconds(),
|
||||
) {
|
||||
(_, Some(0)) => t,
|
||||
(Some(nanos_since_next_from), Some(maximum_resolution_nanos)) => {
|
||||
let nanos_since_next_from = nanos_since_next_from as u64;
|
||||
let maximum_resolution_nanos = maximum_resolution_nanos as u64;
|
||||
let num_steps = nanos_since_next_from.div_ceil(maximum_resolution_nanos);
|
||||
let num_steps =
|
||||
nanos_since_next_from.div_ceil(maximum_resolution_nanos);
|
||||
let subsec_nanos = maximum_resolution.subsec_nanos() as u64;
|
||||
// This will break once this can't be represented in 2^63 nanoseconds (over 200 years)
|
||||
let seconds = ((maximum_resolution.num_seconds() as u64) * num_steps) as i64;
|
||||
let seconds =
|
||||
((maximum_resolution.num_seconds() as u64) * num_steps) as i64;
|
||||
let nanos = (num_steps * subsec_nanos) as i64;
|
||||
next_from + TimeDelta::seconds(seconds) + TimeDelta::nanoseconds(nanos)
|
||||
},
|
||||
next_from
|
||||
+ TimeDelta::seconds(seconds)
|
||||
+ TimeDelta::nanoseconds(nanos)
|
||||
}
|
||||
_ => t + maximum_resolution, // If there is a gap so big it can't be represented in 2^63 nanoseconds (over 200 years) just skip forward
|
||||
};
|
||||
result.push(TelemetryDataItem {
|
||||
@@ -104,14 +118,18 @@ pub struct TelemetryHistory {
|
||||
}
|
||||
|
||||
impl TelemetryHistory {
|
||||
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
segments: RwLock::new(VecDeque::new()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn insert(&self, service: &TelemetryHistoryService, value: TelemetryDataValue, timestamp: DateTime<Utc>) {
|
||||
pub fn insert(
|
||||
&self,
|
||||
service: &TelemetryHistoryService,
|
||||
value: TelemetryDataValue,
|
||||
timestamp: DateTime<Utc>,
|
||||
) {
|
||||
let segments = self.segments.read().unwrap_or_else(|err| {
|
||||
error!("TelemetryHistory::insert - segments was poisoned: {}", err);
|
||||
let lock = err.into_inner();
|
||||
@@ -130,14 +148,20 @@ impl TelemetryHistory {
|
||||
});
|
||||
|
||||
if segments.len() == 0 {
|
||||
segments.push_back(HistorySegment::new(timestamp, timestamp + service.segment_width));
|
||||
segments.push_back(HistorySegment::new(
|
||||
timestamp,
|
||||
timestamp + service.segment_width,
|
||||
));
|
||||
} else {
|
||||
while segments[segments.len() - 1].end < timestamp {
|
||||
if segments.len() == service.max_segments {
|
||||
let _ = segments.pop_front();
|
||||
}
|
||||
let start_time = segments[segments.len() - 1].end;
|
||||
segments.push_back(HistorySegment::new(start_time, start_time + service.segment_width));
|
||||
segments.push_back(HistorySegment::new(
|
||||
start_time,
|
||||
start_time + service.segment_width,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -158,7 +182,12 @@ impl TelemetryHistory {
|
||||
segments[segment_index].insert(value, timestamp);
|
||||
}
|
||||
|
||||
pub fn get(&self, from: DateTime<Utc>, to: DateTime<Utc>, maximum_resolution: TimeDelta) -> Vec<TelemetryDataItem> {
|
||||
pub fn get(
|
||||
&self,
|
||||
from: DateTime<Utc>,
|
||||
to: DateTime<Utc>,
|
||||
maximum_resolution: TimeDelta,
|
||||
) -> Vec<TelemetryDataItem> {
|
||||
let mut result = vec![];
|
||||
|
||||
let segments = self.segments.read().unwrap_or_else(|err| {
|
||||
@@ -182,14 +211,14 @@ impl TelemetryHistory {
|
||||
|
||||
pub struct TelemetryHistoryService {
|
||||
segment_width: TimeDelta,
|
||||
max_segments: usize
|
||||
max_segments: usize,
|
||||
}
|
||||
|
||||
impl TelemetryHistoryService {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
segment_width: TimeDelta::minutes(1),
|
||||
max_segments: 5
|
||||
max_segments: 5,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user