Files
nix_builder/src/nix_util/activity.rs

534 lines
22 KiB
Rust
Raw Normal View History

use std::borrow::Cow;
use tracing::warn;
#[repr(u8)]
pub(crate) enum Activity {
Root(ActivityRoot),
Unknown(ActivityUnknown),
CopyPath(ActivityCopyPath),
FileTransfer(ActivityFileTransfer),
Realize(ActivityRealize),
CopyPaths(ActivityCopyPaths),
Builds(ActivityBuilds),
Build(ActivityBuild),
OptimizeStore(ActivityOptimizeStore),
VerifyPaths(ActivityVerifyPaths),
Substitute(ActivitySubstitute),
QueryPathInfo(ActivityQueryPathInfo),
PostBuildHook(ActivityPostBuildHook),
BuildWaiting(ActivityBuildWaiting),
FetchTree(ActivityFetchTree),
}
impl Activity {
pub(crate) fn stop(&mut self) -> () {
match self {
Activity::Root(_activity_root) => {
panic!("Attempted to start root activity.");
}
Activity::Unknown(activity_unknown) => {
activity_unknown.state = ActivityState::Stopped;
}
Activity::CopyPath(activity_copy_path) => {
activity_copy_path.state = ActivityState::Stopped;
}
Activity::FileTransfer(activity_file_transfer) => {
activity_file_transfer.state = ActivityState::Stopped;
}
Activity::Realize(activity_realize) => {
activity_realize.state = ActivityState::Stopped;
}
Activity::CopyPaths(activity_copy_paths) => {
activity_copy_paths.state = ActivityState::Stopped;
}
Activity::Builds(activity_builds) => {
activity_builds.state = ActivityState::Stopped;
}
Activity::Build(activity_build) => {
activity_build.state = ActivityState::Stopped;
}
Activity::OptimizeStore(activity_optimize_store) => {
activity_optimize_store.state = ActivityState::Stopped;
}
Activity::VerifyPaths(activity_verify_paths) => {
activity_verify_paths.state = ActivityState::Stopped;
}
Activity::Substitute(activity_substitute) => {
activity_substitute.state = ActivityState::Stopped;
}
Activity::QueryPathInfo(activity_query_path_info) => {
activity_query_path_info.state = ActivityState::Stopped;
}
Activity::PostBuildHook(activity_post_build_hook) => {
activity_post_build_hook.state = ActivityState::Stopped;
}
Activity::BuildWaiting(activity_build_waiting) => {
activity_build_waiting.state = ActivityState::Stopped;
}
Activity::FetchTree(activity_fetch_tree) => {
activity_fetch_tree.state = ActivityState::Stopped;
}
}
}
pub(crate) fn is_active(&self) -> bool {
match self {
Activity::Root(_activity_root) => true,
Activity::Unknown(activity_unknown) => {
matches!(activity_unknown.state, ActivityState::Started { .. })
}
Activity::CopyPath(activity_copy_path) => {
matches!(activity_copy_path.state, ActivityState::Started { .. })
}
Activity::FileTransfer(activity_file_transfer) => {
matches!(activity_file_transfer.state, ActivityState::Started { .. })
}
Activity::Realize(activity_realize) => {
matches!(activity_realize.state, ActivityState::Started { .. })
}
Activity::CopyPaths(activity_copy_paths) => {
matches!(activity_copy_paths.state, ActivityState::Started { .. })
}
Activity::Builds(activity_builds) => {
matches!(activity_builds.state, ActivityState::Started { .. })
}
Activity::Build(activity_build) => {
matches!(activity_build.state, ActivityState::Started { .. })
}
Activity::OptimizeStore(activity_optimize_store) => {
matches!(activity_optimize_store.state, ActivityState::Started { .. })
}
Activity::VerifyPaths(activity_verify_paths) => {
matches!(activity_verify_paths.state, ActivityState::Started { .. })
}
Activity::Substitute(activity_substitute) => {
matches!(activity_substitute.state, ActivityState::Started { .. })
}
Activity::QueryPathInfo(activity_query_path_info) => {
matches!(
activity_query_path_info.state,
ActivityState::Started { .. }
)
}
Activity::PostBuildHook(activity_post_build_hook) => {
matches!(
activity_post_build_hook.state,
ActivityState::Started { .. }
)
}
Activity::BuildWaiting(activity_build_waiting) => {
matches!(activity_build_waiting.state, ActivityState::Started { .. })
}
Activity::FetchTree(activity_fetch_tree) => {
matches!(activity_fetch_tree.state, ActivityState::Started { .. })
}
}
}
pub(crate) fn is_transparent(&self) -> bool {
match self {
Activity::Root(_activity_root) => true,
Activity::Unknown(_activity_unknown) => false,
Activity::CopyPath(_activity_copy_path) => false,
Activity::FileTransfer(_activity_file_transfer) => false,
Activity::Realize(_activity_realize) => true,
Activity::CopyPaths(_activity_copy_paths) => true,
Activity::Builds(_activity_builds) => true,
Activity::Build(_activity_build) => false,
Activity::OptimizeStore(_activity_optimize_store) => false,
Activity::VerifyPaths(_activity_verify_paths) => false,
Activity::Substitute(_activity_substitute) => false,
Activity::QueryPathInfo(_activity_query_path_info) => false,
Activity::PostBuildHook(_activity_post_build_hook) => false,
Activity::BuildWaiting(_activity_build_waiting) => true,
Activity::FetchTree(_activity_fetch_tree) => false,
}
}
pub(crate) fn display_name(&self) -> Option<Cow<'_, str>> {
match self {
Activity::Root(_activity_root) => {
warn!("Unexpected display of root activity.");
Some(Cow::Borrowed("Root"))
}
Activity::Unknown(activity_unknown) => {
Some(Cow::Owned(format!("Unknown({})", activity_unknown.text)))
}
Activity::CopyPath(activity_copy_path) => Some(Cow::Owned(format!(
"CopyPath({} | {} -> {})",
activity_copy_path.missing_path,
activity_copy_path.source,
activity_copy_path.destination
))),
Activity::FileTransfer(activity_file_transfer) => Some(Cow::Owned(format!(
"FileTransfer({})",
activity_file_transfer.url
))),
Activity::Realize(_activity_realize) => Some(Cow::Borrowed("Realize")),
Activity::CopyPaths(activity_copy_paths) => Some(Cow::Owned(format!(
"CopyPaths({})",
activity_copy_paths.text
))),
Activity::Builds(_activity_builds) => Some(Cow::Borrowed("Builds")),
Activity::Build(activity_build) => {
if let Some(machine_name) = &activity_build.machine_name {
Some(Cow::Owned(format!(
"Build({}@{machine_name})",
activity_build.drv_path
)))
} else {
Some(Cow::Owned(format!("Build({})", activity_build.drv_path)))
}
}
Activity::OptimizeStore(_activity_optimize_store) => {
Some(Cow::Borrowed("OptimizeStore"))
}
Activity::VerifyPaths(_activity_verify_paths) => Some(Cow::Borrowed("VerifyPaths")),
Activity::Substitute(_activity_substitute) => Some(Cow::Borrowed("Substitute")),
Activity::QueryPathInfo(_activity_query_path_info) => {
Some(Cow::Borrowed("QueryPathInfo"))
}
Activity::PostBuildHook(_activity_post_build_hook) => {
Some(Cow::Borrowed("PostBuildHook"))
}
Activity::BuildWaiting(activity_build_waiting) => Some(Cow::Owned(format!(
"BuildWaiting({:?} | {:?} | {})",
activity_build_waiting.drv_path,
activity_build_waiting.path_resolved,
activity_build_waiting.text
))),
Activity::FetchTree(_activity_fetch_tree) => Some(Cow::Borrowed("FetchTree")),
}
}
2026-03-31 20:02:34 -04:00
pub(crate) fn get_progress_text(&self) -> Option<Cow<'_, str>> {
match self {
Activity::Root(_activity_root) => {
// TODO
panic!("Attempted to get_progress_text of a root activity.");
}
Activity::Unknown(_activity_unknown) => None,
Activity::CopyPath(activity_copy_path) => Some(Cow::Owned(format!(
"[{}/{}]",
activity_copy_path.done, activity_copy_path.expected
))),
Activity::FileTransfer(activity_file_transfer) => Some(Cow::Owned(format!(
"[{}/{}]",
activity_file_transfer.done, activity_file_transfer.expected
))),
Activity::Realize(_activity_realize) => {
// TODO
panic!("Attempted to get_progress_text of a realize activity.");
}
Activity::CopyPaths(activity_copy_paths) => Some(Cow::Owned(format!(
"[{}/{}]",
activity_copy_paths.done, activity_copy_paths.expected
))),
Activity::Builds(activity_builds) => Some(Cow::Owned(format!(
"[{}/{}]",
activity_builds.done, activity_builds.expected
))),
Activity::Build(activity_build) => activity_build
.phase
.as_ref()
.map(|phase| Cow::Owned(format!("[{}]", phase))),
Activity::OptimizeStore(_activity_optimize_store) => {
// TODO
panic!("Attempted to get_progress_text of a optimize store activity.");
}
Activity::VerifyPaths(_activity_verify_paths) => {
// TODO
panic!("Attempted to get_progress_text of a verify paths activity.");
}
Activity::Substitute(_activity_substitute) => {
// TODO
panic!("Attempted to get_progress_text of a substitute activity.");
}
Activity::QueryPathInfo(_activity_query_path_info) => {
// TODO
panic!("Attempted to get_progress_text of a query path info activity.");
}
Activity::PostBuildHook(_activity_post_build_hook) => {
// TODO
panic!("Attempted to get_progress_text of a post build hook activity.");
}
Activity::BuildWaiting(_activity_build_waiting) => {
// TODO
panic!("Attempted to get_progress_text of a build waiting activity.");
}
Activity::FetchTree(_activity_fetch_tree) => {
// TODO
panic!("Attempted to get_progress_text of a fetch tree activity.");
}
}
}
pub(crate) fn set_phase(&mut self, phase: Option<String>) -> () {
match self {
Activity::Root(_activity_root) => {
panic!("Attempted to set the phase of a root activity.");
}
Activity::Unknown(_activity_unknown) => {
panic!("Attempted to set the phase of an unknown activity.");
}
Activity::CopyPath(_activity_copy_path) => {
panic!("Attempted to set the phase of a copy path activity.");
}
Activity::FileTransfer(_activity_file_transfer) => {
panic!("Attempted to set the phase of a file transfer activity.");
}
Activity::Realize(_activity_realize) => {
panic!("Attempted to set the phase of a realize activity.");
}
Activity::CopyPaths(_activity_copy_paths) => {
panic!("Attempted to set the phase of a copy paths activity.");
}
Activity::Builds(_activity_builds) => {
panic!("Attempted to set the phase of a builds activity.");
}
Activity::Build(activity_build) => {
activity_build.phase = phase;
}
Activity::OptimizeStore(_activity_optimize_store) => {
panic!("Attempted to set the phase of an optimize store activity.");
}
Activity::VerifyPaths(_activity_verify_paths) => {
panic!("Attempted to set the phase of a verify paths activity.");
}
Activity::Substitute(_activity_substitute) => {
panic!("Attempted to set the phase of a substitute activity.");
}
Activity::QueryPathInfo(_activity_query_path_info) => {
panic!("Attempted to set the phase of a query path info activity.");
}
Activity::PostBuildHook(_activity_post_build_hook) => {
panic!("Attempted to set the phase of a post build hook activity.");
}
Activity::BuildWaiting(_activity_build_waiting) => {
panic!("Attempted to set the phase of a build waiting activity.");
}
Activity::FetchTree(_activity_fetch_tree) => {
panic!("Attempted to set the phase of a fetch tree activity.");
}
}
}
pub(crate) fn set_progress(
&mut self,
done: u64,
expected: u64,
running: u64,
failed: u64,
) -> () {
match self {
Activity::Root(_activity_root) => {
panic!("Attempted to set the progress of a root activity.");
}
Activity::Unknown(_activity_unknown) => {
panic!("Attempted to set the progress of an unknown activity.");
}
Activity::CopyPath(activity_copy_path) => {
if running != 0 || failed != 0 {
panic!("Attempted to set the progress of a copy path activity.");
}
activity_copy_path.done = done;
activity_copy_path.expected = expected;
}
Activity::FileTransfer(activity_file_transfer) => {
if running != 0 || failed != 0 {
panic!("Attempted to set the progress of a file transfer activity.");
}
activity_file_transfer.done = done;
activity_file_transfer.expected = expected;
}
Activity::Realize(_activity_realize) => {
panic!("Attempted to set the progress of a realize activity.");
}
Activity::CopyPaths(activity_copy_paths) => {
activity_copy_paths.done = done;
activity_copy_paths.expected = expected;
activity_copy_paths.running = running;
activity_copy_paths.failed = failed;
}
Activity::Builds(activity_builds) => {
activity_builds.done = done;
activity_builds.expected = expected;
activity_builds.running = running;
activity_builds.failed = failed;
}
Activity::Build(_activity_build) => {
panic!("Attempted to set the progress of a build activity.");
}
Activity::OptimizeStore(_activity_optimize_store) => {
panic!("Attempted to set the progress of an optimize store activity.");
}
Activity::VerifyPaths(_activity_verify_paths) => {
panic!("Attempted to set the progress of a verify paths activity.");
}
Activity::Substitute(_activity_substitute) => {
panic!("Attempted to set the progress of a substitute activity.");
}
Activity::QueryPathInfo(_activity_query_path_info) => {
panic!("Attempted to set the progress of a query path info activity.");
}
Activity::PostBuildHook(_activity_post_build_hook) => {
panic!("Attempted to set the progress of a post build hook activity.");
}
Activity::BuildWaiting(_activity_build_waiting) => {
panic!("Attempted to set the progress of a build waiting activity.");
}
Activity::FetchTree(_activity_fetch_tree) => {
panic!("Attempted to set the progress of a fetch tree activity.");
}
}
}
pub(crate) fn set_expected(&mut self, expected: u64) -> () {
match self {
Activity::Root(_activity_root) => {
panic!("Attempted to set the expected of a root activity.");
}
Activity::Unknown(_activity_unknown) => {
panic!("Attempted to set the expected of an unknown activity.");
}
Activity::CopyPath(_activity_copy_path) => {
panic!("Attempted to set the expected of a copy path activity.");
}
Activity::FileTransfer(_activity_file_transfer) => {
panic!("Attempted to set the expected of a file transfer activity.");
}
Activity::Realize(_activity_realize) => {
// Seems to always be zero?
if expected != 0 {
panic!("Attempted to set the expected of a realize activity.");
}
}
Activity::CopyPaths(activity_copy_paths) => {
activity_copy_paths.expected = expected;
}
Activity::Builds(_activity_builds) => {
panic!("Attempted to set the expected of a builds activity.");
}
Activity::Build(_activity_build) => {
panic!("Attempted to set the expected of a build activity.");
}
Activity::OptimizeStore(_activity_optimize_store) => {
panic!("Attempted to set the expected of an optimize store activity.");
}
Activity::VerifyPaths(_activity_verify_paths) => {
panic!("Attempted to set the expected of a verify paths activity.");
}
Activity::Substitute(_activity_substitute) => {
panic!("Attempted to set the expected of a substitute activity.");
}
Activity::QueryPathInfo(_activity_query_path_info) => {
panic!("Attempted to set the expected of a query path info activity.");
}
Activity::PostBuildHook(_activity_post_build_hook) => {
panic!("Attempted to set the expected of a post build hook activity.");
}
Activity::BuildWaiting(_activity_build_waiting) => {
panic!("Attempted to set the expected of a build waiting activity.");
}
Activity::FetchTree(_activity_fetch_tree) => {
panic!("Attempted to set the expected of a fetch tree activity.");
}
}
}
}
pub(crate) struct ActivityRoot {}
pub(crate) struct ActivityUnknown {
pub(crate) state: ActivityState,
pub(crate) text: String,
}
pub(crate) struct ActivityCopyPath {
pub(crate) state: ActivityState,
pub(crate) missing_path: String,
/// The machine with the file(s)
pub(crate) source: String,
/// The machine that is receiving the file(s)
pub(crate) destination: String,
pub(crate) done: u64,
pub(crate) expected: u64,
}
pub(crate) struct ActivityFileTransfer {
pub(crate) state: ActivityState,
pub(crate) url: String,
pub(crate) done: u64,
pub(crate) expected: u64,
}
pub(crate) struct ActivityRealize {
pub(crate) state: ActivityState,
}
pub(crate) struct ActivityCopyPaths {
pub(crate) state: ActivityState,
pub(crate) text: String,
pub(crate) done: u64,
pub(crate) expected: u64,
pub(crate) running: u64,
pub(crate) failed: u64,
}
pub(crate) struct ActivityBuilds {
pub(crate) state: ActivityState,
pub(crate) done: u64,
pub(crate) expected: u64,
pub(crate) running: u64,
pub(crate) failed: u64,
}
pub(crate) struct ActivityBuild {
pub(crate) state: ActivityState,
pub(crate) drv_path: String,
pub(crate) machine_name: Option<String>,
pub(crate) phase: Option<String>,
}
pub(crate) struct ActivityOptimizeStore {
pub(crate) state: ActivityState,
}
pub(crate) struct ActivityVerifyPaths {
pub(crate) state: ActivityState,
}
pub(crate) struct ActivitySubstitute {
pub(crate) state: ActivityState,
}
pub(crate) struct ActivityQueryPathInfo {
pub(crate) state: ActivityState,
}
pub(crate) struct ActivityPostBuildHook {
pub(crate) state: ActivityState,
}
pub(crate) struct ActivityBuildWaiting {
pub(crate) state: ActivityState,
pub(crate) text: String,
pub(crate) drv_path: Option<String>,
pub(crate) path_resolved: Option<String>,
}
pub(crate) struct ActivityFetchTree {
pub(crate) state: ActivityState,
}
pub(crate) enum ActivityState {
Started {
progress_numerator: u64,
progress_denominator: u64,
progress_running: u64,
progress_failed: u64,
},
Stopped,
}
impl Default for ActivityState {
fn default() -> Self {
ActivityState::Started {
progress_numerator: 0,
progress_denominator: 0,
progress_running: 0,
progress_failed: 0,
}
}
}