From b8e45d196f5cb9e4f06bf3902799297146498ba6 Mon Sep 17 00:00:00 2001 From: Martin von Zweigbergk Date: Wed, 27 Dec 2023 22:59:02 -0800 Subject: [PATCH] op heads: add a new trait method combining add and remove of op heads Consider how one would implment the current `OpHeadsStore` interface for a cloud-based backend. After `OpHeadsStore::add_op_head()` is called, the set of op heads temporarily contains two heads (typically) until `OpHeadsStore::remove_op_head()` is called. That's not invalid, but it's annoying to have to deal with that state more than necessary. Also, it's unnecessarily inefficient to send the addition and removal of op heads as separate RPCs. This patch therefore adds a `update_op_heads()` method that takes a list of old heads to remove and a single new head to add. Coming patches will start migrating to that method. --- lib/src/op_heads_store.rs | 7 +++++++ lib/src/repo.rs | 2 +- lib/src/simple_op_heads_store.rs | 7 +++++++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/lib/src/op_heads_store.rs b/lib/src/op_heads_store.rs index c309ea123..b478f1f2f 100644 --- a/lib/src/op_heads_store.rs +++ b/lib/src/op_heads_store.rs @@ -43,8 +43,15 @@ pub trait OpHeadsStoreLock<'a> { pub trait OpHeadsStore: Send + Sync + Debug { fn name(&self) -> &str; + /// Remove the old op heads and add the new one. + /// + /// The old op heads must not contain the new one. + fn update_op_heads(&self, old_ids: &[OperationId], new_id: &OperationId); + + // TODO: migrate callers update_op_heads() fn add_op_head(&self, id: &OperationId); + // TODO: migrate callers update_op_heads() fn remove_op_head(&self, id: &OperationId); fn get_op_heads(&self) -> Vec; diff --git a/lib/src/repo.rs b/lib/src/repo.rs index e4bcc5b7c..8d711ed95 100644 --- a/lib/src/repo.rs +++ b/lib/src/repo.rs @@ -186,7 +186,7 @@ impl ReadonlyRepo { let init_operation_id = op_store.write_operation(&init_operation).unwrap(); let init_operation = Operation::new(op_store.clone(), init_operation_id, init_operation); let op_heads_store = op_heads_store_initializer(user_settings, &op_heads_path); - op_heads_store.add_op_head(init_operation.id()); + op_heads_store.update_op_heads(&[], init_operation.id()); let op_heads_type_path = op_heads_path.join("type"); fs::write(&op_heads_type_path, op_heads_store.name()).context(&op_heads_type_path)?; let op_heads_store = Arc::from(op_heads_store); diff --git a/lib/src/simple_op_heads_store.rs b/lib/src/simple_op_heads_store.rs index 3f538694d..24af51025 100644 --- a/lib/src/simple_op_heads_store.rs +++ b/lib/src/simple_op_heads_store.rs @@ -72,6 +72,13 @@ impl OpHeadsStore for SimpleOpHeadsStore { Self::name() } + fn update_op_heads(&self, old_ids: &[OperationId], new_id: &OperationId) { + self.add_op_head(new_id); + for old_id in old_ids { + self.remove_op_head(old_id) + } + } + fn add_op_head(&self, id: &OperationId) { std::fs::write(self.dir.join(id.hex()), "").unwrap(); }