pub trait ConditionalOperations: ResourceProvider {
// Provided methods
fn conditional_update_resource(
&self,
resource_type: &str,
id: &str,
data: Value,
expected_version: &RawVersion,
context: &RequestContext,
) -> impl Future<Output = Result<ConditionalResult<VersionedResource>, Self::Error>> + Send
where Self: Sync { ... }
fn conditional_delete_resource(
&self,
resource_type: &str,
id: &str,
expected_version: &RawVersion,
context: &RequestContext,
) -> impl Future<Output = Result<ConditionalResult<()>, Self::Error>> + Send
where Self: Sync { ... }
fn conditional_patch_resource(
&self,
resource_type: &str,
id: &str,
patch_request: &Value,
expected_version: &RawVersion,
context: &RequestContext,
) -> impl Future<Output = Result<ConditionalResult<VersionedResource>, Self::Error>> + Send
where Self: Sync { ... }
fn get_versioned_resource(
&self,
resource_type: &str,
id: &str,
context: &RequestContext,
) -> impl Future<Output = Result<Option<VersionedResource>, Self::Error>> + Send
where Self: Sync { ... }
fn create_versioned_resource(
&self,
resource_type: &str,
data: Value,
context: &RequestContext,
) -> impl Future<Output = Result<VersionedResource, Self::Error>> + Send
where Self: Sync { ... }
fn check_resource_version(
&self,
resource_type: &str,
id: &str,
expected_version: &RawVersion,
context: &RequestContext,
) -> impl Future<Output = Result<Option<bool>, Self::Error>> + Send
where Self: Sync { ... }
fn get_resource_version(
&self,
resource_type: &str,
id: &str,
context: &RequestContext,
) -> impl Future<Output = Result<Option<RawVersion>, Self::Error>> + Send
where Self: Sync { ... }
fn is_valid_version(&self, version: &RawVersion) -> bool { ... }
fn create_version_conflict(
&self,
expected: RawVersion,
current: RawVersion,
resource_info: Option<&str>,
) -> VersionConflict { ... }
}
Expand description
Trait providing version-based conditional operations for SCIM resources.
This trait extends ResourceProvider with optimistic concurrency control capabilities including conditional updates, deletes, and version management. Most implementers can use the default implementations which provide standard conditional operation patterns.
Provided Methods§
Sourcefn conditional_update_resource(
&self,
resource_type: &str,
id: &str,
data: Value,
expected_version: &RawVersion,
context: &RequestContext,
) -> impl Future<Output = Result<ConditionalResult<VersionedResource>, Self::Error>> + Sendwhere
Self: Sync,
fn conditional_update_resource(
&self,
resource_type: &str,
id: &str,
data: Value,
expected_version: &RawVersion,
context: &RequestContext,
) -> impl Future<Output = Result<ConditionalResult<VersionedResource>, Self::Error>> + Sendwhere
Self: Sync,
Perform a conditional update operation.
Updates a resource only if the current version matches the expected version, preventing lost updates in concurrent scenarios. Uses optimistic locking based on resource content versioning.
§Arguments
resource_type
- The type of resource to updateid
- The unique identifier of the resourcedata
- The updated resource dataexpected_version
- The version the client expects (for conflict detection)context
- Request context containing tenant information
§Returns
Success(VersionedResource)
- Update succeeded with new resource and versionVersionMismatch(VersionConflict)
- Resource was modified by another clientNotFound
- Resource doesn’t exist
§Example
use scim_server::resource::version::{RawVersion, ConditionalResult};
use serde_json::json;
let expected_version = RawVersion::from_hash("abc123");
let update_data = json!({"userName": "newname", "active": false});
// ConditionalOperations automatically available on ResourceProvider implementations
// match provider.conditional_update_resource("Users", "123", update_data, &expected_version, &context).await? {
// ConditionalResult::Success(versioned) => println!("Update successful"),
// ConditionalResult::VersionMismatch(conflict) => println!("Conflict detected"),
// ConditionalResult::NotFound => println!("Resource not found"),
// }
Sourcefn conditional_delete_resource(
&self,
resource_type: &str,
id: &str,
expected_version: &RawVersion,
context: &RequestContext,
) -> impl Future<Output = Result<ConditionalResult<()>, Self::Error>> + Sendwhere
Self: Sync,
fn conditional_delete_resource(
&self,
resource_type: &str,
id: &str,
expected_version: &RawVersion,
context: &RequestContext,
) -> impl Future<Output = Result<ConditionalResult<()>, Self::Error>> + Sendwhere
Self: Sync,
Perform a conditional delete operation.
Deletes a resource only if the current version matches the expected version, preventing accidental deletion of modified resources.
§Arguments
resource_type
- The type of resource to deleteid
- The unique identifier of the resourceexpected_version
- The version the client expects (for conflict detection)context
- Request context containing tenant information
§Returns
Success(())
- Delete succeededVersionMismatch(VersionConflict)
- Resource was modified by another clientNotFound
- Resource doesn’t exist
Sourcefn conditional_patch_resource(
&self,
resource_type: &str,
id: &str,
patch_request: &Value,
expected_version: &RawVersion,
context: &RequestContext,
) -> impl Future<Output = Result<ConditionalResult<VersionedResource>, Self::Error>> + Sendwhere
Self: Sync,
fn conditional_patch_resource(
&self,
resource_type: &str,
id: &str,
patch_request: &Value,
expected_version: &RawVersion,
context: &RequestContext,
) -> impl Future<Output = Result<ConditionalResult<VersionedResource>, Self::Error>> + Sendwhere
Self: Sync,
Perform a conditional PATCH operation.
Applies PATCH operations to a resource only if the current version matches the expected version, combining version control with incremental updates.
§Arguments
resource_type
- The type of resource to patchid
- The unique identifier of the resourcepatch_request
- The PATCH operations to applyexpected_version
- The version the client expects (for conflict detection)context
- Request context containing tenant information
§Returns
Success(VersionedResource)
- PATCH succeeded with updated resource and versionVersionMismatch(VersionConflict)
- Resource was modified by another clientNotFound
- Resource doesn’t exist
Sourcefn get_versioned_resource(
&self,
resource_type: &str,
id: &str,
context: &RequestContext,
) -> impl Future<Output = Result<Option<VersionedResource>, Self::Error>> + Sendwhere
Self: Sync,
fn get_versioned_resource(
&self,
resource_type: &str,
id: &str,
context: &RequestContext,
) -> impl Future<Output = Result<Option<VersionedResource>, Self::Error>> + Sendwhere
Self: Sync,
Get a resource with its version information.
Retrieves a resource wrapped in a VersionedResource container that includes both the resource data and its computed version for use in conditional operations.
§Arguments
resource_type
- The type of resource to retrieveid
- The unique identifier of the resourcecontext
- Request context containing tenant information
§Returns
The versioned resource if found, None if not found
§Example
// ConditionalOperations provides get_versioned_resource for getting resources with version info
// if let Some(versioned_resource) = provider.get_versioned_resource("Users", "123", &context).await? {
// let current_version = versioned_resource.version().clone();
// // Use current_version for subsequent conditional operations
// }
Sourcefn create_versioned_resource(
&self,
resource_type: &str,
data: Value,
context: &RequestContext,
) -> impl Future<Output = Result<VersionedResource, Self::Error>> + Sendwhere
Self: Sync,
fn create_versioned_resource(
&self,
resource_type: &str,
data: Value,
context: &RequestContext,
) -> impl Future<Output = Result<VersionedResource, Self::Error>> + Sendwhere
Self: Sync,
Create a resource with version information.
Creates a new resource and returns it wrapped in a VersionedResource container with its initial computed version for immediate use in conditional operations.
§Arguments
resource_type
- The type of resource to createdata
- The resource data as JSONcontext
- Request context containing tenant information
§Returns
The newly created versioned resource
§Example
use serde_json::json;
let user_data = json!({"userName": "john.doe", "active": true});
// ConditionalOperations provides create_versioned_resource for creating resources with version info
// let versioned_user = provider.create_versioned_resource("Users", user_data, &context).await?;
// let initial_version = versioned_user.version().clone();
Sourcefn check_resource_version(
&self,
resource_type: &str,
id: &str,
expected_version: &RawVersion,
context: &RequestContext,
) -> impl Future<Output = Result<Option<bool>, Self::Error>> + Sendwhere
Self: Sync,
fn check_resource_version(
&self,
resource_type: &str,
id: &str,
expected_version: &RawVersion,
context: &RequestContext,
) -> impl Future<Output = Result<Option<bool>, Self::Error>> + Sendwhere
Self: Sync,
Check if a resource version matches the expected version.
Utility method for comparing resource versions without performing operations, useful for validation or pre-flight checks.
§Arguments
resource_type
- The type of resource to checkid
- The unique identifier of the resourceexpected_version
- The version to compare againstcontext
- Request context containing tenant information
§Returns
Some(true)
- Resource exists and version matchesSome(false)
- Resource exists but version doesn’t matchNone
- Resource doesn’t exist
Sourcefn get_resource_version(
&self,
resource_type: &str,
id: &str,
context: &RequestContext,
) -> impl Future<Output = Result<Option<RawVersion>, Self::Error>> + Sendwhere
Self: Sync,
fn get_resource_version(
&self,
resource_type: &str,
id: &str,
context: &RequestContext,
) -> impl Future<Output = Result<Option<RawVersion>, Self::Error>> + Sendwhere
Self: Sync,
Get the current version of a resource without retrieving the full resource.
Optimized method for retrieving just the version information, useful for version checks without the overhead of full resource retrieval.
§Arguments
resource_type
- The type of resource to checkid
- The unique identifier of the resourcecontext
- Request context containing tenant information
§Returns
The current version if the resource exists, None if not found
§Default Implementation
The default implementation retrieves the full resource and computes the version. Implementers may override this for more efficient version-only retrieval.
Sourcefn is_valid_version(&self, version: &RawVersion) -> bool
fn is_valid_version(&self, version: &RawVersion) -> bool
Sourcefn create_version_conflict(
&self,
expected: RawVersion,
current: RawVersion,
resource_info: Option<&str>,
) -> VersionConflict
fn create_version_conflict( &self, expected: RawVersion, current: RawVersion, resource_info: Option<&str>, ) -> VersionConflict
Create a version conflict error with standard messaging.
Helper method for creating consistent version conflict errors across conditional operations.
§Arguments
expected
- The version the client expectedcurrent
- The actual current version on the serverresource_info
- Optional additional context about the resource
§Returns
A VersionConflict with appropriate error messaging
Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.
Implementors§
impl<T: ResourceProvider> ConditionalOperations for T
Default implementation for any ResourceProvider