ferrum_interfaces/vnext/operation/
compiled_identity.rs1use serde::Serialize;
2use std::sync::Arc;
3
4use super::super::{
5 DeviceId, ExecutionIdentityEnvelope, ExecutionIdentityParts, ExecutionLaneId, NodeId,
6 NodeInvocationId, OperationId, PlanHash, PlanId, ProviderId, RequestIdentity, ResourcePoolId,
7 RunId, SpanId, StepParticipantFrameAssignment, TransactionId, EXECUTION_IDENTITY_VERSION,
8};
9use super::ProviderExecutionSemantics;
10
11#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
12pub(super) struct CompiledSubmissionWaveNodeIdentityTemplate {
13 node_index: u32,
14 node_id: NodeId,
15 operation_id: OperationId,
16 provider_id: ProviderId,
17 provider_implementation_fingerprint: String,
18 provider_execution_semantics: ProviderExecutionSemantics,
19}
20
21impl CompiledSubmissionWaveNodeIdentityTemplate {
22 pub(super) fn new(
23 node_index: u32,
24 node_id: NodeId,
25 operation_id: OperationId,
26 provider_id: ProviderId,
27 provider_implementation_fingerprint: String,
28 provider_execution_semantics: ProviderExecutionSemantics,
29 ) -> Self {
30 Self {
31 node_index,
32 node_id,
33 operation_id,
34 provider_id,
35 provider_implementation_fingerprint,
36 provider_execution_semantics,
37 }
38 }
39
40 pub(super) const fn node_index(&self) -> u32 {
41 self.node_index
42 }
43
44 pub(super) fn node_id(&self) -> &NodeId {
45 &self.node_id
46 }
47
48 pub(super) fn operation_id(&self) -> &OperationId {
49 &self.operation_id
50 }
51
52 pub(super) fn provider_id(&self) -> &ProviderId {
53 &self.provider_id
54 }
55
56 pub(super) fn provider_implementation_fingerprint(&self) -> &str {
57 &self.provider_implementation_fingerprint
58 }
59
60 pub(super) const fn provider_execution_semantics(&self) -> ProviderExecutionSemantics {
61 self.provider_execution_semantics
62 }
63}
64
65#[derive(Debug, PartialEq, Eq, Serialize)]
66struct CompiledSubmissionWaveIdentityData {
67 plan_id: PlanId,
68 plan_hash: PlanHash,
69 device_id: DeviceId,
70 runtime_implementation_fingerprint: String,
71 lane_id: ExecutionLaneId,
72 nodes: Vec<CompiledSubmissionWaveNodeIdentityTemplate>,
73 fingerprint: String,
74}
75
76#[derive(Debug, Clone, PartialEq, Eq)]
82pub struct CompiledSubmissionWaveIdentity {
83 data: Arc<CompiledSubmissionWaveIdentityData>,
84}
85
86impl CompiledSubmissionWaveIdentity {
87 #[allow(clippy::too_many_arguments)]
88 pub(super) fn from_validated(
89 plan_id: PlanId,
90 plan_hash: PlanHash,
91 device_id: DeviceId,
92 runtime_implementation_fingerprint: String,
93 lane_id: ExecutionLaneId,
94 nodes: Vec<CompiledSubmissionWaveNodeIdentityTemplate>,
95 fingerprint: String,
96 ) -> Self {
97 Self {
98 data: Arc::new(CompiledSubmissionWaveIdentityData {
99 plan_id,
100 plan_hash,
101 device_id,
102 runtime_implementation_fingerprint,
103 lane_id,
104 nodes,
105 fingerprint,
106 }),
107 }
108 }
109
110 pub fn plan_id(&self) -> &PlanId {
111 &self.data.plan_id
112 }
113
114 pub fn plan_hash(&self) -> &PlanHash {
115 &self.data.plan_hash
116 }
117
118 pub fn device_id(&self) -> &DeviceId {
119 &self.data.device_id
120 }
121
122 pub fn runtime_implementation_fingerprint(&self) -> &str {
123 &self.data.runtime_implementation_fingerprint
124 }
125
126 pub fn lane_id(&self) -> ExecutionLaneId {
127 self.data.lane_id
128 }
129
130 pub fn node_count(&self) -> usize {
131 self.data.nodes.len()
132 }
133
134 pub fn fingerprint(&self) -> &str {
135 &self.data.fingerprint
136 }
137
138 pub(super) fn node_id_at(&self, node_index: usize) -> Option<&NodeId> {
139 self.data.nodes.get(node_index).map(|node| &node.node_id)
140 }
141
142 pub(super) fn node_at(
143 &self,
144 node_index: usize,
145 ) -> Option<&CompiledSubmissionWaveNodeIdentityTemplate> {
146 self.data.nodes.get(node_index)
147 }
148
149 pub(super) fn operation_id_at(&self, node_index: usize) -> Option<&OperationId> {
150 self.data
151 .nodes
152 .get(node_index)
153 .map(|node| &node.operation_id)
154 }
155
156 pub(super) fn provider_id_at(&self, node_index: usize) -> Option<&ProviderId> {
157 self.data
158 .nodes
159 .get(node_index)
160 .map(|node| &node.provider_id)
161 }
162
163 pub(super) fn node_index(&self, node_id: &NodeId) -> Option<usize> {
164 self.data
165 .nodes
166 .iter()
167 .position(|node| &node.node_id == node_id)
168 }
169}
170
171#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
172pub(super) struct SubmissionWaveParticipantIdentitySeed {
173 frame: StepParticipantFrameAssignment,
174 run_id: RunId,
175 request_id: RequestIdentity,
176 resource_pool_id: Option<ResourcePoolId>,
177 resource_pool_identity_fingerprint: Option<String>,
178 provisioning_run_id: Option<RunId>,
179 provisioning_request_id: Option<RequestIdentity>,
180 transaction_id: Option<TransactionId>,
181 active_sequence_slot: u32,
182 admission_generation: u64,
183 activation_epoch: u64,
184 runtime_implementation_fingerprint: String,
185 active_sequence_fingerprint: String,
186 span_root: String,
187}
188
189impl SubmissionWaveParticipantIdentitySeed {
190 #[allow(clippy::too_many_arguments)]
191 pub(super) fn new(
192 frame: StepParticipantFrameAssignment,
193 run_id: RunId,
194 request_id: RequestIdentity,
195 resource_pool_id: Option<ResourcePoolId>,
196 resource_pool_identity_fingerprint: Option<String>,
197 provisioning_run_id: Option<RunId>,
198 provisioning_request_id: Option<RequestIdentity>,
199 transaction_id: Option<TransactionId>,
200 active_sequence_slot: u32,
201 admission_generation: u64,
202 activation_epoch: u64,
203 runtime_implementation_fingerprint: String,
204 active_sequence_fingerprint: String,
205 span_root: String,
206 ) -> Self {
207 Self {
208 frame,
209 run_id,
210 request_id,
211 resource_pool_id,
212 resource_pool_identity_fingerprint,
213 provisioning_run_id,
214 provisioning_request_id,
215 transaction_id,
216 active_sequence_slot,
217 admission_generation,
218 activation_epoch,
219 runtime_implementation_fingerprint,
220 active_sequence_fingerprint,
221 span_root,
222 }
223 }
224
225 pub(super) const fn frame(&self) -> StepParticipantFrameAssignment {
226 self.frame
227 }
228
229 pub(super) fn runtime_implementation_fingerprint(&self) -> &str {
230 &self.runtime_implementation_fingerprint
231 }
232
233 pub(super) fn operation_identity(
234 &self,
235 topology: &CompiledSubmissionWaveIdentity,
236 node_index: usize,
237 ) -> Option<ExecutionIdentityEnvelope> {
238 let node = topology.data.nodes.get(node_index)?;
239 let topology = topology.data.as_ref();
240 let node_count = u64::try_from(topology.nodes.len())
241 .expect("compiled submission-wave node count fits u64");
242 let node_index = u64::from(node.node_index);
243 let completed_frames = self.frame.frame_id().get() - 1;
244 let node_invocation = completed_frames
245 .checked_mul(node_count)
246 .and_then(|value| value.checked_add(node_index))
247 .and_then(|value| value.checked_add(1))
248 .expect("compiled submission-wave invocation range was validated");
249 let node_invocation_id = NodeInvocationId::try_from(node_invocation)
250 .expect("compiled submission-wave invocation id is non-zero");
251 let events_per_frame = node_count
252 .checked_mul(3)
253 .and_then(|value| value.checked_add(2))
254 .expect("compiled submission-wave event range was validated");
255 let sequence = completed_frames
256 .checked_mul(events_per_frame)
257 .and_then(|value| value.checked_add(node_index.checked_mul(3)?))
258 .and_then(|value| value.checked_add(5))
259 .expect("compiled submission-wave event sequence was validated");
260 let node_span = SpanId::new(format!(
261 "{}/frame/{}/node/{node_invocation}",
262 self.span_root,
263 self.frame.frame_id()
264 ))
265 .expect("compiled submission-wave node span is portable");
266 let operation_span = SpanId::new(format!("{node_span}/operation"))
267 .expect("compiled submission-wave operation span is portable");
268
269 Some(
270 ExecutionIdentityEnvelope::new(ExecutionIdentityParts {
271 version: EXECUTION_IDENTITY_VERSION,
272 run_id: self.run_id.clone(),
273 request_id: self.request_id.clone(),
274 sequence,
275 plan_id: Some(topology.plan_id.clone()),
276 plan_hash: Some(topology.plan_hash.clone()),
277 frame_id: Some(self.frame.frame_id()),
278 node_invocation_id: Some(node_invocation_id),
279 node_id: Some(node.node_id.clone()),
280 operation_id: Some(node.operation_id.clone()),
281 provider_id: Some(node.provider_id.clone()),
282 device_id: Some(topology.device_id.clone()),
283 resource_pool_id: self.resource_pool_id.clone(),
284 resource_pool_identity_fingerprint: self.resource_pool_identity_fingerprint.clone(),
285 provisioning_run_id: self.provisioning_run_id.clone(),
286 provisioning_request_id: self.provisioning_request_id.clone(),
287 transaction_id: self.transaction_id.clone(),
288 active_sequence_slot: Some(self.active_sequence_slot),
289 admission_generation: Some(self.admission_generation),
290 activation_epoch: Some(self.activation_epoch),
291 runtime_implementation_fingerprint: Some(
292 self.runtime_implementation_fingerprint.clone(),
293 ),
294 active_sequence_fingerprint: Some(self.active_sequence_fingerprint.clone()),
295 completed_sequence_fingerprint: None,
296 aborted_sequence_fingerprint: None,
297 resource_id: None,
298 resource_generation: None,
299 resource_batch_fingerprint: None,
300 span_id: operation_span,
301 parent_span_id: Some(node_span),
302 async_links: Vec::new(),
303 })
304 .expect("compiled submission-wave participant seed is a valid operation identity"),
305 )
306 }
307}