pdk_classy/extract/
context.rs1use std::any::TypeId;
8use std::collections::HashSet;
9use std::{cell::RefCell, convert::Infallible, rc::Rc};
10
11use crate::host::clock::Clock;
12use crate::host::grpc::GrpcHost;
13use crate::host::shared_data::SharedData;
14use crate::{
15 context,
16 event::{After, Exchange, Start},
17 host::Host,
18 reactor::{http::HttpReactor, root::RootReactor},
19 types::{HttpCid, RootCid},
20 BoxFuture,
21};
22
23use super::{extractability, AlreadyExtracted, Exclusive, FromContext, FromContextOnce};
24
25pub struct ConfigureContext {
28 pub(crate) host: Rc<dyn Host>,
29 pub(crate) clock: Rc<dyn Clock>,
30 pub(crate) grpc_host: Rc<dyn GrpcHost>,
31 pub(crate) shared_data: Rc<dyn SharedData>,
32 #[cfg(feature = "experimental_metrics")]
33 pub(crate) metrics: Rc<dyn crate::host::metrics::MetricsHost>,
34 pub(crate) root_reactor: Rc<RootReactor>,
35 pub(crate) unique_extractions: RefCell<HashSet<TypeId>>,
36}
37
38context!(ConfigureContext);
39
40impl ConfigureContext {
41 pub(crate) fn extract_unique<T: 'static>(
42 &self,
43 op: impl FnOnce() -> T,
44 ) -> Result<T, AlreadyExtracted<T>> {
45 self.unique_extractions
46 .borrow_mut()
47 .insert(TypeId::of::<T>())
48 .then(op)
49 .ok_or_else(AlreadyExtracted::default)
50 }
51}
52
53impl FromContext<ConfigureContext, extractability::Transitive> for Rc<dyn Host> {
54 type Error = Infallible;
55
56 fn from_context(context: &ConfigureContext) -> Result<Self, Self::Error> {
57 Ok(context.host.clone())
58 }
59}
60
61impl FromContext<ConfigureContext, extractability::Transitive> for Rc<dyn Clock> {
62 type Error = Infallible;
63
64 fn from_context(context: &ConfigureContext) -> Result<Self, Self::Error> {
65 Ok(context.clock.clone())
66 }
67}
68
69impl FromContext<ConfigureContext, extractability::Transitive> for Rc<dyn SharedData> {
70 type Error = Infallible;
71
72 fn from_context(context: &ConfigureContext) -> Result<Self, Self::Error> {
73 Ok(context.shared_data.clone())
74 }
75}
76
77#[cfg(feature = "experimental_metrics")]
78impl FromContext<ConfigureContext, extractability::Transitive>
79 for Rc<dyn crate::host::metrics::MetricsHost>
80{
81 type Error = Infallible;
82
83 fn from_context(context: &ConfigureContext) -> Result<Self, Self::Error> {
84 Ok(context.metrics.clone())
85 }
86}
87
88impl FromContext<ConfigureContext, extractability::Transitive> for Rc<RootReactor> {
89 type Error = Infallible;
90
91 fn from_context(context: &ConfigureContext) -> Result<Self, Self::Error> {
92 Ok(context.root_reactor.clone())
93 }
94}
95
96impl FromContext<ConfigureContext, extractability::Transitive> for RootCid {
97 type Error = Infallible;
98
99 fn from_context(context: &ConfigureContext) -> Result<Self, Self::Error> {
100 Ok(context.root_reactor.context_id())
101 }
102}
103
104pub struct FilterContext {
107 parent: Rc<ConfigureContext>,
108 http_reactor: Rc<HttpReactor>,
109}
110
111impl FilterContext {
112 pub(crate) fn new(parent: Rc<ConfigureContext>, http_reactor: Rc<HttpReactor>) -> Self {
113 Self {
114 parent,
115 http_reactor,
116 }
117 }
118
119 fn parent(&self) -> &ConfigureContext {
120 &self.parent
121 }
122}
123
124context!(FilterContext => ConfigureContext {FilterContext::parent});
125
126impl<E> FromContextOnce<FilterContext> for Exchange<E>
127where
128 E: After<Start> + 'static,
129{
130 type Error = AlreadyExtracted<Exchange<E>>;
131
132 type Future<'c> = BoxFuture<'c, Result<Self, Self::Error>>;
133
134 fn from_context_once(context: Exclusive<FilterContext>) -> Self::Future<'_> {
135 Box::pin(async move {
136 let exchange = Exchange::new(
137 context.http_reactor.clone(),
138 context.parent.host.clone(),
139 Some(Start {
140 _context_id: context.http_reactor.context_id(),
141 }),
142 );
143 Ok(exchange.wait_for_event::<E>().await)
144 })
145 }
146}
147
148impl FromContext<FilterContext> for Rc<HttpReactor> {
149 type Error = Infallible;
150
151 fn from_context(context: &FilterContext) -> Result<Self, Self::Error> {
152 Ok(context.http_reactor.clone())
153 }
154}
155
156impl FromContext<FilterContext> for HttpCid {
157 type Error = Infallible;
158
159 fn from_context(context: &FilterContext) -> Result<Self, Self::Error> {
160 Ok(context.http_reactor.context_id())
161 }
162}