vector_common/internal_event/
cached_event.rs1use std::{
2 collections::HashMap,
3 hash::Hash,
4 sync::{Arc, RwLock},
5};
6
7use derivative::Derivative;
8
9use super::{InternalEventHandle, RegisterInternalEvent};
10
11#[derive(Derivative)]
21#[derivative(Clone(bound = "T: Clone"))]
22pub struct RegisteredEventCache<T, Event: RegisterTaggedInternalEvent> {
23 fixed_tags: T,
24 cache: Arc<
25 RwLock<
26 HashMap<
27 <Event as RegisterTaggedInternalEvent>::Tags,
28 <Event as RegisterInternalEvent>::Handle,
29 >,
30 >,
31 >,
32}
33
34pub trait RegisterTaggedInternalEvent: RegisterInternalEvent {
37 type Tags;
40
41 type Fixed;
44
45 fn register(fixed: Self::Fixed, tags: Self::Tags) -> <Self as RegisterInternalEvent>::Handle;
46}
47
48impl<Event, EventHandle, Data, Tags, FixedTags> RegisteredEventCache<FixedTags, Event>
49where
50 Data: Sized,
51 EventHandle: InternalEventHandle<Data = Data>,
52 Tags: Clone + Eq + Hash,
53 FixedTags: Clone,
54 Event: RegisterInternalEvent<Handle = EventHandle>
55 + RegisterTaggedInternalEvent<Tags = Tags, Fixed = FixedTags>,
56{
57 pub fn new(fixed_tags: FixedTags) -> Self {
60 Self {
61 fixed_tags,
62 cache: Arc::default(),
63 }
64 }
65
66 pub fn emit(&self, tags: &Tags, value: Data) {
74 let read = self.cache.read().unwrap();
75 if let Some(event) = read.get(tags) {
76 event.emit(value);
77 } else {
78 let event = <Event as RegisterTaggedInternalEvent>::register(
79 self.fixed_tags.clone(),
80 tags.clone(),
81 );
82 event.emit(value);
83
84 drop(read);
86 self.cache.write().unwrap().insert(tags.clone(), event);
87 }
88 }
89}
90
91#[cfg(test)]
92mod tests {
93 #![allow(unreachable_pub)]
94 use metrics::Counter;
95 use strum::IntoEnumIterator;
96
97 use super::*;
98 use crate::internal_event::CounterName;
99
100 #[test]
101 fn test_fixed_tag() {
102 crate::registered_event!(
103 TestEvent {
104 fixed: String,
105 dynamic: String,
106 } => {
107 event: Counter = {
108 crate::counter!(CounterName::iter().next().unwrap(), "fixed" => self.fixed, "dynamic" => self.dynamic)
109 },
110 }
111
112 fn emit(&self, count: u64) {
113 self.event.increment(count);
114 }
115
116 fn register(fixed: String, dynamic: String) {
117 crate::internal_event::register(TestEvent {
118 fixed,
119 dynamic,
120 })
121 }
122 );
123
124 let event: RegisteredEventCache<String, TestEvent> =
125 RegisteredEventCache::new("fixed".to_string());
126
127 for tag in 1..=5 {
128 event.emit(&format!("dynamic{tag}"), tag);
129 }
130 }
131}