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 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
// Copyright 2023-2024 Hugo Osvaldo Barrera
//
// SPDX-License-Identifier: EUPL-1.2
//! Types for specifying rules for a synchronisation.
use std::sync::Arc;
use crate::{
base::{Item, Storage},
CollectionId, Href,
};
/// A collection declared either via its `href` or `collection_id`.
#[derive(Debug, Clone)]
pub enum CollectionDescription {
Id { id: CollectionId },
Href { href: Href },
}
impl CollectionDescription {
pub(crate) fn alias(&self) -> String {
match self {
CollectionDescription::Id { id } => id.to_string(),
CollectionDescription::Href { href } => format!("href:{href}"),
}
}
}
/// A mapping between of a pair of collections across storages.
///
/// This is an unresolved mapping which may be lacking information on one side.
#[derive(Debug, Clone)]
pub enum DeclaredMapping {
/// Copy between two collections with the same definition on both sides.
///
/// Usage of [`CollectionDescription::Href`] between different storage implementations is
/// discouraged.
Direct { description: CollectionDescription },
/// Copy between two collections with explicit definitions on both sides.
Mapped {
/// A descriptive name used for logging and display.
alias: String,
a: CollectionDescription,
b: CollectionDescription,
},
}
impl DeclaredMapping {
/// Create a direct mapping.
///
/// This creates the simplest kind of mapping: it maps two collections with the same
/// [`CollectionId`].
#[must_use]
pub fn direct(id: CollectionId) -> Self {
DeclaredMapping::Direct {
description: CollectionDescription::Id { id },
}
}
}
/// A pair of storage that are to be synchronised.
///
/// This type merely wraps around the declaration of what shall be synchronised. It can be
/// constructed offline and is the entry point to create a [`Plan`] and then execute it.
///
/// New pairs can be created via [`StoragePair::new`].
///
/// [`Plan`]: crate::sync::plan::Plan
pub struct StoragePair<I: Item> {
pub(super) storage_a: Arc<dyn Storage<I>>,
pub(super) storage_b: Arc<dyn Storage<I>>,
pub(super) mappings: Vec<DeclaredMapping>,
pub(super) all_from_a: bool,
pub(super) all_from_b: bool,
pub(super) on_empty: OnEmpty,
}
impl<I: Item> StoragePair<I> {
/// Create a new instance.
///
/// By default, no collections are to be synchronised. See other associated functions for
/// details con configuring additional collections.
#[must_use]
pub fn new(storage_a: Arc<dyn Storage<I>>, storage_b: Arc<dyn Storage<I>>) -> StoragePair<I> {
StoragePair {
storage_a,
storage_b,
mappings: Vec::new(),
all_from_a: false,
all_from_b: false,
on_empty: OnEmpty::Skip,
}
}
/// Include the specified mapping when synchronising.
#[must_use]
pub fn with_mapping(mut self, mapping: DeclaredMapping) -> Self {
self.mappings.push(mapping);
self
}
/// Include all collections from storage A when synchronising.
///
/// By default, only explicitly included collections are synchronised.
#[must_use]
pub fn with_all_from_a(mut self) -> Self {
self.all_from_a = true;
self
}
/// Include all collections from storage B when synchronising.
///
/// By default, only explicitly included collections are synchronised.
#[must_use]
pub fn with_all_from_b(mut self) -> Self {
self.all_from_b = true;
self
}
/// Returns a reference to storage a.
#[must_use]
pub fn storage_a(&self) -> &dyn Storage<I> {
self.storage_a.as_ref()
}
/// Returns a reference to storage a.
#[must_use]
pub fn storage_b(&self) -> &dyn Storage<I> {
self.storage_b.as_ref()
}
/// Action to take when a collection is completely emptied.
#[must_use]
pub fn on_empty(mut self, action: OnEmpty) -> Self {
self.on_empty = action;
self
}
}
#[derive(Debug, PartialEq, Default)]
pub enum OnEmpty {
#[default]
Skip,
Sync,
}