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,28 @@ 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
+ #[ clap( long) ]
66
+ advanced : bool ,
67
+
68
+ /// Date to start syncing from.
69
+ /// If not specified, start from beginning.
70
+ /// Format: YYYY-MM-DD
71
+ #[ clap( long, value_parser=parse_start_date) ]
72
+ start_date : Option < DateTime < Utc > > ,
73
+
74
+ /// Specify buckets to sync using a comma-separated list.
75
+ /// If not specified, all buckets will be synced.
76
+ #[ clap( long, value_parser=parse_list) ]
77
+ buckets : Option < Vec < String > > ,
78
+
79
+ /// Full path to sync db file
80
+ /// Useful for syncing buckets from a specific db file in the sync directory.
81
+ /// Must be a valid absolute path to a file in the sync directory.
82
+ #[ clap( long) ]
83
+ sync_db : Option < PathBuf > ,
84
+ } ,
64
85
65
86
/// Sync subcommand (basic)
66
87
///
@@ -140,11 +161,27 @@ fn main() -> Result<(), Box<dyn Error>> {
140
161
let client = AwClient :: new ( & opts. host , port, "aw-sync" ) ?;
141
162
142
163
// if opts.command is None, then we're using the default subcommand (Sync)
143
- match opts. command . unwrap_or ( Commands :: Daemon { } ) {
164
+ match opts. command . unwrap_or ( Commands :: Daemon {
165
+ advanced : false ,
166
+ start_date : None ,
167
+ buckets : None ,
168
+ sync_db : None ,
169
+ } ) {
144
170
// Start daemon
145
- Commands :: Daemon { } => {
171
+ Commands :: Daemon {
172
+ advanced,
173
+ start_date,
174
+ buckets,
175
+ sync_db,
176
+ } => {
146
177
info ! ( "Starting daemon..." ) ;
147
- daemon ( & client) ?;
178
+ if advanced {
179
+ info ! ( "Using advanced sync mode" ) ;
180
+ daemon_advanced ( & client, start_date, buckets, sync_db) ?;
181
+ } else {
182
+ info ! ( "Using basic sync mode" ) ;
183
+ daemon ( & client) ?;
184
+ }
148
185
}
149
186
// Perform basic sync
150
187
Commands :: Sync { host } => {
@@ -167,6 +204,7 @@ fn main() -> Result<(), Box<dyn Error>> {
167
204
sync_wrapper:: push ( & client) ?
168
205
}
169
206
// Perform two-way sync
207
+ // Only way to sync non-window buckets
170
208
Commands :: SyncAdvanced {
171
209
start_date,
172
210
buckets,
@@ -247,3 +285,56 @@ fn daemon_sync_cycle(client: &AwClient) -> Result<(), Box<dyn Error>> {
247
285
248
286
Ok ( ( ) )
249
287
}
288
+
289
+ fn daemon_advanced (
290
+ client : & AwClient ,
291
+ start_date : Option < DateTime < Utc > > ,
292
+ buckets : Option < Vec < String > > ,
293
+ sync_db : Option < PathBuf > ,
294
+ ) -> Result < ( ) , Box < dyn Error > > {
295
+ let ( tx, rx) = channel ( ) ;
296
+
297
+ ctrlc:: set_handler ( move || {
298
+ let _ = tx. send ( ( ) ) ;
299
+ } ) ?;
300
+
301
+ let sync_dir = dirs:: get_sync_dir ( ) ?;
302
+ if let Some ( db_path) = & sync_db {
303
+ info ! ( "Using sync db: {}" , & db_path. display( ) ) ;
304
+
305
+ if !db_path. is_absolute ( ) {
306
+ Err ( "Sync db path must be absolute" ) ?
307
+ }
308
+ if !db_path. starts_with ( & sync_dir) {
309
+ Err ( "Sync db path must be in sync directory" ) ?
310
+ }
311
+ }
312
+
313
+ let sync_spec = sync:: SyncSpec {
314
+ path : sync_dir,
315
+ path_db : sync_db,
316
+ buckets,
317
+ start : start_date,
318
+ } ;
319
+
320
+ loop {
321
+ if let Err ( e) = sync:: sync_run ( client, & sync_spec, sync:: SyncMode :: Both ) {
322
+ error ! ( "Error during sync cycle: {}" , e) ;
323
+ return Err ( e) ;
324
+ }
325
+
326
+ info ! ( "Advanced sync pass done, sleeping for 5 minutes" ) ;
327
+
328
+ match rx. recv_timeout ( Duration :: from_secs ( 300 ) ) {
329
+ Ok ( _) | Err ( RecvTimeoutError :: Disconnected ) => {
330
+ info ! ( "Termination signal received, shutting down." ) ;
331
+ break ;
332
+ }
333
+ Err ( RecvTimeoutError :: Timeout ) => {
334
+ // Continue the loop if the timeout occurs
335
+ }
336
+ }
337
+ }
338
+
339
+ Ok ( ( ) )
340
+ }
0 commit comments