Common/Storage/
SetStorageItem.rs

1// File: Common/Source/Storage/SetStorageItem.rs
2// Role: Defines the `SetStorageItem` ActionEffect.
3// Responsibilities:
4//   - Provide a declarative effect for setting or updating a single item in
5//     Memento storage.
6//   - This effect abstracts the "what" (set a storage item) from the "how" (the
7//     StorageProvider implementation).
8//
9// NOTE: This effect is part of a legacy, per-key storage model. The newer,
10
11// high-performance storage model in Cocoon uses a batch-oriented approach
12// (`GetAllStorage`, `SetAllStorage`), making this effect obsolete for that
13// use case. It is kept for potential other uses or until fully deprecated.
14
15//! # SetStorageItem Effect
16//!
17//! Defines the `ActionEffect` for setting or updating an item in Memento-style
18//! storage.
19
20use std::sync::Arc;
21
22use serde_json::Value;
23
24use super::StorageProvider::StorageProvider;
25use crate::{Effect::ActionEffect::ActionEffect, Error::CommonError::CommonError};
26
27/// Creates an effect that, when executed, will set or update an item in either
28/// global or workspace-scoped Memento storage.
29///
30/// It uses the `StorageProvider` capability from the environment to perform the
31/// actual data persistence on the host.
32///
33/// # Parameters
34/// * `TargetObjectValue`: A `serde_json::Value` expected to be an object with
35///   the following fields:
36///     - `Scope` (boolean, optional): `true` for global scope, `false` or
37///       absent for workspace scope.
38///     - `Key` (string, required): The key of the item to set or update.
39/// * `ValueToSet`: The `serde_json::Value` to store. If this value is
40///   `Value::Null`, the effect will delete the item from storage.
41///
42/// # Returns
43/// An `ActionEffect` that resolves to `()` on success.
44pub fn SetStorageItem(
45	TargetObjectValue:Value,
46
47	ValueToSet:Value,
48) -> ActionEffect<Arc<dyn StorageProvider>, CommonError, ()> {
49	ActionEffect::New(Arc::new(move |Provider:Arc<dyn StorageProvider>| {
50		let TargetObjectClone = TargetObjectValue.clone();
51
52		let ValueToSetClone = ValueToSet.clone();
53
54		Box::pin(async move {
55			let IsGlobal = TargetObjectClone.get("Scope").and_then(Value::as_bool).unwrap_or(false);
56
57			let Key = TargetObjectClone
58				.get("Key")
59				.and_then(Value::as_str)
60				.ok_or_else(|| {
61					CommonError::InvalidArgument {
62						ArgumentName:"TargetObject.Key".to_string(),
63
64						Reason:"Expected a 'Key' string field in TargetObject.".to_string(),
65					}
66				})?
67				.to_string();
68
69			// A JSON null from the caller signals deletion to the provider.
70			let ValueToStore = if ValueToSetClone.is_null() { None } else { Some(ValueToSetClone) };
71
72			Provider.UpdateStorageValue(IsGlobal, Key, ValueToStore).await
73		})
74	}))
75}