summaryrefslogtreecommitdiff
path: root/crates/vcs_actions
diff options
context:
space:
mode:
author魏曹先生 <1992414357@qq.com>2025-11-05 16:45:30 +0800
committer魏曹先生 <1992414357@qq.com>2025-11-05 16:46:22 +0800
commit8b3b92b405ebc96416ec300ad3f6260bd8354864 (patch)
treecf7a404b3ae78a8a7675eb2e587a07b383698198 /crates/vcs_actions
parent7627c0e4911cc354e3dd7a3e445ee36252b1e9a6 (diff)
Add sheet restoration and drop functionality
- Add write_and_return macro for common result handling pattern - Extend make_sheet_action to restore sheets with no holder - Implement drop_sheet_action for releasing sheet ownership - Register new drop_sheet_action in client and server registries
Diffstat (limited to 'crates/vcs_actions')
-rw-r--r--crates/vcs_actions/src/actions.rs9
-rw-r--r--crates/vcs_actions/src/actions/sheet_actions.rs156
-rw-r--r--crates/vcs_actions/src/registry/client_registry.rs3
-rw-r--r--crates/vcs_actions/src/registry/server_registry.rs3
4 files changed, 149 insertions, 22 deletions
diff --git a/crates/vcs_actions/src/actions.rs b/crates/vcs_actions/src/actions.rs
index 795d2b0..51186fb 100644
--- a/crates/vcs_actions/src/actions.rs
+++ b/crates/vcs_actions/src/actions.rs
@@ -116,3 +116,12 @@ pub async fn auth_member(
Err(TcpTargetError::NoResult("Auth failed.".to_string()))
}
+
+/// The macro to write and return a result.
+#[macro_export]
+macro_rules! write_and_return {
+ ($instance:expr, $result:expr) => {{
+ $instance.lock().await.write($result).await?;
+ return Ok($result);
+ }};
+}
diff --git a/crates/vcs_actions/src/actions/sheet_actions.rs b/crates/vcs_actions/src/actions/sheet_actions.rs
index b6ea51d..b4e07a7 100644
--- a/crates/vcs_actions/src/actions/sheet_actions.rs
+++ b/crates/vcs_actions/src/actions/sheet_actions.rs
@@ -1,13 +1,19 @@
+use std::io::ErrorKind;
+
use action_system::{action::ActionContext, macros::action_gen};
use serde::{Deserialize, Serialize};
use tcp_connection::error::TcpTargetError;
use vcs_data::data::sheet::SheetName;
-use crate::actions::{auth_member, check_connection_instance, try_get_vault};
+use crate::{
+ actions::{auth_member, check_connection_instance, try_get_local_workspace, try_get_vault},
+ write_and_return,
+};
#[derive(Default, Serialize, Deserialize)]
pub enum MakeSheetActionResult {
Success,
+ SuccessRestore,
// Fail
AuthorizeFailed(String),
@@ -36,31 +42,35 @@ pub async fn make_sheet_action(
let vault = try_get_vault(&ctx)?;
// Check if the sheet already exists
- if vault.sheet(&sheet_name).await.is_ok() {
- instance
- .lock()
- .await
- .write(MakeSheetActionResult::SheetAlreadyExists)
- .await?;
- return Ok(MakeSheetActionResult::SheetAlreadyExists);
+ if let Ok(mut sheet) = vault.sheet(&sheet_name).await {
+ // If the sheet has no holder, assign it to the current member (restore operation)
+ if sheet.holder().is_none() {
+ sheet.set_holder(member_id);
+ match sheet.persist().await {
+ Ok(_) => {
+ write_and_return!(instance, MakeSheetActionResult::SuccessRestore);
+ }
+ Err(e) => {
+ write_and_return!(
+ instance,
+ MakeSheetActionResult::SheetCreationFailed(e.to_string())
+ );
+ }
+ }
+ } else {
+ write_and_return!(instance, MakeSheetActionResult::SheetAlreadyExists);
+ }
} else {
// Create the sheet
match vault.create_sheet(&sheet_name, &member_id).await {
Ok(_) => {
- instance
- .lock()
- .await
- .write(MakeSheetActionResult::Success)
- .await?;
- return Ok(MakeSheetActionResult::Success);
+ write_and_return!(instance, MakeSheetActionResult::Success);
}
Err(e) => {
- instance
- .lock()
- .await
- .write(MakeSheetActionResult::SheetCreationFailed(e.to_string()))
- .await?;
- return Ok(MakeSheetActionResult::SheetCreationFailed(e.to_string()));
+ write_and_return!(
+ instance,
+ MakeSheetActionResult::SheetCreationFailed(e.to_string())
+ );
}
}
}
@@ -77,3 +87,109 @@ pub async fn make_sheet_action(
Err(TcpTargetError::NoResult("No result.".to_string()))
}
+
+#[derive(Default, Serialize, Deserialize)]
+pub enum DropSheetActionResult {
+ Success,
+
+ // Fail
+ SheetInUse,
+ AuthorizeFailed(String),
+ SheetNotExists,
+ SheetDropFailed(String),
+ NoHolder,
+ NotOwner,
+
+ #[default]
+ Unknown,
+}
+
+#[action_gen]
+pub async fn drop_sheet_action(
+ ctx: ActionContext,
+ sheet_name: SheetName,
+) -> Result<DropSheetActionResult, TcpTargetError> {
+ let instance = check_connection_instance(&ctx)?;
+
+ // Auth Member
+ let member_id = match auth_member(&ctx, instance).await {
+ Ok(id) => id,
+ Err(e) => {
+ return Ok(DropSheetActionResult::AuthorizeFailed(e.to_string()));
+ }
+ };
+
+ // Check sheet in use on local
+ if ctx.is_proc_on_local() {
+ let local_workspace = try_get_local_workspace(&ctx)?;
+ if let Some(sheet) = local_workspace.config().lock().await.sheet_in_use() {
+ if sheet == &sheet_name {
+ instance.lock().await.write(false).await?;
+ return Ok(DropSheetActionResult::SheetInUse);
+ }
+ instance.lock().await.write(true).await?;
+ } else {
+ instance.lock().await.write(true).await?;
+ }
+ }
+
+ if ctx.is_proc_on_remote() {
+ // Check if client sheet is in use
+ let sheet_in_use = instance.lock().await.read::<bool>().await?;
+ if !sheet_in_use {
+ return Ok(DropSheetActionResult::SheetInUse);
+ }
+
+ let vault = try_get_vault(&ctx)?;
+
+ // Check if the sheet exists
+ let mut sheet = match vault.sheet(&sheet_name).await {
+ Ok(sheet) => sheet,
+ Err(e) => {
+ if e.kind() == ErrorKind::NotFound {
+ write_and_return!(instance, DropSheetActionResult::SheetNotExists);
+ } else {
+ write_and_return!(
+ instance,
+ DropSheetActionResult::SheetDropFailed(e.to_string())
+ );
+ }
+ }
+ };
+
+ // Get the sheet's holder
+ let Some(holder) = sheet.holder() else {
+ write_and_return!(instance, DropSheetActionResult::NoHolder);
+ };
+
+ // Verify the sheet's holder
+ if holder != &member_id {
+ write_and_return!(instance, DropSheetActionResult::NotOwner);
+ }
+
+ // Drop the sheet
+ sheet.forget_holder();
+ match sheet.persist().await {
+ Ok(_) => {
+ write_and_return!(instance, DropSheetActionResult::Success);
+ }
+ Err(e) => {
+ write_and_return!(
+ instance,
+ DropSheetActionResult::SheetDropFailed(e.to_string())
+ );
+ }
+ }
+ }
+
+ if ctx.is_proc_on_local() {
+ let result = instance
+ .lock()
+ .await
+ .read::<DropSheetActionResult>()
+ .await?;
+ return Ok(result);
+ }
+
+ Err(TcpTargetError::NoResult("No result.".to_string()))
+}
diff --git a/crates/vcs_actions/src/registry/client_registry.rs b/crates/vcs_actions/src/registry/client_registry.rs
index a0b87a6..95c0939 100644
--- a/crates/vcs_actions/src/registry/client_registry.rs
+++ b/crates/vcs_actions/src/registry/client_registry.rs
@@ -13,7 +13,7 @@ use crate::{
local_actions::{
register_set_upstream_vault_action, register_update_to_latest_info_action,
},
- sheet_actions::register_make_sheet_action,
+ sheet_actions::{register_drop_sheet_action, register_make_sheet_action},
},
connection::protocol::RemoteActionInvoke,
};
@@ -27,6 +27,7 @@ fn register_actions(pool: &mut ActionPool) {
// Sheet Actions
register_make_sheet_action(pool);
+ register_drop_sheet_action(pool);
}
pub fn client_action_pool() -> ActionPool {
diff --git a/crates/vcs_actions/src/registry/server_registry.rs b/crates/vcs_actions/src/registry/server_registry.rs
index eade391..b99d697 100644
--- a/crates/vcs_actions/src/registry/server_registry.rs
+++ b/crates/vcs_actions/src/registry/server_registry.rs
@@ -2,7 +2,7 @@ use action_system::action_pool::ActionPool;
use crate::actions::{
local_actions::{register_set_upstream_vault_action, register_update_to_latest_info_action},
- sheet_actions::register_make_sheet_action,
+ sheet_actions::{register_drop_sheet_action, register_make_sheet_action},
};
pub fn server_action_pool() -> ActionPool {
@@ -14,6 +14,7 @@ pub fn server_action_pool() -> ActionPool {
// Sheet Actions
register_make_sheet_action(&mut pool);
+ register_drop_sheet_action(&mut pool);
pool
}