1
1
use serde:: Deserialize ;
2
+ use std:: sync:: Arc ;
3
+ use std:: time:: Duration ;
2
4
use tokio:: fs;
3
5
use tokio:: sync:: RwLock ;
6
+ use tokio:: task:: JoinHandle ;
4
7
use tracing:: { error, info} ;
5
8
6
9
#[ derive( Debug , Deserialize , Clone , PartialEq , Default ) ]
@@ -10,22 +13,29 @@ pub struct RuntimeConfig {
10
13
}
11
14
12
15
pub struct RuntimeConfigManager {
13
- pub config : RwLock < RuntimeConfig > ,
14
- pub path : String ,
16
+ pub config : Arc < RwLock < RuntimeConfig > > ,
17
+ pub handler : JoinHandle < ( ) > ,
15
18
}
16
19
17
20
impl RuntimeConfigManager {
18
21
pub async fn new ( path : String ) -> Self {
19
- let runtime_config = Self :: read_yaml_file ( & path) . await ;
22
+ let runtime_config = Arc :: new ( RwLock :: new ( Default :: default ( ) ) ) ;
23
+ let _ = Self :: reload_config ( & path, & runtime_config) . await ;
20
24
Self {
21
- config : RwLock :: new ( runtime_config) ,
22
- path,
25
+ config : runtime_config. clone ( ) ,
26
+ handler : tokio:: spawn ( async move {
27
+ let mut interval = tokio:: time:: interval ( Duration :: from_secs ( 60 ) ) ;
28
+ loop {
29
+ Self :: reload_config ( & path, & runtime_config) . await ;
30
+ interval. tick ( ) . await ;
31
+ }
32
+ } ) ,
23
33
}
24
34
}
25
35
26
- async fn read_yaml_file ( path : & str ) -> RuntimeConfig {
36
+ pub async fn reload_config ( path : & str , config : & Arc < RwLock < RuntimeConfig > > ) {
27
37
let contents = fs:: read_to_string ( path) . await ;
28
- match contents {
38
+ let new_config : RuntimeConfig = match contents {
29
39
Ok ( contents) => {
30
40
let runtime_config = serde_yaml:: from_str :: < RuntimeConfig > ( & contents) ;
31
41
match runtime_config {
@@ -43,17 +53,10 @@ impl RuntimeConfigManager {
43
53
) ;
44
54
RuntimeConfig :: default ( )
45
55
}
46
- }
47
- }
48
-
49
- pub async fn reload_config ( & self ) -> Result < bool , anyhow:: Error > {
50
- let new_config = Self :: read_yaml_file ( & self . path ) . await ;
51
- if new_config != * self . config . read ( ) . await {
52
- * self . config . write ( ) . await = new_config;
53
- info ! ( "Reloaded new runtime config from {}" , self . path) ;
54
- Ok ( true )
55
- } else {
56
- Ok ( false )
56
+ } ;
57
+ if new_config != * config. read ( ) . await {
58
+ * config. write ( ) . await = new_config;
59
+ info ! ( "Reloaded new runtime config from {}" , path) ;
57
60
}
58
61
}
59
62
@@ -82,21 +85,6 @@ drop_task_killswitch:
82
85
assert_eq ! ( config. drop_task_killswitch. len( ) , 1 ) ;
83
86
assert_eq ! ( config. drop_task_killswitch[ 0 ] , "test:do_nothing" ) ;
84
87
85
- std:: fs:: write (
86
- test_path,
87
- r#"
88
- drop_task_killswitch:
89
- - test:do_nothing
90
- - test:also_do_nothing"# ,
91
- )
92
- . unwrap ( ) ;
93
-
94
- let _ = runtime_config. reload_config ( ) . await ;
95
- let config = runtime_config. read ( ) . await ;
96
- assert_eq ! ( config. drop_task_killswitch. len( ) , 2 ) ;
97
- assert_eq ! ( config. drop_task_killswitch[ 0 ] , "test:do_nothing" ) ;
98
- assert_eq ! ( config. drop_task_killswitch[ 1 ] , "test:also_do_nothing" ) ;
99
-
100
88
fs:: remove_file ( test_path) . await . unwrap ( ) ;
101
89
}
102
90
}
0 commit comments