1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use crate::{ client::ClientData, telemetry, CollectionRequest, Guid, IncomingChangeset, OutgoingChangeset, ServerTimestamp, }; use anyhow::Result; #[derive(Debug, Clone, PartialEq)] pub struct CollSyncIds { pub global: Guid, pub coll: Guid, } /// Defines how a store is associated with Sync. #[derive(Debug, Clone, PartialEq)] pub enum StoreSyncAssociation { /// This store is disconnected (although it may be connected in the future). Disconnected, /// Sync is connected, and has the following sync IDs. Connected(CollSyncIds), } /// Low-level store functionality. Stores that need custom reconciliation logic /// should use this. /// /// Different stores will produce errors of different types. To accommodate /// this, we force them all to return failure::Error. pub trait Store { fn collection_name(&self) -> std::borrow::Cow<'static, str>; /// Prepares the store for syncing. The tabs store currently uses this to /// store the current list of clients, which it uses to look up device names /// and types. /// /// Note that this method is only called by `sync_multiple`, and only if a /// command processor is registered. In particular, `prepare_for_sync` will /// not be called if the store is synced using `sync::synchronize` or /// `sync_multiple::sync_multiple`. It _will_ be called if the store is /// synced via the Sync Manager. /// /// TODO(issue #2590): This is pretty cludgey and will be hard to extend for /// any case other than the tabs case. We should find another way to support /// tabs... fn prepare_for_sync(&self, _get_client_data: &dyn Fn() -> ClientData) -> Result<()> { Ok(()) } /// `inbound` is a vector to support the case where /// `get_collection_requests` returned multiple requests. The changesets are /// in the same order as the requests were -- e.g. if `vec![req_a, req_b]` /// was returned from `get_collection_requests`, `inbound` will have the /// results from `req_a` as its first index, and those from `req_b` as it's /// second. fn apply_incoming( &self, inbound: Vec<IncomingChangeset>, telem: &mut telemetry::Engine, ) -> Result<OutgoingChangeset>; fn sync_finished( &self, new_timestamp: ServerTimestamp, records_synced: Vec<Guid>, ) -> Result<()>; /// The store is responsible for building the collection request. Engines /// typically will store a lastModified timestamp and use that to build a /// request saying "give me full records since that date" - however, other /// engines might do something fancier. This could even later be extended to /// handle "backfills" etc /// /// To support more advanced use cases (e.g. remerge), multiple requests can /// be returned here. The vast majority of engines will just want to return /// zero or one item in their vector (zero is a valid optimization when the /// server timestamp is the same as the engine last saw, one when it is not) /// /// Important: In the case when more than one collection is requested, it's /// assumed the last one is the "canonical" one. (That is, it must be for /// "this" collection, its timestamp is used to represent the sync, etc). fn get_collection_requests( &self, server_timestamp: ServerTimestamp, ) -> Result<Vec<CollectionRequest>>; /// Get persisted sync IDs. If they don't match the global state we'll be /// `reset()` with the new IDs. fn get_sync_assoc(&self) -> Result<StoreSyncAssociation>; /// Reset the store without wiping local data, ready for a "first sync". /// `assoc` defines how this store is to be associated with sync. fn reset(&self, assoc: &StoreSyncAssociation) -> Result<()>; fn wipe(&self) -> Result<()>; }