@@ -20,14 +20,14 @@ use chrono::{TimeDelta, Timelike};
20
20
use std:: future:: Future ;
21
21
use std:: panic:: AssertUnwindSafe ;
22
22
use tokio:: sync:: oneshot;
23
+ use tokio:: task:: JoinSet ;
23
24
use tokio:: time:: { interval_at, sleep, Duration , Instant } ;
24
25
use tokio:: { select, task} ;
25
26
use tracing:: { error, info, trace, warn} ;
26
27
27
28
use crate :: alerts:: { alerts_utils, AlertConfig , AlertError } ;
28
29
use crate :: parseable:: PARSEABLE ;
29
- use crate :: storage:: LOCAL_SYNC_INTERVAL ;
30
- use crate :: { STORAGE_CONVERSION_INTERVAL , STORAGE_UPLOAD_INTERVAL } ;
30
+ use crate :: { LOCAL_SYNC_INTERVAL , STORAGE_UPLOAD_INTERVAL } ;
31
31
32
32
// Calculates the instant that is the start of the next minute
33
33
fn next_minute ( ) -> Instant {
63
63
if warned_once {
64
64
warn!(
65
65
"Task '{task_name}' took longer than expected: {:?} (threshold: {threshold:?})" ,
66
- start_time. elapsed( ) - threshold
66
+ start_time. elapsed( )
67
67
) ;
68
68
}
69
69
break res. expect( "Task handle shouldn't error" ) ;
@@ -74,28 +74,22 @@ where
74
74
75
75
/// Flushes arrows onto disk every `LOCAL_SYNC_INTERVAL` seconds, packs arrows into parquet every
76
76
/// `STORAGE_CONVERSION_INTERVAL` secondsand uploads them every `STORAGE_UPLOAD_INTERVAL` seconds.
77
- #[ tokio:: main( flavor = "current_thread" ) ]
77
+ #[ tokio:: main( flavor = "multi_thread" , worker_threads = 2 ) ]
78
78
pub async fn handler ( mut cancel_rx : oneshot:: Receiver < ( ) > ) -> anyhow:: Result < ( ) > {
79
- let ( localsync_handler, mut localsync_outbox, localsync_inbox) = run_local_sync ( ) ;
79
+ let ( localsync_handler, mut localsync_outbox, localsync_inbox) = local_sync ( ) ;
80
80
let ( mut remote_sync_handler, mut remote_sync_outbox, mut remote_sync_inbox) =
81
81
object_store_sync ( ) ;
82
- let ( mut remote_conversion_handler, mut remote_conversion_outbox, mut remote_conversion_inbox) =
83
- arrow_conversion ( ) ;
84
82
loop {
85
83
select ! {
86
84
_ = & mut cancel_rx => {
87
85
// actix server finished .. stop other threads and stop the server
88
86
remote_sync_inbox. send( ( ) ) . unwrap_or( ( ) ) ;
89
87
localsync_inbox. send( ( ) ) . unwrap_or( ( ) ) ;
90
- remote_conversion_inbox. send( ( ) ) . unwrap_or( ( ) ) ;
91
88
if let Err ( e) = localsync_handler. await {
92
- error!( "Error joining remote_sync_handler : {:?}" , e ) ;
89
+ error!( "Error joining localsync_handler : {e :?}" ) ;
93
90
}
94
91
if let Err ( e) = remote_sync_handler. await {
95
- error!( "Error joining remote_sync_handler: {:?}" , e) ;
96
- }
97
- if let Err ( e) = remote_conversion_handler. await {
98
- error!( "Error joining remote_conversion_handler: {:?}" , e) ;
92
+ error!( "Error joining remote_sync_handler: {e:?}" ) ;
99
93
}
100
94
return Ok ( ( ) ) ;
101
95
} ,
@@ -107,17 +101,10 @@ pub async fn handler(mut cancel_rx: oneshot::Receiver<()>) -> anyhow::Result<()>
107
101
_ = & mut remote_sync_outbox => {
108
102
// remote_sync failed, this is recoverable by just starting remote_sync thread again
109
103
if let Err ( e) = remote_sync_handler. await {
110
- error!( "Error joining remote_sync_handler: {:?}" , e ) ;
104
+ error!( "Error joining remote_sync_handler: {e :?}" ) ;
111
105
}
112
106
( remote_sync_handler, remote_sync_outbox, remote_sync_inbox) = object_store_sync( ) ;
113
107
} ,
114
- _ = & mut remote_conversion_outbox => {
115
- // remote_conversion failed, this is recoverable by just starting remote_conversion thread again
116
- if let Err ( e) = remote_conversion_handler. await {
117
- error!( "Error joining remote_conversion_handler: {:?}" , e) ;
118
- }
119
- ( remote_conversion_handler, remote_conversion_outbox, remote_conversion_inbox) = arrow_conversion( ) ;
120
- } ,
121
108
}
122
109
}
123
110
}
@@ -132,8 +119,7 @@ pub fn object_store_sync() -> (
132
119
133
120
let handle = task:: spawn ( async move {
134
121
let result = std:: panic:: catch_unwind ( AssertUnwindSafe ( || async move {
135
- let mut sync_interval =
136
- interval_at ( next_minute ( ) , Duration :: from_secs ( STORAGE_UPLOAD_INTERVAL ) ) ;
122
+ let mut sync_interval = interval_at ( next_minute ( ) , STORAGE_UPLOAD_INTERVAL ) ;
137
123
138
124
let mut inbox_rx = AssertUnwindSafe ( inbox_rx) ;
139
125
@@ -183,64 +169,8 @@ pub fn object_store_sync() -> (
183
169
( handle, outbox_rx, inbox_tx)
184
170
}
185
171
186
- pub fn arrow_conversion ( ) -> (
187
- task:: JoinHandle < ( ) > ,
188
- oneshot:: Receiver < ( ) > ,
189
- oneshot:: Sender < ( ) > ,
190
- ) {
191
- let ( outbox_tx, outbox_rx) = oneshot:: channel :: < ( ) > ( ) ;
192
- let ( inbox_tx, inbox_rx) = oneshot:: channel :: < ( ) > ( ) ;
193
-
194
- let handle = task:: spawn ( async move {
195
- let result = std:: panic:: catch_unwind ( AssertUnwindSafe ( || async move {
196
- let mut sync_interval = interval_at (
197
- next_minute ( ) + Duration :: from_secs ( 5 ) , // 5 second delay
198
- Duration :: from_secs ( STORAGE_CONVERSION_INTERVAL ) ,
199
- ) ;
200
-
201
- let mut inbox_rx = AssertUnwindSafe ( inbox_rx) ;
202
-
203
- loop {
204
- select ! {
205
- _ = sync_interval. tick( ) => {
206
- trace!( "Converting Arrow to Parquet... " ) ;
207
- if let Err ( e) = monitor_task_duration(
208
- "arrow_conversion" ,
209
- Duration :: from_secs( 30 ) ,
210
- || async { PARSEABLE . streams. prepare_parquet( false ) } ,
211
- ) . await
212
- {
213
- warn!( "failed to convert local arrow data to parquet. {e:?}" ) ;
214
- }
215
- } ,
216
- res = & mut inbox_rx => { match res{
217
- Ok ( _) => break ,
218
- Err ( _) => {
219
- warn!( "Inbox channel closed unexpectedly" ) ;
220
- break ;
221
- } }
222
- }
223
- }
224
- }
225
- } ) ) ;
226
-
227
- match result {
228
- Ok ( future) => {
229
- future. await ;
230
- }
231
- Err ( panic_error) => {
232
- error ! ( "Panic in object store sync task: {panic_error:?}" ) ;
233
- let _ = outbox_tx. send ( ( ) ) ;
234
- }
235
- }
236
-
237
- info ! ( "Object store sync task ended" ) ;
238
- } ) ;
239
-
240
- ( handle, outbox_rx, inbox_tx)
241
- }
242
-
243
- pub fn run_local_sync ( ) -> (
172
+ /// Flush arrows onto disk and convert them into parquet files
173
+ pub fn local_sync ( ) -> (
244
174
task:: JoinHandle < ( ) > ,
245
175
oneshot:: Receiver < ( ) > ,
246
176
oneshot:: Sender < ( ) > ,
@@ -253,15 +183,23 @@ pub fn run_local_sync() -> (
253
183
let mut inbox_rx = inbox_rx;
254
184
255
185
let result = std:: panic:: catch_unwind ( AssertUnwindSafe ( || async move {
256
- let mut sync_interval =
257
- interval_at ( next_minute ( ) , Duration :: from_secs ( LOCAL_SYNC_INTERVAL ) ) ;
186
+ let mut sync_interval = interval_at ( next_minute ( ) , LOCAL_SYNC_INTERVAL ) ;
187
+ let mut joinset = JoinSet :: new ( ) ;
258
188
259
189
loop {
260
190
select ! {
191
+ // Spawns a flush+conversion task every `LOCAL_SYNC_INTERVAL` seconds
261
192
_ = sync_interval. tick( ) => {
262
- trace!( "Flushing Arrows to disk..." ) ;
263
- PARSEABLE . flush_all_streams( ) ;
193
+ PARSEABLE . streams. flush_and_convert( & mut joinset, false )
264
194
} ,
195
+ // Joins and logs errors in spawned tasks
196
+ Some ( res) = joinset. join_next( ) , if !joinset. is_empty( ) => {
197
+ match res {
198
+ Ok ( Ok ( _) ) => info!( "Successfully converted arrow files to parquet." ) ,
199
+ Ok ( Err ( err) ) => warn!( "Failed to convert arrow files to parquet. {err:?}" ) ,
200
+ Err ( err) => error!( "Issue joining flush+conversion task: {err}" ) ,
201
+ }
202
+ }
265
203
res = & mut inbox_rx => { match res{
266
204
Ok ( _) => break ,
267
205
Err ( _) => {
@@ -278,7 +216,7 @@ pub fn run_local_sync() -> (
278
216
future. await ;
279
217
}
280
218
Err ( panic_error) => {
281
- error ! ( "Panic in local sync task: {:?}" , panic_error ) ;
219
+ error ! ( "Panic in local sync task: {panic_error :?}" ) ;
282
220
}
283
221
}
284
222
0 commit comments