Skip to main content

trellis_testing/
resource_state.rs

1use std::collections::BTreeSet;
2
3use trellis_core::{ResourceCommand, ResourceCommandKind, Revision, ScopeId, TransactionId};
4
5use crate::{HostStatusEvent, ResourceCommandContext};
6
7/// Applied resource command with transaction and generation context.
8#[derive(Clone, Debug, Eq, PartialEq)]
9pub struct ResourceCommandRecord<C = ()> {
10    /// Context common to all resource command assertions.
11    pub context: ResourceCommandContext,
12    /// Retained host command payload for open/replace/refresh commands.
13    pub command: Option<C>,
14}
15
16impl<C: Clone> ResourceCommandRecord<C> {
17    pub(crate) fn from_command(
18        command: &ResourceCommand<C>,
19        transaction_id: TransactionId,
20        revision: Revision,
21        generation: u64,
22    ) -> Self {
23        Self {
24            context: ResourceCommandContext {
25                key: command.key().clone(),
26                scope: command.scope(),
27                transaction_id,
28                revision,
29                generation,
30                kind: resource_command_kind(command),
31            },
32            command: retained_payload(command),
33        }
34    }
35}
36
37/// Current or historical ledger view for one resource key.
38#[derive(Clone, Debug, Eq, PartialEq)]
39pub struct ResourceSnapshot<C = ()> {
40    /// Scopes that currently own the resource.
41    pub owners: BTreeSet<ScopeId>,
42    /// Whether the resource is currently open.
43    pub is_open: bool,
44    /// Number of open commands observed.
45    pub open_count: usize,
46    /// Number of close commands observed.
47    pub close_count: usize,
48    /// Number of replace commands observed.
49    pub replace_count: usize,
50    /// Latest command revision observed for this key.
51    pub command_revision: Revision,
52    /// Monotonic command generation assigned by the ledger.
53    pub generation: u64,
54    /// Last transaction that emitted a command for this key.
55    pub last_transaction_id: TransactionId,
56    /// Last accepted host status revision for this key.
57    pub last_status_revision: Option<Revision>,
58    /// Latest retained host command payload for this key.
59    pub current_command: Option<C>,
60    /// Latest injected host status accepted for this key.
61    pub injected_status: Option<HostStatusEvent>,
62    /// Last applied command record for this key.
63    pub last_command: ResourceCommandRecord<C>,
64}
65
66impl<C: Clone> ResourceSnapshot<C> {
67    pub(crate) fn new(record: ResourceCommandRecord<C>) -> Self {
68        Self {
69            owners: BTreeSet::new(),
70            is_open: true,
71            open_count: 0,
72            close_count: 0,
73            replace_count: 0,
74            command_revision: record.context.revision,
75            generation: record.context.generation,
76            last_transaction_id: record.context.transaction_id,
77            last_status_revision: None,
78            current_command: record.command.clone(),
79            injected_status: None,
80            last_command: record,
81        }
82    }
83
84    pub(crate) fn record_command(&mut self, record: ResourceCommandRecord<C>) {
85        self.command_revision = record.context.revision;
86        self.generation = record.context.generation;
87        self.last_transaction_id = record.context.transaction_id;
88        self.current_command = record.command.clone();
89        self.last_command = record;
90    }
91}
92
93impl<C> ResourceSnapshot<C> {
94    pub(crate) fn command_context(&self) -> ResourceCommandContext {
95        self.last_command.context.clone()
96    }
97}
98
99fn retained_payload<C: Clone>(command: &ResourceCommand<C>) -> Option<C> {
100    match command {
101        ResourceCommand::Open { command, .. }
102        | ResourceCommand::Replace { command, .. }
103        | ResourceCommand::Refresh { command, .. } => Some(command.clone()),
104        ResourceCommand::Close { .. } => None,
105    }
106}
107
108fn resource_command_kind<C>(command: &ResourceCommand<C>) -> ResourceCommandKind {
109    match command {
110        ResourceCommand::Open { .. } => ResourceCommandKind::Open,
111        ResourceCommand::Close { .. } => ResourceCommandKind::Close,
112        ResourceCommand::Replace { .. } => ResourceCommandKind::Replace,
113        ResourceCommand::Refresh { .. } => ResourceCommandKind::Refresh,
114    }
115}