Skip to content

Commit f14bf36

Browse files
authored
Ftr: add rpc-context (apache#58) (apache#64)
* Ftr: add rpc-context * fix: format * doc: add SafetyValue unittest
1 parent 5ea6df5 commit f14bf36

File tree

2 files changed

+121
-0
lines changed

2 files changed

+121
-0
lines changed

dubbo/src/context.rs

+120
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
use core::cell::RefCell;
19+
use std::any::Any;
20+
use std::collections::HashMap;
21+
use std::fmt;
22+
use std::sync::Arc;
23+
24+
///
25+
/// ```rust
26+
/// use std::collections::HashMap;
27+
/// use std::sync::Arc;
28+
///
29+
/// let mut map = HashMap::<String, SafetyValue>::new();
30+
/// map.insert("key1".into(), Arc::new("data-1"));
31+
///
32+
/// // get a typed value from SafetyValue
33+
/// let value = map
34+
/// .get("key1")
35+
/// .and_then(|f| f.downcast_ref::<String>())
36+
/// .unwrap();
37+
///
38+
/// assert_eq!(value, "data-1");
39+
/// ```
40+
type SafetyValue = Arc<dyn Any + Sync + Send>;
41+
42+
thread_local! {
43+
static SERVICE_CONTEXT: RefCell<RpcContext> = RefCell::new(RpcContext::default());
44+
}
45+
46+
///
47+
/// All environment information of during the current call will put into the context
48+
/// on the filter composing process,and all configuration information will convert the parameters of URL instance.
49+
///
50+
/// RpcContext is a temporary status recorder of [thread_local],when accept RPC request or send RPC request,
51+
/// The RpcContext will be changed.Such as: A call B and B call C.
52+
/// On B machine,before B call C,the RpcContext will record the information of A call B.
53+
/// After B call C,the RpcContext record the information of B call C
54+
///
55+
#[derive(Clone, Default)]
56+
pub struct RpcContext {
57+
pub attachments: HashMap<String, SafetyValue>,
58+
// TODO
59+
}
60+
61+
impl RpcContext {
62+
pub fn current() -> Self {
63+
get_current(|ctx| ctx.clone())
64+
}
65+
66+
pub fn clear(&mut self) {
67+
self.attachments.clear();
68+
}
69+
}
70+
71+
fn get_current<F: FnMut(&RpcContext) -> T, T>(mut f: F) -> T {
72+
SERVICE_CONTEXT.try_with(|ctx| f(&ctx.borrow())).unwrap()
73+
}
74+
75+
impl fmt::Debug for RpcContext {
76+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
77+
f.debug_struct("Context")
78+
.field("attachments", &self.attachments)
79+
.finish()
80+
}
81+
}
82+
83+
#[cfg(test)]
84+
mod tests {
85+
use super::*;
86+
use std::thread::sleep;
87+
use std::time::Duration;
88+
89+
#[test]
90+
fn context_with_thread_local() {
91+
let rt = tokio::runtime::Builder::new_multi_thread()
92+
.max_blocking_threads(2)
93+
.enable_all()
94+
.build()
95+
.unwrap();
96+
97+
let mut handles = Vec::with_capacity(10);
98+
99+
for i in 0..10 {
100+
handles.push(rt.spawn(async move {
101+
let mut attachments = RpcContext::current().attachments;
102+
attachments.insert("key1".into(), Arc::new(format!("data-{i}")));
103+
104+
if i == 10 {
105+
attachments.insert("key2".into(), Arc::new(2));
106+
assert_eq!(attachments.len(), 2);
107+
} else {
108+
assert_eq!(attachments.len(), 1);
109+
}
110+
}));
111+
}
112+
113+
sleep(Duration::from_millis(500));
114+
115+
for handle in handles {
116+
rt.block_on(handle).unwrap();
117+
}
118+
assert_eq!(RpcContext::current().attachments.len(), 0);
119+
}
120+
}

dubbo/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
pub mod codegen;
1919
pub mod common;
20+
pub mod context;
2021
pub mod filter;
2122
mod framework;
2223
pub mod invocation;

0 commit comments

Comments
 (0)