1use crate::{CallContext, DbScopeDiagnosticIdentity};
4use serde::{Serialize, Serializer, ser::SerializeStruct};
5use std::sync::{
6 Arc, OnceLock,
7 atomic::{AtomicU64, Ordering},
8};
9
10static NEXT_ROOT: AtomicU64 = AtomicU64::new(1);
11
12#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize)]
14#[serde(tag = "state", content = "value", rename_all = "snake_case")]
15pub enum ContextFact<T> {
16 Present(T),
17 NotApplicable,
18 NotEstablished,
19 Unavailable,
20}
21
22#[derive(Clone, Copy, Eq, PartialEq)]
24pub struct ContextIdentity {
25 bytes: [u8; 256],
26 len: u16,
27}
28impl ContextIdentity {
29 pub fn checked(value: &str) -> Result<Self, ContextConflict> {
30 if value.is_empty() || value.len() > 256 || value.chars().any(char::is_control) {
31 return Err(ContextConflict::InvalidIdentity);
32 }
33 let mut out = Self {
34 bytes: [0; 256],
35 len: value.len() as u16,
36 };
37 out.bytes[..value.len()].copy_from_slice(value.as_bytes());
38 Ok(out)
39 }
40 fn as_str(&self) -> &str {
41 std::str::from_utf8(&self.bytes[..usize::from(self.len)]).expect("validated UTF-8")
42 }
43}
44impl Serialize for ContextIdentity {
45 fn serialize<S: Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
46 s.serialize_str(self.as_str())
47 }
48}
49
50#[derive(Clone, Copy, Eq, PartialEq, Serialize)]
52#[serde(transparent)]
53pub struct ContextLabel(ContextIdentity);
54impl ContextLabel {
55 pub fn checked(value: &str) -> Result<Self, ContextConflict> {
56 let value = ContextIdentity::checked(value)?;
57 if value.as_str().contains("://")
58 || !value
59 .as_str()
60 .chars()
61 .all(|c| c.is_alphanumeric() || "_.:/{}*-".contains(c))
62 {
63 return Err(ContextConflict::UnsafeMetadata);
64 }
65 Ok(Self(value))
66 }
67}
68
69#[derive(Clone, Copy, Debug, Eq, PartialEq)]
70pub enum ContextConflict {
71 InvalidIdentity,
72 UnsafeMetadata,
73 IdentityGroup,
74 ForeignRoot,
75 ChildRelation,
76 CounterExhausted,
77}
78
79#[derive(Eq, PartialEq)]
82pub struct RequestIdentityGroup {
83 application: ContextLabel,
84 module: ContextLabel,
85 service: ContextLabel,
86 operation: ContextLabel,
87 trace: ContextIdentity,
88 rpc: ContextFact<ContextIdentity>,
89 span: u64,
90 request: ContextIdentity,
91 route: ContextLabel,
92 attempt: u32,
93 zone: ContextFact<ContextLabel>,
94}
95impl RequestIdentityGroup {
96 pub fn from_validated(
97 call: &CallContext,
98 request: &str,
99 route: &str,
100 attempt: u32,
101 zone: ContextFact<ContextLabel>,
102 ) -> Result<Self, ContextConflict> {
103 if attempt == 0 {
104 return Err(ContextConflict::InvalidIdentity);
105 }
106 Ok(Self {
107 application: ContextLabel::checked(call.application().as_str())?,
108 module: ContextLabel::checked(call.module().as_str())?,
109 service: ContextLabel::checked(call.service().as_str())?,
110 operation: ContextLabel::checked(call.operation().as_str())?,
111 trace: ContextIdentity::checked(call.trace_correlation_id().as_str())?,
112 rpc: match call.rpc_correlation_id() {
113 Some(id) => ContextFact::Present(ContextIdentity::checked(id.as_str())?),
114 None => ContextFact::Unavailable,
115 },
116 span: call.span_id().as_u64(),
117 request: ContextIdentity::checked(request)?,
118 route: ContextLabel::checked(route)?,
119 attempt,
120 zone,
121 })
122 }
123}
124
125struct RequestRoot {
126 local: u64,
127 application: ContextLabel,
128 initial: ContextFact<()>,
129 identity: OnceLock<RequestIdentityGroup>,
130}
131impl Drop for RequestRoot {
132 fn drop(&mut self) {
133 observe(self.local, "root_drop");
134 }
135}
136
137pub struct RequestRootPublisher {
144 root: Arc<RequestRoot>,
145}
146
147pub struct RequestRootRef {
149 root: Arc<RequestRoot>,
150}
151impl Clone for RequestRootRef {
152 fn clone(&self) -> Self {
153 observe(self.root.local, "root_share");
154 Self {
155 root: Arc::clone(&self.root),
156 }
157 }
158}
159impl Drop for RequestRootRef {
160 fn drop(&mut self) {
161 observe(self.root.local, "root_release");
162 }
163}
164
165impl RequestRootPublisher {
166 pub fn create(
169 application: ContextLabel,
170 initial: ContextFact<()>,
171 ) -> Result<Self, ContextConflict> {
172 if matches!(initial, ContextFact::Present(())) {
173 return Err(ContextConflict::InvalidIdentity);
174 }
175 let local = NEXT_ROOT
176 .fetch_update(Ordering::Relaxed, Ordering::Relaxed, |n| n.checked_add(1))
177 .map_err(|_| ContextConflict::CounterExhausted)?;
178 let root = Arc::new(RequestRoot {
179 local,
180 application,
181 initial,
182 identity: OnceLock::new(),
183 });
184 observe(local, "root_create");
185 Ok(Self { root })
186 }
187 pub fn reference(&self) -> RequestRootRef {
188 observe(self.root.local, "root_share");
189 RequestRootRef {
190 root: Arc::clone(&self.root),
191 }
192 }
193 #[allow(clippy::result_large_err)] pub fn publish(
195 &mut self,
196 group: RequestIdentityGroup,
197 ) -> Result<(), (ContextConflict, RequestIdentityGroup)> {
198 if group.application != self.root.application {
199 return Err((ContextConflict::IdentityGroup, group));
200 }
201 if let Some(old) = self.root.identity.get() {
202 return if old == &group {
203 Ok(())
204 } else {
205 Err((ContextConflict::IdentityGroup, group))
206 };
207 }
208 self.root
209 .identity
210 .set(group)
211 .map_err(|group| (ContextConflict::IdentityGroup, group))
212 }
213}
214
215#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize)]
217#[serde(rename_all = "snake_case")]
218pub enum RequestViewPhase {
219 SocketAccepted,
220 Reading,
221 Admitted,
222 Dispatch,
223 Handler,
224 Database,
225 Outbound,
226 Response,
227 Finalizing,
228 Finished,
229}
230
231#[derive(Clone, Copy, Eq, PartialEq, Serialize)]
233pub struct RegisteredContextOperation(&'static str);
234impl RegisteredContextOperation {
235 pub fn checked(value: &'static str) -> Result<Self, ContextConflict> {
236 ContextLabel::checked(value)?;
237 Ok(Self(value))
238 }
239}
240
241#[derive(Clone, Copy)]
242pub struct RequestLocalFacts {
243 task: ContextFact<u64>,
244 scope: ContextFact<DbScopeDiagnosticIdentity>,
245 db_operation: ContextFact<RegisteredContextOperation>,
246 phase: RequestViewPhase,
247}
248impl RequestLocalFacts {
249 pub fn new(phase: RequestViewPhase) -> Self {
250 Self {
251 task: ContextFact::NotEstablished,
252 scope: ContextFact::NotEstablished,
253 db_operation: ContextFact::NotApplicable,
254 phase,
255 }
256 }
257 pub fn with_task(mut self, task: ContextFact<u64>) -> Self {
259 self.task = task;
260 self
261 }
262 pub fn without_scope(mut self, state: ContextFact<()>) -> Self {
263 self.scope = absent(state);
264 self
265 }
266 pub fn with_db_operation(mut self, operation: RegisteredContextOperation) -> Self {
267 self.db_operation = ContextFact::Present(operation);
268 self
269 }
270}
271
272struct ChildCall {
275 #[cfg(test)]
276 observation: LocalObservation,
277 application: ContextLabel,
278 module: ContextLabel,
279 service: ContextLabel,
280 operation: ContextLabel,
281 rpc: ContextIdentity,
282 span: u64,
283 route: ContextLabel,
284 attempt: u32,
285}
286struct LocalView {
287 #[cfg(test)]
288 observation: LocalObservation,
289 root: Arc<RequestRoot>,
290 published: bool,
291 facts: RequestLocalFacts,
292 child: Option<Arc<ChildCall>>,
293}
294impl Drop for LocalView {
295 fn drop(&mut self) {
296 observe(self.root.local, "view_drop");
297 #[cfg(test)]
298 self.observation.record("destroy");
299 }
300}
301impl Drop for ChildCall {
302 fn drop(&mut self) {
303 #[cfg(test)]
304 self.observation.record("destroy");
305 }
306}
307
308pub struct RequestExecutionView {
316 inner: Arc<LocalView>,
317}
318
319#[derive(Clone, Copy, Serialize)]
322pub struct RequestContextSnapshot {
323 schema_version: u8,
324 local_request: u64,
325 publication: u8,
326 application: ContextFact<ContextLabel>,
327 call_application: ContextFact<ContextLabel>,
328 module: ContextFact<ContextLabel>,
329 service: ContextFact<ContextLabel>,
330 operation: ContextFact<ContextLabel>,
331 trace_id: ContextFact<ContextIdentity>,
332 request: ContextFact<ContextIdentity>,
333 span_id: ContextFact<SpanProjection>,
334 route: ContextFact<ContextLabel>,
335 attempt: ContextFact<u32>,
336 rpc_id: ContextFact<ContextIdentity>,
337 zone: ContextFact<ContextLabel>,
338 db_operation: ContextFact<RegisteredContextOperation>,
339 scope: ContextFact<DbScopeDiagnosticIdentity>,
340 task: ContextFact<u64>,
341 lifecycle: ContextFact<RequestViewPhase>,
342 target: ContextFact<ContextLabel>,
343}
344pub struct OutboundSourceContext<'a> {
347 view: &'a RequestExecutionView,
348 business_unit: &'a str,
349}
350impl Clone for RequestExecutionView {
351 fn clone(&self) -> Self {
352 #[cfg(test)]
353 self.inner.observation.record("share");
354 Self {
355 inner: Arc::clone(&self.inner),
356 }
357 }
358}
359impl Drop for RequestExecutionView {
360 fn drop(&mut self) {
361 #[cfg(test)]
362 self.inner.observation.record("release");
363 }
364}
365impl RequestRootRef {
366 pub fn view(&self, facts: RequestLocalFacts) -> RequestExecutionView {
367 RequestExecutionView::allocate(
368 Arc::clone(&self.root),
369 self.root.identity.get().is_some(),
370 facts,
371 None,
372 )
373 }
374 pub fn same_request(&self, view: &RequestExecutionView) -> bool {
375 Arc::ptr_eq(&self.root, &view.inner.root)
376 }
377}
378impl RequestExecutionView {
379 pub fn diagnostic_snapshot(&self) -> RequestContextSnapshot {
380 let identity = self.identity();
381 let child = self.inner.child.as_deref();
382 let initial = self.inner.root.initial;
383 macro_rules! root {
384 ($field:ident) => { identity.map_or_else(|| absent(initial), |g| ContextFact::Present(g.$field)) };
385 }
386 macro_rules! call {
387 ($field:ident) => { child.map(|c| c.$field).or_else(|| identity.map(|g| g.$field))
388 .map_or_else(|| absent(initial), ContextFact::Present) };
389 }
390 RequestContextSnapshot {
391 schema_version: 2,
392 local_request: self.inner.root.local,
393 publication: u8::from(self.inner.published),
394 application: ContextFact::Present(self.inner.root.application),
395 call_application: ContextFact::Present(child.map_or(self.inner.root.application, |c| c.application)),
396 module: call!(module), service: call!(service), operation: call!(operation),
397 trace_id: root!(trace), request: root!(request),
398 span_id: child.map(|c| c.span).or_else(|| identity.map(|g| g.span))
399 .map_or_else(|| absent(initial), |span| ContextFact::Present(SpanProjection(span))),
400 route: call!(route), attempt: call!(attempt),
401 rpc_id: child.map(|c| ContextFact::Present(c.rpc)).or_else(|| identity.map(|g| g.rpc))
402 .unwrap_or_else(|| absent(initial)),
403 zone: identity.map_or_else(|| absent(initial), |g| g.zone),
404 db_operation: self.inner.facts.db_operation, scope: self.inner.facts.scope,
405 task: self.inner.facts.task, lifecycle: ContextFact::Present(self.inner.facts.phase),
406 target: child.map_or(ContextFact::NotApplicable, |c| ContextFact::Present(c.route)),
407 }
408 }
409 pub fn outbound_source_context<'a>(&'a self, business_unit: &'a str) -> OutboundSourceContext<'a> {
410 OutboundSourceContext { view: self, business_unit }
411 }
412 fn allocate(
413 root: Arc<RequestRoot>,
414 published: bool,
415 facts: RequestLocalFacts,
416 child: Option<Arc<ChildCall>>,
417 ) -> Self {
418 observe(root.local, "view_create");
419 Self {
420 inner: Arc::new(LocalView {
421 #[cfg(test)]
422 observation: LocalObservation::create(root.local, "view"),
423 root,
424 published,
425 facts,
426 child,
427 }),
428 }
429 }
430 fn local(&self, facts: RequestLocalFacts) -> Self {
432 Self::allocate(
433 Arc::clone(&self.inner.root),
434 self.inner.published,
435 facts,
436 self.inner.child.clone(),
437 )
438 }
439 pub fn with_phase(&self, phase: RequestViewPhase) -> Self {
440 let mut facts = self.inner.facts;
441 facts.phase = phase;
442 self.local(facts)
443 }
444 pub fn with_db_operation(&self, operation: RegisteredContextOperation) -> Self {
445 self.local(self.inner.facts.with_db_operation(operation))
446 }
447 pub fn in_task(&self, task: u64) -> Self {
450 self.local(self.inner.facts.with_task(ContextFact::Present(task)))
451 }
452 pub fn in_db_scope(
453 &self,
454 scope: &crate::DbScopeDiagnosticContext<Self>,
455 ) -> Result<Self, ContextConflict> {
456 let (original, identity) = scope.diagnostic_context();
457 if !self.same_request(original) {
458 return Err(ContextConflict::ForeignRoot);
459 }
460 let mut facts = self.inner.facts;
461 facts.scope = ContextFact::Present(identity);
462 Ok(self.local(facts))
463 }
464 pub fn observed_db_scope(
465 &self,
466 scope: &crate::DbScopeObservation<Self>,
467 ) -> Result<Self, ContextConflict> {
468 let (original, identity) = scope.diagnostic_context();
469 if !self.same_request(original) {
470 return Err(ContextConflict::ForeignRoot);
471 }
472 let mut facts = self.inner.facts;
473 facts.scope = ContextFact::Present(identity);
474 Ok(self.local(facts))
475 }
476 pub fn same_request(&self, other: &Self) -> bool {
477 Arc::ptr_eq(&self.inner.root, &other.inner.root)
478 }
479 pub fn same_view(&self, other: &Self) -> bool {
480 Arc::ptr_eq(&self.inner, &other.inner)
481 }
482 pub fn refresh(&self, root: &RequestRootRef) -> Result<Self, ContextConflict> {
484 if !root.same_request(self) {
485 return Err(ContextConflict::ForeignRoot);
486 }
487 Ok(Self::allocate(
488 Arc::clone(&self.inner.root),
489 self.inner.root.identity.get().is_some(),
490 self.inner.facts,
491 self.inner.child.clone(),
492 ))
493 }
494 pub fn child(
495 &self,
496 call: &CallContext,
497 request: &str,
498 route: &str,
499 attempt: u32,
500 ) -> Result<Self, ContextConflict> {
501 let identity = self.identity().ok_or(ContextConflict::ChildRelation)?;
502 if identity.trace.as_str() != call.trace_correlation_id().as_str()
503 || identity.request.as_str() != request
504 {
505 return Err(ContextConflict::ForeignRoot);
506 }
507 let parent_rpc = if let Some(child) = &self.inner.child {
508 &child.rpc
509 } else if let ContextFact::Present(rpc) = &identity.rpc {
510 rpc
511 } else {
512 return Err(ContextConflict::ChildRelation);
513 };
514 let rpc = call
515 .rpc_correlation_id()
516 .ok_or(ContextConflict::ChildRelation)?;
517 let suffix = rpc
518 .as_str()
519 .strip_prefix(parent_rpc.as_str())
520 .and_then(|s| s.strip_prefix('.'))
521 .ok_or(ContextConflict::ChildRelation)?;
522 let span = self
523 .inner
524 .child
525 .as_ref()
526 .map_or(identity.span, |child| child.span);
527 if suffix.is_empty()
528 || !suffix.bytes().all(|b| b.is_ascii_digit())
529 || span == call.span_id().as_u64()
530 || attempt == 0
531 {
532 return Err(ContextConflict::ChildRelation);
533 }
534 let child = Arc::new(ChildCall {
535 application: ContextLabel::checked(call.application().as_str())?,
536 module: ContextLabel::checked(call.module().as_str())?,
537 service: ContextLabel::checked(call.service().as_str())?,
538 operation: ContextLabel::checked(call.operation().as_str())?,
539 rpc: ContextIdentity::checked(rpc.as_str())?,
540 span: call.span_id().as_u64(),
541 route: ContextLabel::checked(route)?,
542 attempt,
543 #[cfg(test)]
544 observation: LocalObservation::create(self.inner.root.local, "child"),
545 });
546 Ok(Self::allocate(
547 Arc::clone(&self.inner.root),
548 self.inner.published,
549 self.inner.facts,
550 Some(child),
551 ))
552 }
553 fn identity(&self) -> Option<&RequestIdentityGroup> {
554 self.inner
555 .published
556 .then(|| self.inner.root.identity.get())
557 .flatten()
558 }
559}
560
561fn absent<T>(state: ContextFact<()>) -> ContextFact<T> {
562 match state {
563 ContextFact::NotApplicable => ContextFact::NotApplicable,
564 ContextFact::NotEstablished => ContextFact::NotEstablished,
565 _ => ContextFact::Unavailable,
566 }
567}
568impl Serialize for RequestExecutionView {
569 fn serialize<S: Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
570 self.serialize_context(s, None)
571 }
572}
573impl Serialize for OutboundSourceContext<'_> {
574 fn serialize<S: Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
575 self.view.serialize_context(s, Some(self.business_unit))
576 }
577}
578impl RequestExecutionView {
579 fn serialize_context<S: Serializer>(&self, s: S, business_unit: Option<&str>) -> Result<S::Ok, S::Error> {
580 let mut out = s.serialize_struct("RequestContext", 21 + usize::from(business_unit.is_some()))?;
581 let identity = self.identity();
582 let child = self.inner.child.as_deref();
583 let initial = self.inner.root.initial;
584 out.serialize_field("schema_version", &2u8)?;
585 out.serialize_field("local_request", &self.inner.root.local)?;
586 out.serialize_field("publication", &u8::from(self.inner.published))?;
587 out.serialize_field(
588 "application",
589 &ContextFact::Present(&self.inner.root.application),
590 )?;
591 out.serialize_field(
592 "call_application",
593 &ContextFact::Present(child.map_or(&self.inner.root.application, |c| &c.application)),
594 )?;
595 macro_rules! root_field {
596 ($name:literal, $field:ident) => {
597 out.serialize_field(
598 $name,
599 &identity.map_or_else(|| absent(initial), |g| ContextFact::Present(&g.$field)),
600 )?;
601 };
602 }
603 macro_rules! call_field {
604 ($name:literal, $field:ident) => {
605 out.serialize_field(
606 $name,
607 &child
608 .map(|c| &c.$field)
609 .or_else(|| identity.map(|g| &g.$field))
610 .map_or_else(|| absent(initial), ContextFact::Present),
611 )?;
612 };
613 }
614 call_field!("module", module);
615 call_field!("service", service);
616 call_field!("operation", operation);
617 root_field!("trace_id", trace);
618 root_field!("request", request);
619 let span = child.map(|c| c.span).or_else(|| identity.map(|g| g.span));
620 out.serialize_field(
621 "span_id",
622 &span.map_or_else(
623 || absent(initial),
624 |s| ContextFact::Present(SpanProjection(s)),
625 ),
626 )?;
627 call_field!("route", route);
628 call_field!("attempt", attempt);
629 let rpc = child
630 .map(|c| ContextFact::Present(c.rpc))
631 .or_else(|| identity.map(|g| g.rpc))
632 .unwrap_or_else(|| absent(initial));
633 out.serialize_field("rpc_id", &rpc)?;
634 out.serialize_field(
635 "zone",
636 &identity.map_or_else(|| absent(initial), |g| g.zone),
637 )?;
638 out.serialize_field("db_operation", &self.inner.facts.db_operation)?;
639 out.serialize_field("scope", &self.inner.facts.scope)?;
640 out.serialize_field("task", &self.inner.facts.task)?;
641 out.serialize_field("lifecycle", &ContextFact::Present(self.inner.facts.phase))?;
642 out.serialize_field(
644 "target",
645 &child.map_or(ContextFact::NotApplicable, |c| {
646 ContextFact::Present(&c.route)
647 }),
648 )?;
649 if let Some(business_unit) = business_unit {
650 out.serialize_field("business_unit", &ContextFact::Present(business_unit))?;
651 }
652 out.end()
653 }
654}
655
656pub fn request_context_layouts() -> [(std::alloc::Layout, std::alloc::Layout); 3] {
660 fn pair<T>() -> (std::alloc::Layout, std::alloc::Layout) {
661 let payload = std::alloc::Layout::new::<T>();
662 let header = std::alloc::Layout::new::<[std::sync::atomic::AtomicUsize; 2]>();
663 (
664 payload,
665 header
666 .extend(payload)
667 .expect("fixed layout")
668 .0
669 .pad_to_align(),
670 )
671 }
672 [
673 pair::<RequestRoot>(),
674 pair::<LocalView>(),
675 pair::<ChildCall>(),
676 ]
677}
678
679#[cfg(not(test))]
680fn observe(_: u64, _: &'static str) {}
681#[cfg(test)]
682fn observe(root: u64, event: &'static str) {
683 EVENTS.lock().unwrap().push((root, event));
684 record_observation(root, root, "root", event);
685}
686#[cfg(test)]
687static EVENTS: std::sync::Mutex<Vec<(u64, &'static str)>> = std::sync::Mutex::new(Vec::new());
688
689#[derive(Clone, Copy)]
690struct SpanProjection(u64);
691impl Serialize for SpanProjection {
692 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
693 let mut bytes = [b'0'; 16];
694 for (i, byte) in bytes.iter_mut().enumerate() {
695 *byte = b"0123456789abcdef"[((self.0 >> ((15 - i) * 4)) & 15) as usize];
696 }
697 serializer.serialize_str(std::str::from_utf8(&bytes).expect("hex"))
698 }
699}
700
701#[cfg(test)]
704struct LocalObservation {
705 id: u64,
706 root: u64,
707 kind: &'static str,
708}
709#[cfg(test)]
710static LOCAL_EVENTS: std::sync::Mutex<Vec<(u64, u64, &'static str, &'static str)>> =
711 std::sync::Mutex::new(Vec::new());
712#[cfg(test)]
713impl LocalObservation {
714 fn create(root: u64, kind: &'static str) -> Self {
715 static NEXT: AtomicU64 = AtomicU64::new(1);
716 let observation = Self {
717 id: NEXT.fetch_add(1, Ordering::Relaxed),
718 root,
719 kind,
720 };
721 observation.record("create");
722 observation
723 }
724 fn record(&self, event: &'static str) {
725 LOCAL_EVENTS
726 .lock()
727 .unwrap()
728 .push((self.id, self.root, self.kind, event));
729 record_observation(self.root, self.id, self.kind, event);
730 }
731}
732
733#[cfg(test)]
734type ObservationEvent = (u64, u64, u64, &'static str, &'static str);
735#[cfg(test)]
736static ORDERED_EVENTS: std::sync::Mutex<Vec<ObservationEvent>> = std::sync::Mutex::new(Vec::new());
737#[cfg(test)]
738fn record_observation(root: u64, object: u64, kind: &'static str, event: &'static str) {
739 static SEQUENCE: AtomicU64 = AtomicU64::new(1);
740 let sequence = SEQUENCE.fetch_add(1, Ordering::Relaxed);
741 ORDERED_EVENTS
742 .lock()
743 .unwrap()
744 .push((sequence, root, object, kind, event));
745}
746
747#[cfg(test)]
748mod tests;