lib: add timestamp to Run

For each Run, the timestamp can be easily tracked using the
operation's timestamp. This field is added to Run to provide more
information to end users.
This commit is contained in:
Fintan Halpenny
2025-12-28 15:15:18 +00:00
parent 525dc9a9e4
commit c2697d7854
+36 -26
View File
@@ -376,28 +376,34 @@ impl Job {
}
}
fn update(&mut self, node: NodeId, uuid: Uuid, reason: Reason) -> bool {
fn update(
&mut self,
node: NodeId,
uuid: Uuid,
reason: Reason,
timestamp: cob::Timestamp,
) -> bool {
let Some(runs) = self.runs.get_mut(&node) else {
return false;
};
let mut updated = false;
runs.0.entry(uuid).and_modify(|run| {
updated = true;
*run = run.clone().finish(reason);
*run = run.clone().finish(reason, timestamp);
});
updated
}
fn action(&mut self, node: NodeId, action: Action) {
fn action(&mut self, node: NodeId, action: Action, timestamp: cob::Timestamp) {
match action {
// Cannot request for another `oid`, so we ignore any superfluous
// request actions
Action::Request { .. } => {}
Action::Run { uuid, log } => {
self.insert(node, uuid, Run::new(log));
self.insert(node, uuid, Run::new(log, timestamp));
}
Action::Finished { uuid, reason } => {
self.update(node, uuid, reason);
self.update(node, uuid, reason, timestamp);
}
}
}
@@ -422,7 +428,7 @@ impl store::Cob for Job {
.map_err(|err| error::Build::MissingCommit { oid, err })?;
let mut runs = Self::new(oid);
for action in actions {
runs.action(op.author, action);
runs.action(op.author, action, op.timestamp);
}
Ok(runs)
}
@@ -434,7 +440,7 @@ impl store::Cob for Job {
_repo: &R,
) -> Result<(), Self::Error> {
for action in op.actions {
self.action(op.author, action);
self.action(op.author, action, op.timestamp);
}
Ok(())
}
@@ -469,7 +475,7 @@ impl<R: ReadRepository> Evaluate<R> for Job {
///
/// The `Run` also contains a [`Url`] so that any extra metadata, for example
/// logs, can be tracked outside of the `Run` itself.
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct Run {
/// The status of the run.
///
@@ -480,23 +486,27 @@ pub struct Run {
status: Status,
/// The [`Url`] of the [`Run`] where information is logged by the node.
log: Url,
/// The timestamp of the last operation to affect the run.
timestamp: cob::Timestamp,
}
impl Run {
/// Create a new `Run` with a [`Url`] that ideally points to the log of that
/// process.
pub fn new(log: Url) -> Self {
pub fn new(log: Url, timestamp: cob::Timestamp) -> Self {
Self {
status: Status::Started,
log,
timestamp,
}
}
/// Mark the `Run` as finished.
fn finish(self, reason: Reason) -> Self {
fn finish(self, reason: Reason, timestamp: cob::Timestamp) -> Self {
Self {
status: Status::Finished(reason),
log: self.log,
timestamp,
}
}
@@ -510,6 +520,11 @@ impl Run {
&self.status
}
/// Return the timestamp of the last update to the `Run`.
pub fn timestamp(&self) -> &cob::Timestamp {
&self.timestamp
}
/// Returns `true` if the status of the `Run` is [`Status::Started`].
pub fn is_started(&self) -> bool {
match self.status {
@@ -909,23 +924,17 @@ mod test {
let (bob_uuid, bob_log) = node_run();
job.run(bob_uuid, bob_log.clone(), &bob.signer).unwrap();
let alice_runs = job.runs_of(alice.signer.public_key());
assert!(alice_runs.is_some());
assert_eq!(
*alice_runs.unwrap(),
[(alice_uuid, Run::new(alice_log))]
.into_iter()
.collect::<Runs>()
);
let alice_runs = job.runs_of(alice.signer.public_key()).unwrap();
assert!(alice_runs.contains_key(&alice_uuid));
let run = alice_runs.get(&alice_uuid).unwrap();
assert_eq!(run.status, Status::Started);
assert_eq!(run.log, alice_log);
let bob_runs = job.runs_of(bob.signer.public_key());
assert!(bob_runs.is_some());
assert_eq!(
*bob_runs.unwrap(),
[(bob_uuid, Run::new(bob_log))]
.into_iter()
.collect::<Runs>()
);
let bob_runs = job.runs_of(bob.signer.public_key()).unwrap();
assert!(bob_runs.contains_key(&bob_uuid));
let run = bob_runs.get(&bob_uuid).unwrap();
assert_eq!(run.status, Status::Started);
assert_eq!(run.log, bob_log);
job.finish(alice_uuid, Reason::Succeeded, &alice.signer)
.unwrap();
@@ -987,6 +996,7 @@ mod test {
Run {
status: Status::Started,
log: Url::parse("https://example.com/ci/logs").unwrap(),
timestamp: radicle::cob::Timestamp::from_secs(1358182),
},
);
}