@@ -27,7 +27,7 @@ use crate::{
27
27
cli:: { handle_config_errors, LogFormat , Opts , RootOpts } ,
28
28
config:: { self , Config , ConfigPath } ,
29
29
heartbeat,
30
- signal:: { SignalHandler , SignalPair , SignalRx , SignalTo } ,
30
+ signal:: { ShutdownError , SignalHandler , SignalPair , SignalRx , SignalTo } ,
31
31
topology:: {
32
32
self , ReloadOutcome , RunningTopology , SharedTopologyController , TopologyController ,
33
33
} ,
@@ -49,8 +49,8 @@ use tokio::sync::broadcast::error::RecvError;
49
49
pub struct ApplicationConfig {
50
50
pub config_paths : Vec < config:: ConfigPath > ,
51
51
pub topology : RunningTopology ,
52
- pub graceful_crash_sender : mpsc:: UnboundedSender < ( ) > ,
53
- pub graceful_crash_receiver : mpsc:: UnboundedReceiver < ( ) > ,
52
+ pub graceful_crash_sender : mpsc:: UnboundedSender < ShutdownError > ,
53
+ pub graceful_crash_receiver : mpsc:: UnboundedReceiver < ShutdownError > ,
54
54
#[ cfg( feature = "api" ) ]
55
55
pub api : config:: api:: Options ,
56
56
#[ cfg( feature = "enterprise" ) ]
@@ -139,9 +139,12 @@ impl ApplicationConfig {
139
139
140
140
Some ( api_server)
141
141
}
142
- Err ( e) => {
143
- error ! ( "An error occurred that Vector couldn't handle: {}." , e) ;
144
- _ = self . graceful_crash_sender . send ( ( ) ) ;
142
+ Err ( error) => {
143
+ let error = error. to_string ( ) ;
144
+ error ! ( "An error occurred that Vector couldn't handle: {}." , error) ;
145
+ _ = self
146
+ . graceful_crash_sender
147
+ . send ( ShutdownError :: ApiFailed { error } ) ;
145
148
None
146
149
}
147
150
}
@@ -245,7 +248,7 @@ impl Application {
245
248
246
249
pub struct StartedApplication {
247
250
pub config_paths : Vec < ConfigPath > ,
248
- pub graceful_crash_receiver : mpsc:: UnboundedReceiver < ( ) > ,
251
+ pub graceful_crash_receiver : mpsc:: UnboundedReceiver < ShutdownError > ,
249
252
pub signals : SignalPair ,
250
253
pub topology_controller : SharedTopologyController ,
251
254
}
@@ -270,42 +273,19 @@ impl StartedApplication {
270
273
271
274
let signal = loop {
272
275
tokio:: select! {
273
- signal = signal_rx. recv( ) => {
274
- match signal {
275
- Ok ( SignalTo :: ReloadFromConfigBuilder ( config_builder) ) => {
276
- let mut topology_controller = topology_controller. lock( ) . await ;
277
- let new_config = config_builder. build( ) . map_err( handle_config_errors) . ok( ) ;
278
- if let ReloadOutcome :: FatalError = topology_controller. reload( new_config) . await {
279
- break SignalTo :: Shutdown ;
280
- }
281
- }
282
- Ok ( SignalTo :: ReloadFromDisk ) => {
283
- let mut topology_controller = topology_controller. lock( ) . await ;
284
-
285
- // Reload paths
286
- if let Some ( paths) = config:: process_paths( & config_paths) {
287
- topology_controller. config_paths = paths;
288
- }
289
-
290
- // Reload config
291
- let new_config = config:: load_from_paths_with_provider_and_secrets( & topology_controller. config_paths, & mut signal_handler)
292
- . await
293
- . map_err( handle_config_errors) . ok( ) ;
294
-
295
- if let ReloadOutcome :: FatalError = topology_controller. reload( new_config) . await {
296
- break SignalTo :: Shutdown ;
297
- }
298
- } ,
299
- Err ( RecvError :: Lagged ( amt) ) => warn!( "Overflow, dropped {} signals." , amt) ,
300
- Err ( RecvError :: Closed ) => break SignalTo :: Shutdown ,
301
- Ok ( signal) => break signal,
302
- }
303
- }
276
+ signal = signal_rx. recv( ) => if let Some ( signal) = handle_signal(
277
+ signal,
278
+ & topology_controller,
279
+ & config_paths,
280
+ & mut signal_handler,
281
+ ) . await {
282
+ break signal;
283
+ } ,
304
284
// Trigger graceful shutdown if a component crashed, or all sources have ended.
305
- _ = graceful_crash. next( ) => break SignalTo :: Shutdown ,
285
+ error = graceful_crash. next( ) => break SignalTo :: Shutdown ( error ) ,
306
286
_ = TopologyController :: sources_finished( topology_controller. clone( ) ) => {
307
287
info!( "All sources have finished." ) ;
308
- break SignalTo :: Shutdown
288
+ break SignalTo :: Shutdown ( None )
309
289
} ,
310
290
else => unreachable!( "Signal streams never end" ) ,
311
291
}
@@ -319,6 +299,53 @@ impl StartedApplication {
319
299
}
320
300
}
321
301
302
+ async fn handle_signal (
303
+ signal : Result < SignalTo , RecvError > ,
304
+ topology_controller : & SharedTopologyController ,
305
+ config_paths : & [ ConfigPath ] ,
306
+ signal_handler : & mut SignalHandler ,
307
+ ) -> Option < SignalTo > {
308
+ match signal {
309
+ Ok ( SignalTo :: ReloadFromConfigBuilder ( config_builder) ) => {
310
+ let mut topology_controller = topology_controller. lock ( ) . await ;
311
+ let new_config = config_builder. build ( ) . map_err ( handle_config_errors) . ok ( ) ;
312
+ match topology_controller. reload ( new_config) . await {
313
+ ReloadOutcome :: FatalError ( error) => Some ( SignalTo :: Shutdown ( Some ( error) ) ) ,
314
+ _ => None ,
315
+ }
316
+ }
317
+ Ok ( SignalTo :: ReloadFromDisk ) => {
318
+ let mut topology_controller = topology_controller. lock ( ) . await ;
319
+
320
+ // Reload paths
321
+ if let Some ( paths) = config:: process_paths ( config_paths) {
322
+ topology_controller. config_paths = paths;
323
+ }
324
+
325
+ // Reload config
326
+ let new_config = config:: load_from_paths_with_provider_and_secrets (
327
+ & topology_controller. config_paths ,
328
+ signal_handler,
329
+ )
330
+ . await
331
+ . map_err ( handle_config_errors)
332
+ . ok ( ) ;
333
+
334
+ match topology_controller. reload ( new_config) . await {
335
+ ReloadOutcome :: FatalError ( error) => Some ( SignalTo :: Shutdown ( Some ( error) ) ) ,
336
+ _ => None ,
337
+ }
338
+ }
339
+ Err ( RecvError :: Lagged ( amt) ) => {
340
+ warn ! ( "Overflow, dropped {} signals." , amt) ;
341
+ None
342
+ }
343
+ Err ( RecvError :: Closed ) => Some ( SignalTo :: Shutdown ( None ) ) ,
344
+ Ok ( signal) => Some ( signal) ,
345
+ }
346
+ }
347
+
348
+ #[ derive( Debug ) ]
322
349
pub struct FinishedApplication {
323
350
pub signal : SignalTo ,
324
351
pub signal_rx : SignalRx ,
@@ -329,7 +356,7 @@ impl FinishedApplication {
329
356
pub async fn shutdown ( self ) -> ExitStatus {
330
357
let FinishedApplication {
331
358
signal,
332
- mut signal_rx,
359
+ signal_rx,
333
360
topology_controller,
334
361
} = self ;
335
362
@@ -341,49 +368,39 @@ impl FinishedApplication {
341
368
. into_inner ( ) ;
342
369
343
370
match signal {
344
- SignalTo :: Shutdown => {
345
- emit ! ( VectorStopped ) ;
346
- tokio:: select! {
347
- _ = topology_controller. stop( ) => ExitStatus :: from_raw( {
348
- #[ cfg( windows) ]
349
- {
350
- exitcode:: OK as u32
351
- }
352
- #[ cfg( unix) ]
353
- exitcode:: OK
354
- } ) , // Graceful shutdown finished
355
- _ = signal_rx. recv( ) => {
356
- // It is highly unlikely that this event will exit from topology.
357
- emit!( VectorQuit ) ;
358
- // Dropping the shutdown future will immediately shut the server down
359
- ExitStatus :: from_raw( {
360
- #[ cfg( windows) ]
361
- {
362
- exitcode:: UNAVAILABLE as u32
363
- }
364
- #[ cfg( unix) ]
365
- exitcode:: OK
366
- } )
367
- }
371
+ SignalTo :: Shutdown ( _) => Self :: stop ( topology_controller, signal_rx) . await ,
372
+ SignalTo :: Quit => Self :: quit ( ) ,
373
+ _ => unreachable ! ( ) ,
374
+ }
375
+ }
368
376
377
+ async fn stop ( topology_controller : TopologyController , mut signal_rx : SignalRx ) -> ExitStatus {
378
+ emit ! ( VectorStopped ) ;
379
+ tokio:: select! {
380
+ _ = topology_controller. stop( ) => ExitStatus :: from_raw( {
381
+ #[ cfg( windows) ]
382
+ {
383
+ exitcode:: OK as u32
369
384
}
370
- }
371
- SignalTo :: Quit => {
372
- // It is highly unlikely that this event will exit from topology.
373
- emit ! ( VectorQuit ) ;
374
- drop ( topology_controller) ;
375
- ExitStatus :: from_raw ( {
376
- #[ cfg( windows) ]
377
- {
378
- exitcode:: UNAVAILABLE as u32
379
- }
380
- #[ cfg( unix) ]
381
- exitcode:: OK
382
- } )
383
- }
384
- _ => unreachable ! ( ) ,
385
+ #[ cfg( unix) ]
386
+ exitcode:: OK
387
+ } ) , // Graceful shutdown finished
388
+ _ = signal_rx. recv( ) => Self :: quit( ) ,
385
389
}
386
390
}
391
+
392
+ fn quit ( ) -> ExitStatus {
393
+ // It is highly unlikely that this event will exit from topology.
394
+ emit ! ( VectorQuit ) ;
395
+ ExitStatus :: from_raw ( {
396
+ #[ cfg( windows) ]
397
+ {
398
+ exitcode:: UNAVAILABLE as u32
399
+ }
400
+ #[ cfg( unix) ]
401
+ exitcode:: OK
402
+ } )
403
+ }
387
404
}
388
405
389
406
pub fn init_global ( ) {
0 commit comments