ConditionalOperations

Trait ConditionalOperations 

Source
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§

Source

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,

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 update
  • id - The unique identifier of the resource
  • data - The updated resource data
  • expected_version - The version the client expects (for conflict detection)
  • context - Request context containing tenant information
§Returns
  • Success(VersionedResource) - Update succeeded with new resource and version
  • VersionMismatch(VersionConflict) - Resource was modified by another client
  • NotFound - 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"),
// }
Source

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,

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 delete
  • id - The unique identifier of the resource
  • expected_version - The version the client expects (for conflict detection)
  • context - Request context containing tenant information
§Returns
  • Success(()) - Delete succeeded
  • VersionMismatch(VersionConflict) - Resource was modified by another client
  • NotFound - Resource doesn’t exist
Source

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,

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 patch
  • id - The unique identifier of the resource
  • patch_request - The PATCH operations to apply
  • expected_version - The version the client expects (for conflict detection)
  • context - Request context containing tenant information
§Returns
  • Success(VersionedResource) - PATCH succeeded with updated resource and version
  • VersionMismatch(VersionConflict) - Resource was modified by another client
  • NotFound - Resource doesn’t exist
Source

fn get_versioned_resource( &self, resource_type: &str, id: &str, context: &RequestContext, ) -> impl Future<Output = Result<Option<VersionedResource>, Self::Error>> + Send
where 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 retrieve
  • id - The unique identifier of the resource
  • context - 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
// }
Source

fn create_versioned_resource( &self, resource_type: &str, data: Value, context: &RequestContext, ) -> impl Future<Output = Result<VersionedResource, Self::Error>> + Send
where 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 create
  • data - The resource data as JSON
  • context - 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();
Source

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,

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 check
  • id - The unique identifier of the resource
  • expected_version - The version to compare against
  • context - Request context containing tenant information
§Returns
  • Some(true) - Resource exists and version matches
  • Some(false) - Resource exists but version doesn’t match
  • None - Resource doesn’t exist
Source

fn get_resource_version( &self, resource_type: &str, id: &str, context: &RequestContext, ) -> impl Future<Output = Result<Option<RawVersion>, Self::Error>> + Send
where 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 check
  • id - The unique identifier of the resource
  • context - 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.

Source

fn is_valid_version(&self, version: &RawVersion) -> bool

Validate that a version is in the expected format.

Checks that a version string or RawVersion follows expected patterns, useful for input validation before conditional operations.

§Arguments
  • version - The version to validate
§Returns

true if the version format is acceptable

Source

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 expected
  • current - The actual current version on the server
  • resource_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§

Source§

impl<T: ResourceProvider> ConditionalOperations for T

Default implementation for any ResourceProvider