2
2
// - [x] Setup local sync bucket
3
3
// - [x] Import local buckets and sync events from aw-server (either through API or through creating a read-only Datastore)
4
4
// - [x] Import buckets and sync events from remotes
5
- // - [ ] Add CLI arguments
5
+ // - [x ] Add CLI arguments
6
6
// - [x] For which local server to use
7
7
// - [x] For which sync dir to use
8
- // - [ ] Date to start syncing from
8
+ // - [x ] Date to start syncing from
9
9
10
10
#[ macro_use]
11
11
extern crate log;
@@ -60,7 +60,29 @@ struct Opts {
60
60
enum Commands {
61
61
/// Daemon subcommand
62
62
/// Starts aw-sync as a daemon, which will sync every 5 minutes.
63
- Daemon { } ,
63
+ Daemon {
64
+ /// Use advanced sync mode
65
+ /// (automatically enabled when any advanced options are provided)
66
+ #[ clap( long) ]
67
+ advanced : bool ,
68
+
69
+ /// Date to start syncing from.
70
+ /// If not specified, start from beginning.
71
+ /// Format: YYYY-MM-DD
72
+ #[ clap( long, value_parser=parse_start_date) ]
73
+ start_date : Option < DateTime < Utc > > ,
74
+
75
+ /// Specify buckets to sync using a comma-separated list.
76
+ /// If not specified, all buckets will be synced.
77
+ #[ clap( long, value_parser=parse_list) ]
78
+ buckets : Option < Vec < String > > ,
79
+
80
+ /// Full path to sync db file
81
+ /// Useful for syncing buckets from a specific db file in the sync directory.
82
+ /// Must be a valid absolute path to a file in the sync directory.
83
+ #[ clap( long) ]
84
+ sync_db : Option < PathBuf > ,
85
+ } ,
64
86
65
87
/// Sync subcommand (basic)
66
88
///
@@ -140,11 +162,30 @@ fn main() -> Result<(), Box<dyn Error>> {
140
162
let client = AwClient :: new ( & opts. host , port, "aw-sync" ) ?;
141
163
142
164
// if opts.command is None, then we're using the default subcommand (Sync)
143
- match opts. command . unwrap_or ( Commands :: Daemon { } ) {
165
+ match opts. command . unwrap_or ( Commands :: Daemon {
166
+ advanced : false ,
167
+ start_date : None ,
168
+ buckets : None ,
169
+ sync_db : None ,
170
+ } ) {
144
171
// Start daemon
145
- Commands :: Daemon { } => {
172
+ Commands :: Daemon {
173
+ advanced,
174
+ start_date,
175
+ buckets,
176
+ sync_db,
177
+ } => {
146
178
info ! ( "Starting daemon..." ) ;
147
- daemon ( & client) ?;
179
+ // Infer advanced mode if any advanced options are provided
180
+ let use_advanced = start_date. is_some ( ) || buckets. is_some ( ) || sync_db. is_some ( ) ;
181
+
182
+ if use_advanced {
183
+ info ! ( "Using advanced sync mode" ) ;
184
+ daemon_advanced ( & client, start_date, buckets, sync_db) ?;
185
+ } else {
186
+ info ! ( "Using basic sync mode" ) ;
187
+ daemon ( & client) ?;
188
+ }
148
189
}
149
190
// Perform basic sync
150
191
Commands :: Sync { host } => {
@@ -167,6 +208,7 @@ fn main() -> Result<(), Box<dyn Error>> {
167
208
sync_wrapper:: push ( & client) ?
168
209
}
169
210
// Perform two-way sync
211
+ // Only way to sync non-window buckets
170
212
Commands :: SyncAdvanced {
171
213
start_date,
172
214
buckets,
@@ -247,3 +289,56 @@ fn daemon_sync_cycle(client: &AwClient) -> Result<(), Box<dyn Error>> {
247
289
248
290
Ok ( ( ) )
249
291
}
292
+
293
+ fn daemon_advanced (
294
+ client : & AwClient ,
295
+ start_date : Option < DateTime < Utc > > ,
296
+ buckets : Option < Vec < String > > ,
297
+ sync_db : Option < PathBuf > ,
298
+ ) -> Result < ( ) , Box < dyn Error > > {
299
+ let ( tx, rx) = channel ( ) ;
300
+
301
+ ctrlc:: set_handler ( move || {
302
+ let _ = tx. send ( ( ) ) ;
303
+ } ) ?;
304
+
305
+ let sync_dir = dirs:: get_sync_dir ( ) ?;
306
+ if let Some ( db_path) = & sync_db {
307
+ info ! ( "Using sync db: {}" , & db_path. display( ) ) ;
308
+
309
+ if !db_path. is_absolute ( ) {
310
+ Err ( "Sync db path must be absolute" ) ?
311
+ }
312
+ if !db_path. starts_with ( & sync_dir) {
313
+ Err ( "Sync db path must be in sync directory" ) ?
314
+ }
315
+ }
316
+
317
+ let sync_spec = sync:: SyncSpec {
318
+ path : sync_dir,
319
+ path_db : sync_db,
320
+ buckets,
321
+ start : start_date,
322
+ } ;
323
+
324
+ loop {
325
+ if let Err ( e) = sync:: sync_run ( client, & sync_spec, sync:: SyncMode :: Both ) {
326
+ error ! ( "Error during sync cycle: {}" , e) ;
327
+ return Err ( e) ;
328
+ }
329
+
330
+ info ! ( "Advanced sync pass done, sleeping for 5 minutes" ) ;
331
+
332
+ match rx. recv_timeout ( Duration :: from_secs ( 300 ) ) {
333
+ Ok ( _) | Err ( RecvTimeoutError :: Disconnected ) => {
334
+ info ! ( "Termination signal received, shutting down." ) ;
335
+ break ;
336
+ }
337
+ Err ( RecvTimeoutError :: Timeout ) => {
338
+ // Continue the loop if the timeout occurs
339
+ }
340
+ }
341
+ }
342
+
343
+ Ok ( ( ) )
344
+ }
0 commit comments