@@ -34,7 +34,7 @@ pub trait AccessMethod: std::fmt::Debug {
3434 ) -> Result < Vec < Event > , String > ;
3535 fn insert_events ( & self , bucket_id : & str , events : Vec < Event > ) -> Result < Vec < Event > , String > ;
3636 fn get_event_count ( & self , bucket_id : & str ) -> Result < i64 , String > ;
37- fn heartbeat ( & self , bucket_id : & str , event : Event , duration : f64 ) -> Result < Event , String > ;
37+ fn heartbeat ( & self , bucket_id : & str , event : Event , duration : f64 ) -> Result < ( ) , String > ;
3838}
3939
4040impl AccessMethod for Datastore {
@@ -58,10 +58,10 @@ impl AccessMethod for Datastore {
5858 ) -> Result < Vec < Event > , String > {
5959 Ok ( self . get_events ( bucket_id, start, end, limit) . unwrap ( ) )
6060 }
61- fn heartbeat ( & self , bucket_id : & str , event : Event , duration : f64 ) -> Result < Event , String > {
62- let res = self . heartbeat ( bucket_id, event, duration) . unwrap ( ) ;
61+ fn heartbeat ( & self , bucket_id : & str , event : Event , duration : f64 ) -> Result < ( ) , String > {
62+ self . heartbeat ( bucket_id, event, duration) . unwrap ( ) ;
6363 self . force_commit ( ) . unwrap ( ) ;
64- Ok ( res )
64+ Ok ( ( ) )
6565 }
6666 fn insert_events ( & self , bucket_id : & str , events : Vec < Event > ) -> Result < Vec < Event > , String > {
6767 let res = self . insert_events ( bucket_id, & events[ ..] ) . unwrap ( ) ;
@@ -114,39 +114,44 @@ impl AccessMethod for AwClient {
114114 Ok ( ( ) )
115115 //Err(DatastoreError::InternalError("Not implemented".to_string()))
116116 }
117- fn heartbeat ( & self , _bucket_id : & str , _event : Event , _duration : f64 ) -> Result < Event , String > {
118- Err ( "Not implemented" . to_string ( ) )
117+ fn heartbeat ( & self , bucket_id : & str , event : Event , duration : f64 ) -> Result < ( ) , String > {
118+ self . heartbeat ( bucket_id, & event, duration)
119+ . map_err ( |e| format ! ( "{:?}" , e) )
119120 }
120121}
121122
122123/// Performs a single sync pass
123- pub fn sync_run ( ) {
124- // TODO: Get path using dirs module
125- let sync_directory = Path :: new ( "/tmp/aw-sync-rust/testing" ) ;
124+ pub fn sync_run ( sync_directory : & Path , client : AwClient ) {
126125 fs:: create_dir_all ( sync_directory) . unwrap ( ) ;
127126
128- // TODO: Use the local datastore here, preferably passed from main
129- let ds_local = AwClient :: new ( "127.0.0.1" , "5666" , "aw-sync-rust" ) ;
130- // let ds_local = Datastore::new(
131- // sync_directory
132- // .join("test-local.db")
133- // .into_os_string( )
134- // .into_string ()
135- // .unwrap(),
136- // false ,
137- //);
138- info ! ( "Set up local datastore" ) ;
139- //log_buckets(&ds_local)? ;
127+ // TODO: Get device id and use to name db file
128+
129+ let info = client . get_info ( ) . unwrap ( ) ;
130+ let ds_localremote = Datastore :: new (
131+ sync_directory
132+ . join ( format ! ( "test-{}.db" , info . device_id ) )
133+ . into_os_string ( )
134+ . into_string ( )
135+ . unwrap ( ) ,
136+ false ,
137+ ) ;
138+ info ! ( "Set up remote for local device" ) ;
140139
141140 let ds_remotes = setup_test ( sync_directory) . unwrap ( ) ;
142- info ! ( "Set up remote datastores " ) ;
141+ info ! ( "Set up remotes for testing " ) ;
143142
144- // FIXME: These are not the datastores that should actually be synced, I'm just testing
143+ // Pull
144+ info ! ( "Pulling..." ) ;
145145 for ds_from in & ds_remotes {
146- sync_datastores ( ds_from, & ds_local ) ;
146+ sync_datastores ( ds_from, & client , false ) ;
147147 }
148148
149- log_buckets ( & ds_local) ;
149+ // Push local server buckets to sync folder
150+ info ! ( "Pushing..." ) ;
151+ sync_datastores ( & client, & ds_localremote, true ) ;
152+
153+ log_buckets ( & client) ;
154+ log_buckets ( & ds_localremote) ;
150155 for ds_from in & ds_remotes {
151156 log_buckets ( ds_from) ;
152157 }
@@ -166,14 +171,15 @@ fn setup_test(sync_directory: &Path) -> std::io::Result<Vec<Datastore>> {
166171 let ds = & ds_ as & dyn AccessMethod ;
167172
168173 // Create a bucket
174+ // NOTE: Created with duplicate name to make sure it still works under such conditions
169175 let bucket_jsonstr = format ! (
170176 r#"{{
171- "id": "bucket-{} ",
172- "type": "test",
173- "hostname": "device-{}",
174- "client": "test"
175- }}"# ,
176- n, n
177+ "id": "bucket",
178+ "type": "test",
179+ "hostname": "device-{}",
180+ "client": "test"
181+ }}"# ,
182+ n
177183 ) ;
178184 let bucket: Bucket = serde_json:: from_str ( & bucket_jsonstr) ?;
179185 match ds. create_bucket ( & bucket) {
@@ -212,9 +218,18 @@ fn setup_test(sync_directory: &Path) -> std::io::Result<Vec<Datastore>> {
212218}
213219
214220/// Returns the sync-destination bucket for a given bucket, creates it if it doesn't exist.
215- fn get_or_create_sync_bucket ( bucket_from : & Bucket , ds_to : & dyn AccessMethod ) -> Bucket {
216- // Ensure the bucket ID ends in "-synced"
217- let new_id = format ! ( "{}-synced" , bucket_from. id. replace( "-synced" , "" ) ) ;
221+ fn get_or_create_sync_bucket (
222+ bucket_from : & Bucket ,
223+ ds_to : & dyn AccessMethod ,
224+ is_push : bool ,
225+ ) -> Bucket {
226+ let new_id = if is_push {
227+ bucket_from. id . clone ( )
228+ } else {
229+ // Ensure the bucket ID ends in "-synced"
230+ let orig_bucketid = bucket_from. id . split ( "-synced-from-" ) . next ( ) . unwrap ( ) ;
231+ format ! ( "{}-synced-from-{}" , orig_bucketid, bucket_from. hostname)
232+ } ;
218233
219234 match ds_to. get_bucket ( new_id. as_str ( ) ) {
220235 Ok ( bucket) => bucket,
@@ -223,9 +238,10 @@ fn get_or_create_sync_bucket(bucket_from: &Bucket, ds_to: &dyn AccessMethod) ->
223238 bucket_new. id = new_id. clone ( ) ;
224239 // TODO: Replace sync origin with hostname/GUID and discuss how we will treat the data
225240 // attributes for internal use.
226- bucket_new
227- . data
228- . insert ( "$aw.sync.origin" . to_string ( ) , serde_json:: json!( "test" ) ) ;
241+ bucket_new. data . insert (
242+ "$aw.sync.origin" . to_string ( ) ,
243+ serde_json:: json!( bucket_from. hostname) ,
244+ ) ;
229245 ds_to. create_bucket ( & bucket_new) . unwrap ( ) ;
230246 ds_to. get_bucket ( new_id. as_str ( ) ) . unwrap ( )
231247 }
@@ -234,16 +250,21 @@ fn get_or_create_sync_bucket(bucket_from: &Bucket, ds_to: &dyn AccessMethod) ->
234250}
235251
236252/// Syncs all buckets from `ds_from` to `ds_to` with `-synced` appended to the ID of the destination bucket.
237- pub fn sync_datastores ( ds_from : & dyn AccessMethod , ds_to : & dyn AccessMethod ) {
253+ fn sync_datastores ( ds_from : & dyn AccessMethod , ds_to : & dyn AccessMethod , is_push : bool ) {
238254 // FIXME: "-synced" should only be appended when synced to the local database, not to the
239255 // staging area for local buckets.
240256 info ! ( "Syncing {:?} to {:?}" , ds_from, ds_to) ;
241257
242258 let buckets_from = ds_from. get_buckets ( ) . unwrap ( ) ;
243259 for bucket_from in buckets_from. values ( ) {
244- let bucket_to = get_or_create_sync_bucket ( bucket_from, ds_to) ;
260+ // TODO: Refuse to sync buckets without hostname/device ID set, or if set to 'unknown'
261+ if bucket_from. hostname == "unknown" {
262+ warn ! ( "Bucket hostname/device ID was invalid, skipping" ) ;
263+ continue ;
264+ }
265+ let bucket_to = get_or_create_sync_bucket ( bucket_from, ds_to, is_push) ;
245266 let eventcount_to_old = ds_to. get_event_count ( bucket_to. id . as_str ( ) ) . unwrap ( ) ;
246- // info!("{:?}", bucket_to);
267+ info ! ( "Bucket: {:?}" , bucket_to. id ) ;
247268
248269 // Sync events
249270 // FIXME: This should use bucket_to.metadata.end, but it doesn't because it doesn't work
0 commit comments