12
12
// See the License for the specific language governing permissions and
13
13
// limitations under the License.
14
14
15
- use std:: sync:: { Arc , Mutex } ;
15
+ use std:: sync:: { Arc , Condvar , Mutex } ;
16
16
17
17
use super :: current_mode:: CurrentModeOfflineReason ;
18
18
use super :: update_thread_worker:: UpdateThreadWorker ;
19
19
use super :: { CurrentMode , Error , OfflineMode , Result } ;
20
20
use crate :: models:: Configuration ;
21
21
use crate :: network:: http_client:: ServerClient ;
22
+ use crate :: network:: live_configuration:: current_mode;
22
23
use crate :: utils:: { ThreadHandle , ThreadStatus } ;
23
24
use crate :: { ConfigurationId , ConfigurationProvider } ;
24
25
@@ -37,10 +38,10 @@ pub trait LiveConfiguration: ConfigurationProvider {
37
38
pub ( crate ) struct LiveConfigurationImpl {
38
39
/// Configuration object that will be returned to consumers. This is also the object
39
40
/// that the thread in the backend will be updating.
40
- configuration : Arc < Mutex < Option < Configuration > > > ,
41
+ configuration : Arc < ( Mutex < Option < Configuration > > , Condvar ) > ,
41
42
42
43
/// Current operation mode.
43
- current_mode : Arc < Mutex < CurrentMode > > ,
44
+ current_mode : Arc < ( Mutex < CurrentMode > , Condvar ) > ,
44
45
45
46
/// Handler to the internal thread that takes care of updating the [`LiveConfigurationImpl::configuration`].
46
47
update_thread : ThreadHandle < Result < ( ) > > ,
@@ -57,10 +58,11 @@ impl LiveConfigurationImpl {
57
58
server_client : T ,
58
59
configuration_id : ConfigurationId ,
59
60
) -> Self {
60
- let configuration = Arc :: new ( Mutex :: new ( None ) ) ;
61
- let current_mode = Arc :: new ( Mutex :: new ( CurrentMode :: Offline (
62
- CurrentModeOfflineReason :: Initializing ,
63
- ) ) ) ;
61
+ let configuration = Arc :: new ( ( Mutex :: new ( None ) , Condvar :: new ( ) ) ) ;
62
+ let current_mode = Arc :: new ( (
63
+ Mutex :: new ( CurrentMode :: Offline ( CurrentModeOfflineReason :: Initializing ) ) ,
64
+ Condvar :: new ( ) ,
65
+ ) ) ;
64
66
65
67
let worker = UpdateThreadWorker :: new (
66
68
server_client,
@@ -84,20 +86,25 @@ impl LiveConfigurationImpl {
84
86
/// configured for this object.
85
87
fn get_configuration ( & self ) -> Result < Configuration > {
86
88
// TODO: Can we return a reference instead?
87
- match & * self . current_mode . lock ( ) ? {
89
+ let ( current_mode_mutex, _) = & * self . current_mode ;
90
+ match & * current_mode_mutex. lock ( ) ? {
88
91
CurrentMode :: Online => {
89
- match & * self . configuration . lock ( ) ? {
92
+ let ( configuration_mutex, _) = & * self . configuration ;
93
+ match & * configuration_mutex. lock ( ) ? {
90
94
// We store the configuration retrieved from the server into the Arc<Mutex> before switching the flag to Online
91
95
None => unreachable ! ( ) ,
92
96
Some ( configuration) => Ok ( configuration. clone ( ) ) ,
93
97
}
94
98
}
95
99
CurrentMode :: Offline ( current_mode_offline_reason) => match & self . offline_mode {
96
100
OfflineMode :: Fail => Err ( Error :: Offline ( current_mode_offline_reason. clone ( ) ) ) ,
97
- OfflineMode :: Cache => match & * self . configuration . lock ( ) ? {
98
- None => Err ( Error :: ConfigurationNotYetAvailable ) ,
99
- Some ( configuration) => Ok ( configuration. clone ( ) ) ,
100
- } ,
101
+ OfflineMode :: Cache => {
102
+ let ( configuration_mutex, _) = & * self . configuration ;
103
+ match & * configuration_mutex. lock ( ) ? {
104
+ None => Err ( Error :: ConfigurationNotYetAvailable ) ,
105
+ Some ( configuration) => Ok ( configuration. clone ( ) ) ,
106
+ }
107
+ }
101
108
OfflineMode :: FallbackData ( app_configuration_offline) => {
102
109
Ok ( app_configuration_offline. config_snapshot . clone ( ) )
103
110
}
@@ -107,13 +114,16 @@ impl LiveConfigurationImpl {
107
114
"Thread finished with status: {:?}" ,
108
115
result
109
116
) ) ) ,
110
- OfflineMode :: Cache => match & * self . configuration . lock ( ) ? {
111
- None => Err ( Error :: UnrecoverableError ( format ! (
112
- "Initial configuration failed to retrieve: {:?}" ,
113
- result
114
- ) ) ) ,
115
- Some ( configuration) => Ok ( configuration. clone ( ) ) ,
116
- } ,
117
+ OfflineMode :: Cache => {
118
+ let ( configuration_mutex, _) = & * self . configuration ;
119
+ match & * configuration_mutex. lock ( ) ? {
120
+ None => Err ( Error :: UnrecoverableError ( format ! (
121
+ "Initial configuration failed to retrieve: {:?}" ,
122
+ result
123
+ ) ) ) ,
124
+ Some ( configuration) => Ok ( configuration. clone ( ) ) ,
125
+ }
126
+ }
117
127
OfflineMode :: FallbackData ( app_configuration_offline) => {
118
128
Ok ( app_configuration_offline. config_snapshot . clone ( ) )
119
129
}
@@ -142,6 +152,24 @@ impl ConfigurationProvider for LiveConfigurationImpl {
142
152
fn is_online ( & self ) -> crate :: Result < bool > {
143
153
Ok ( self . get_current_mode ( ) ? == CurrentMode :: Online )
144
154
}
155
+
156
+ fn wait_until_configuration_is_available ( & self ) {
157
+ let ( configuration_mutex, condition_variable) = & * self . configuration ;
158
+ let configuration_guard = configuration_mutex. lock ( ) . unwrap ( ) ;
159
+ condition_variable
160
+ . wait_while ( configuration_guard, |configuration| configuration. is_none ( ) )
161
+ . unwrap ( ) ;
162
+ }
163
+
164
+ fn wait_until_online ( & self ) {
165
+ let ( current_mode_mutex, condition_variable) = & * self . current_mode ;
166
+ let current_mode_guard = current_mode_mutex. lock ( ) . unwrap ( ) ;
167
+ condition_variable
168
+ . wait_while ( current_mode_guard, |current_mode| {
169
+ * current_mode == CurrentMode :: Online
170
+ } )
171
+ . unwrap ( ) ;
172
+ }
145
173
}
146
174
147
175
impl LiveConfiguration for LiveConfigurationImpl {
@@ -150,7 +178,8 @@ impl LiveConfiguration for LiveConfigurationImpl {
150
178
}
151
179
152
180
fn get_current_mode ( & self ) -> Result < CurrentMode > {
153
- Ok ( self . current_mode . lock ( ) ?. clone ( ) )
181
+ let ( current_mode_mutex, _) = & * self . current_mode ;
182
+ Ok ( current_mode_mutex. lock ( ) ?. clone ( ) )
154
183
}
155
184
}
156
185
0 commit comments