build monthly stats and build versions

This commit is contained in:
mbecker20
2023-07-28 01:54:29 -04:00
parent 3ac7cc1a59
commit 482f8bb862
5 changed files with 240 additions and 2 deletions

View File

@@ -1,13 +1,17 @@
use std::collections::HashMap;
use anyhow::Context;
use async_timing_util::unix_timestamp_ms;
use async_trait::async_trait;
use futures::TryStreamExt;
use monitor_types::{
entities::{
build::{Build, BuildActionState},
PermissionLevel,
Operation, PermissionLevel, update::UpdateStatus,
},
requests::read::*,
};
use mungos::mongodb::bson::doc;
use mungos::mongodb::{bson::doc, options::FindOptions};
use resolver_api::Resolve;
use crate::{auth::RequestUser, resource::Resource, state::State};
@@ -87,3 +91,130 @@ impl Resolve<GetBuildsSummary, RequestUser> for State {
Ok(res)
}
}
const ONE_DAY_MS: i64 = 86400000;
#[async_trait]
impl Resolve<GetBuildMonthlyStats, RequestUser> for State {
async fn resolve(
&self,
GetBuildMonthlyStats { page }: GetBuildMonthlyStats,
_: RequestUser,
) -> anyhow::Result<GetBuildMonthlyStatsResponse> {
let curr_ts = unix_timestamp_ms() as i64;
let next_day = curr_ts - curr_ts % ONE_DAY_MS + ONE_DAY_MS;
let close_ts = next_day - page as i64 * 30 * ONE_DAY_MS;
let open_ts = close_ts - 30 * ONE_DAY_MS;
let mut build_updates = self
.db
.updates
.collection
.find(
doc! {
"start_ts": {
"$gte": open_ts,
"$lt": close_ts
},
"operation": Operation::RunBuild.to_string(),
},
None,
)
.await
.context("failed to get updates cursor")?;
let mut days = HashMap::<i64, BuildStatsDay>::with_capacity(32);
let mut curr = open_ts;
while curr < close_ts {
let stats = BuildStatsDay {
ts: curr as f64,
..Default::default()
};
days.insert(curr, stats);
curr += ONE_DAY_MS;
}
while let Some(update) = build_updates.try_next().await? {
if let Some(end_ts) = update.end_ts {
let day = update.start_ts - update.start_ts % ONE_DAY_MS;
let mut entry = days.entry(day).or_default();
entry.count += 1.0;
entry.time += ms_to_hour(end_ts - update.start_ts);
}
}
Ok(GetBuildMonthlyStatsResponse::new(
days.into_values().collect(),
))
}
}
const MS_TO_HOUR_DIVISOR: f64 = 1000.0 * 60.0 * 60.0;
fn ms_to_hour(duration: i64) -> f64 {
duration as f64 / MS_TO_HOUR_DIVISOR
}
const NUM_VERSIONS_PER_PAGE: u64 = 10;
#[async_trait]
impl Resolve<GetBuildVersions, RequestUser> for State {
async fn resolve(
&self,
GetBuildVersions {
id,
page,
major,
minor,
patch,
}: GetBuildVersions,
user: RequestUser,
) -> anyhow::Result<Vec<BuildVersionResponseItem>> {
let _: Build = self
.get_resource_check_permissions(&id, &user, PermissionLevel::Read)
.await?;
let mut filter = doc! {
"target": {
"type": "Build",
"id": id
},
"operation": Operation::RunBuild.to_string(),
"status": UpdateStatus::Complete.to_string(),
"success": true
};
if let Some(major) = major {
filter.insert("version.major", major);
}
if let Some(minor) = minor {
filter.insert("version.minor", minor);
}
if let Some(patch) = patch {
filter.insert("version.patch", patch);
}
let versions = self
.db
.updates
.get_some(
filter,
FindOptions::builder()
.sort(doc! { "_id": -1 })
.limit(NUM_VERSIONS_PER_PAGE as i64)
.skip(page as u64 * NUM_VERSIONS_PER_PAGE)
.build(),
)
.await
.context("failed to pull versions from mongo")?
.into_iter()
.map(|u| (u.version, u.start_ts))
.filter(|(v, _)| !v.is_none())
.map(|(version, ts)| BuildVersionResponseItem {
version,
ts,
})
.collect();
Ok(versions)
}
}

View File

@@ -67,6 +67,8 @@ enum ReadRequest {
GetBuild(GetBuild),
ListBuilds(ListBuilds),
GetBuildActionState(GetBuildActionState),
GetBuildMonthlyStats(GetBuildMonthlyStats),
GetBuildVersions(GetBuildVersions),
// ==== REPO ====
GetReposSummary(GetReposSummary),