diff --git a/src/api/proto.rs b/src/api/proto.rs index 502215edd..b2a0eed94 100644 --- a/src/api/proto.rs +++ b/src/api/proto.rs @@ -118,7 +118,7 @@ pub enum Request { ListTags(ListTagsRequest), #[rpc(tx = oneshot::Sender>)] SetTag(SetTagRequest), - #[rpc(tx = oneshot::Sender>)] + #[rpc(tx = oneshot::Sender>)] DeleteTags(DeleteTagsRequest), #[rpc(tx = oneshot::Sender>)] RenameTag(RenameTagRequest), diff --git a/src/api/tags.rs b/src/api/tags.rs index b235a8c6b..f19177101 100644 --- a/src/api/tags.rs +++ b/src/api/tags.rs @@ -107,21 +107,28 @@ impl Tags { self.list_with_opts(ListOptions::hash_seq()).await } - /// Deletes a tag. - pub async fn delete_with_opts(&self, options: DeleteOptions) -> super::RequestResult<()> { + /// Deletes a tag, with full control over options. All other delete methods + /// wrap this. + /// + /// Returns the number of tags actually removed. Attempting to delete a non-existent tag will *not* fail. + pub async fn delete_with_opts(&self, options: DeleteOptions) -> super::RequestResult { trace!("{:?}", options); - self.client.rpc(options).await??; - Ok(()) + let deleted = self.client.rpc(options).await??; + Ok(deleted) } /// Deletes a tag. - pub async fn delete(&self, name: impl AsRef<[u8]>) -> super::RequestResult<()> { + /// + /// Returns the number of tags actually removed. Attempting to delete a non-existent tag will *not* fail. + pub async fn delete(&self, name: impl AsRef<[u8]>) -> super::RequestResult { self.delete_with_opts(DeleteOptions::single(name.as_ref())) .await } /// Deletes a range of tags. - pub async fn delete_range(&self, range: R) -> super::RequestResult<()> + /// + /// Returns the number of tags actually removed. Attempting to delete a non-existent tag will *not* fail. + pub async fn delete_range(&self, range: R) -> super::RequestResult where R: RangeBounds, E: AsRef<[u8]>, @@ -130,13 +137,17 @@ impl Tags { } /// Delete all tags with the given prefix. - pub async fn delete_prefix(&self, prefix: impl AsRef<[u8]>) -> super::RequestResult<()> { + /// + /// Returns the number of tags actually removed. Attempting to delete a non-existent tag will *not* fail. + pub async fn delete_prefix(&self, prefix: impl AsRef<[u8]>) -> super::RequestResult { self.delete_with_opts(DeleteOptions::prefix(prefix.as_ref())) .await } /// Delete all tags. Use with care. After this, all data will be garbage collected. - pub async fn delete_all(&self) -> super::RequestResult<()> { + /// + /// Returns the number of tags actually removed. Attempting to delete a non-existent tag will *not* fail. + pub async fn delete_all(&self) -> super::RequestResult { self.delete_with_opts(DeleteOptions { from: None, to: None, diff --git a/src/store/fs/meta.rs b/src/store/fs/meta.rs index 5f76b7fff..aac43cb4a 100644 --- a/src/store/fs/meta.rs +++ b/src/store/fs/meta.rs @@ -631,10 +631,12 @@ impl Actor { .extract_from_if((from, to), |_, _| true) .context(StorageSnafu)?; // drain the iterator to actually remove the tags + let mut deleted = 0; for res in removing { res.context(StorageSnafu)?; + deleted += 1; } - tx.send(Ok(())).await.ok(); + tx.send(Ok(deleted)).await.ok(); Ok(()) } diff --git a/src/store/mem.rs b/src/store/mem.rs index e5529e7fa..cc4c3d849 100644 --- a/src/store/mem.rs +++ b/src/store/mem.rs @@ -227,6 +227,7 @@ impl Actor { info!("deleting tags from {:?} to {:?}", from, to); // state.tags.remove(&from.unwrap()); // todo: more efficient impl + let mut deleted = 0; self.state.tags.retain(|tag, _| { if let Some(from) = &from { if tag < from { @@ -239,9 +240,10 @@ impl Actor { } } info!(" removing {:?}", tag); + deleted += 1; false }); - tx.send(Ok(())).await.ok(); + tx.send(Ok(deleted)).await.ok(); } Command::RenameTag(cmd) => { let RenameTagMsg {