15
15
* limitations under the License.
16
16
*/
17
17
18
- use core:: cell:: RefCell ;
19
- use std:: any:: Any ;
20
18
use std:: collections:: HashMap ;
21
- use std:: fmt ;
22
- use std:: sync :: Arc ;
19
+ use std:: sync :: { Arc , Mutex } ;
20
+ use std:: thread ;
23
21
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 > ;
22
+ use serde_json:: Value ;
23
+ use state:: Container ;
41
24
42
- thread_local ! {
43
- static SERVICE_CONTEXT : RefCell <RpcContext > = RefCell :: new( RpcContext :: default ( ) ) ;
44
- }
25
+ pub static APPLICATION_CONTEXT : Container ! [ Send + Sync ] = <Container ! [ Send + Sync ] >:: new ( ) ;
45
26
46
27
///
47
28
/// All environment information of during the current call will put into the context
@@ -53,37 +34,38 @@ thread_local! {
53
34
/// After B call C,the RpcContext record the information of B call C
54
35
///
55
36
#[ 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
- }
37
+ pub struct RpcContext { }
65
38
66
- pub fn clear ( & mut self ) {
67
- self . attachments . clear ( ) ;
68
- }
39
+ pub trait Context {
40
+ fn get_attachments ( ) -> Option < Arc < Mutex < HashMap < String , Value > > > > ;
69
41
}
70
42
71
- fn get_current < F : FnMut ( & RpcContext ) -> T , T > ( mut f : F ) -> T {
72
- SERVICE_CONTEXT . try_with ( |ctx| f ( & ctx. borrow ( ) ) ) . unwrap ( )
73
- }
43
+ impl Context for RpcContext {
44
+ fn get_attachments ( ) -> Option < Arc < Mutex < HashMap < String , Value > > > > {
45
+ let local = APPLICATION_CONTEXT . try_get_local :: < Arc < Mutex < HashMap < String , Value > > > > ( ) ;
46
+
47
+ tracing:: debug!( "{:?} - {:?}" , thread:: current( ) . id( ) , local) ;
74
48
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 ( )
49
+ match local {
50
+ Some ( attachment) => Some ( attachment. clone ( ) ) ,
51
+ None => {
52
+ let attachment = HashMap :: < String , Value > :: new ( ) ;
53
+ let mutex = Arc :: new ( Mutex :: new ( attachment) ) ;
54
+ let mutex_clone = Arc :: clone ( & mutex) ;
55
+ APPLICATION_CONTEXT . set_local ( move || {
56
+ return Arc :: clone ( & mutex_clone) ;
57
+ } ) ;
58
+ Some ( Arc :: clone ( & mutex) )
59
+ }
60
+ }
80
61
}
81
62
}
82
63
83
64
#[ cfg( test) ]
84
65
mod tests {
66
+ use tokio:: time;
67
+
85
68
use super :: * ;
86
- use std:: thread:: sleep;
87
69
use std:: time:: Duration ;
88
70
89
71
#[ test]
@@ -96,25 +78,26 @@ mod tests {
96
78
97
79
let mut handles = Vec :: with_capacity ( 10 ) ;
98
80
99
- for i in 0 ..10 {
81
+ for i in 0 ..= 10 {
100
82
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
- }
83
+ if let Some ( attachments) = RpcContext :: get_attachments ( ) {
84
+ let mut attachments = attachments. lock ( ) . unwrap ( ) ;
85
+ attachments. insert ( "key1" . into ( ) , Value :: from ( format ! ( "data-{i}" ) ) ) ;
86
+
87
+ assert ! ( attachments. len( ) > 0 ) ;
88
+ } ;
89
+
90
+ time:: sleep ( Duration :: from_millis ( 1000 ) ) . await ;
91
+
92
+ if let Some ( attachments) = RpcContext :: get_attachments ( ) {
93
+ let attachments = attachments. lock ( ) . unwrap ( ) ;
94
+ assert ! ( attachments. len( ) > 0 ) ;
95
+ } ;
110
96
} ) ) ;
111
97
}
112
98
113
- sleep ( Duration :: from_millis ( 500 ) ) ;
114
-
115
99
for handle in handles {
116
100
rt. block_on ( handle) . unwrap ( ) ;
117
101
}
118
- assert_eq ! ( RpcContext :: current( ) . attachments. len( ) , 0 ) ;
119
102
}
120
103
}
0 commit comments