@@ -8,59 +8,83 @@ use open_feature::provider::{FeatureProvider, ProviderMetadata, ResolutionDetail
88use open_feature:: { EvaluationContext , EvaluationError , EvaluationErrorCode , StructValue , Value } ;
99use serde_json:: Value as JsonValue ;
1010use std:: sync:: Arc ;
11+ use tokio:: sync:: Mutex ;
12+ use tracing:: debug;
1113
12- use crate :: resolver:: in_process:: storage:: FlagStore ;
1314use crate :: resolver:: in_process:: storage:: connector:: grpc:: GrpcStreamConnector ;
15+ use crate :: resolver:: in_process:: storage:: { FlagStore , StorageState , StorageStateChange } ;
1416
1517pub struct InProcessResolver {
1618 store : Arc < FlagStore > ,
1719 operator : Operator ,
1820 metadata : ProviderMetadata ,
1921 cache : Option < Arc < CacheService < Value > > > ,
22+ state_receiver : Arc < Mutex < tokio:: sync:: mpsc:: Receiver < StorageStateChange > > > ,
2023}
2124
2225impl InProcessResolver {
2326 pub async fn new ( options : & FlagdOptions ) -> Result < Self > {
24- let store = match & options. socket_path {
27+ let ( store, state_receiver ) = match & options. socket_path {
2528 Some ( _) => Self :: create_unix_socket_store ( options) . await ?,
2629 None => Self :: create_tcp_store ( options) . await ?,
2730 } ;
2831
32+ let cache = options
33+ . cache_settings
34+ . clone ( )
35+ . map ( |settings| Arc :: new ( CacheService :: new ( settings) ) ) ;
36+
2937 Ok ( Self {
3038 store,
3139 operator : Operator :: new ( ) ,
3240 metadata : ProviderMetadata :: new ( "flagd" ) ,
33- cache : options
34- . cache_settings
35- . clone ( )
36- . map ( |settings| Arc :: new ( CacheService :: new ( settings) ) ) ,
41+ cache,
42+ state_receiver : Arc :: new ( Mutex :: new ( state_receiver) ) ,
3743 } )
3844 }
3945
40- async fn create_unix_socket_store ( _options : & FlagdOptions ) -> Result < Arc < FlagStore > > {
41- // let socket_path = options.socket_path.as_ref().unwrap().clone();
42- // let socket_path_for_connector = socket_path.clone();
46+ /// Check for flag updates and clear cache if needed (non-blocking)
47+ async fn check_for_updates ( & self ) {
48+ if self . cache . is_none ( ) {
49+ return ;
50+ }
51+
52+ let mut receiver = self . state_receiver . lock ( ) . await ;
4353
44- // let _channel = Endpoint::try_from("http://[::]:50051")?
45- // .connect_with_connector(service_fn(move |_: Uri| {
46- // let path = socket_path.clone();
47- // async move {
48- // let stream = UnixStream::connect(path).await?;
49- // Ok::<_, std::io::Error>(TokioIo::new(stream))
50- // }
51- // }))
52- // .await?;
54+ // Drain all pending state changes (non-blocking)
55+ let mut should_clear = false ;
56+ while let Ok ( state_change) = receiver. try_recv ( ) {
57+ if state_change. storage_state == StorageState :: Ok {
58+ should_clear = true ;
59+ }
60+ }
5361
54- // let connector =
55- // GrpcStreamConnector::new(socket_path_for_connector, options.selector.clone(), options);
56- // let (store, _state_receiver) = FlagStore::new(Arc::new(connector));
57- // let store = Arc::new(store);
58- // store.init().await?;
59- // Ok(store)
60- todo ! ( "Unix socket store for in-process is not implemented" )
62+ if should_clear {
63+ debug ! ( "Flag store updated, clearing cache" ) ;
64+ if let Some ( cache) = & self . cache {
65+ cache. purge ( ) . await ;
66+ }
67+ }
6168 }
6269
63- async fn create_tcp_store ( options : & FlagdOptions ) -> Result < Arc < FlagStore > > {
70+ async fn create_unix_socket_store (
71+ _options : & FlagdOptions ,
72+ ) -> Result < (
73+ Arc < FlagStore > ,
74+ tokio:: sync:: mpsc:: Receiver < crate :: resolver:: in_process:: storage:: StorageStateChange > ,
75+ ) > {
76+ // Unix socket store for in-process is not implemented
77+ Err ( anyhow:: anyhow!(
78+ "Unix socket store for in-process is not implemented"
79+ ) )
80+ }
81+
82+ async fn create_tcp_store (
83+ options : & FlagdOptions ,
84+ ) -> Result < (
85+ Arc < FlagStore > ,
86+ tokio:: sync:: mpsc:: Receiver < crate :: resolver:: in_process:: storage:: StorageStateChange > ,
87+ ) > {
6488 let target = options
6589 . target_uri
6690 . clone ( )
@@ -73,10 +97,10 @@ impl InProcessResolver {
7397 upstream_config. authority ( ) . to_string ( ) ,
7498 ) ;
7599
76- let ( store, _state_receiver ) = FlagStore :: new ( Arc :: new ( connector) ) ;
100+ let ( store, state_receiver ) = FlagStore :: new ( Arc :: new ( connector) ) ;
77101 let store = Arc :: new ( store) ;
78102 store. init ( ) . await ?;
79- Ok ( store)
103+ Ok ( ( store, state_receiver ) )
80104 }
81105
82106 async fn get_cached_value < T > (
@@ -100,6 +124,9 @@ impl InProcessResolver {
100124 value_converter : impl Fn ( & JsonValue ) -> Option < T > ,
101125 type_name : & str ,
102126 ) -> Result < ResolutionDetails < T > , EvaluationError > {
127+ // Check for flag updates and clear cache if needed
128+ self . check_for_updates ( ) . await ;
129+
103130 // Try cache first
104131 if let Some ( cached_value) = self
105132 . get_cached_value ( flag_key, context, |v| match v {
0 commit comments