scim_server/providers/in_memory.rs
1//! Error types and statistics for in-memory resource provider implementations.
2//!
3//! This module provides error types and statistics structures that are shared
4//! between different in-memory resource provider implementations.
5//!
6//! # Key Types
7//!
8//! - [`InMemoryError`] - Provider-specific error types for in-memory operations
9//! - [`InMemoryStats`] - Resource statistics and performance metrics
10//!
11//! # Usage
12//!
13//! These types are used with `StandardResourceProvider<InMemoryStorage>`:
14//!
15//! ```rust
16//! use scim_server::providers::StandardResourceProvider;
17//! use scim_server::storage::InMemoryStorage;
18//!
19//! let storage = InMemoryStorage::new();
20//! let provider = StandardResourceProvider::new(storage);
21//! ```
22
23use thiserror::Error;
24
25/// Errors that can occur during in-memory provider operations.
26///
27/// This error type is used by in-memory resource providers to represent
28/// various failure conditions during SCIM operations.
29#[derive(Debug, Clone, Error)]
30pub enum InMemoryError {
31 #[error("Resource not found: {resource_type} with id '{id}' in tenant '{tenant_id}'")]
32 ResourceNotFound {
33 /// The type of resource that was not found
34 resource_type: String,
35 /// The ID of the resource that was not found
36 id: String,
37 /// The tenant ID where the resource was not found
38 tenant_id: String,
39 },
40
41 #[error("Duplicate attribute '{attribute}' with value '{value}' for {resource_type} in tenant '{tenant_id}'")]
42 DuplicateAttribute {
43 /// The type of resource with duplicate attribute
44 resource_type: String,
45 /// The name of the duplicate attribute
46 attribute: String,
47 /// The duplicate value
48 value: String,
49 /// The tenant ID where the duplicate was found
50 tenant_id: String,
51 },
52
53 #[error("Invalid resource data: {message}")]
54 InvalidData {
55 /// Description of the invalid data
56 message: String,
57 },
58
59 #[error("Query error: {message}")]
60 QueryError {
61 /// Description of the query error
62 message: String,
63 },
64
65 #[error("Internal error: {message}")]
66 Internal {
67 /// Description of the internal error
68 message: String,
69 },
70
71 #[error("Invalid input: {message}")]
72 InvalidInput {
73 /// Description of what input was invalid
74 message: String,
75 },
76
77 #[error("Resource not found: {resource_type} with id '{id}'")]
78 NotFound {
79 /// The type of resource that was not found
80 resource_type: String,
81 /// The ID of the resource that was not found
82 id: String,
83 },
84
85 #[error("Precondition failed: {message}")]
86 PreconditionFailed {
87 /// Description of the precondition failure
88 message: String,
89 },
90
91 #[error("Duplicate resource: {resource_type} with userName '{username}' already exists in tenant '{tenant_id}'")]
92 DuplicateUserName {
93 /// The resource type that had the duplicate
94 resource_type: String,
95 /// The duplicate userName
96 username: String,
97 /// The tenant where the duplicate was found
98 tenant_id: String,
99 },
100
101 #[error("Patch operation failed: {message}")]
102 PatchOperationFailed {
103 /// Description of why the patch operation failed
104 message: String,
105 },
106
107 #[error("Version conflict: {conflict}")]
108 VersionConflict {
109 /// Details of the version conflict
110 #[from]
111 conflict: crate::resource::version::VersionConflict,
112 },
113}
114
115
116
117/// Statistics about the in-memory provider state.
118///
119/// Provides metrics about resource counts, tenants, and resource types
120/// for monitoring and debugging purposes.
121#[derive(Debug, Clone)]
122pub struct InMemoryStats {
123 /// Number of active tenants in the provider
124 pub tenant_count: usize,
125 /// Total number of resources across all tenants
126 pub total_resources: usize,
127 /// Number of distinct resource types
128 pub resource_type_count: usize,
129 /// List of resource type names
130 pub resource_types: Vec<String>,
131}
132
133impl InMemoryStats {
134 /// Create new empty statistics.
135 pub fn new() -> Self {
136 Self {
137 tenant_count: 0,
138 total_resources: 0,
139 resource_type_count: 0,
140 resource_types: Vec::new(),
141 }
142 }
143
144 /// Check if the provider is empty (no resources).
145 pub fn is_empty(&self) -> bool {
146 self.total_resources == 0
147 }
148}
149
150impl Default for InMemoryStats {
151 fn default() -> Self {
152 Self::new()
153 }
154}