pub trait StorageAdapter: Send + Sync {
// Required methods
fn all_schemas(
&self,
) -> impl Future<Output = Result<Vec<ClassSchema>, ParseError>> + Send;
fn upsert_schema(
&self,
schema: &ClassSchema,
) -> impl Future<Output = Result<(), ParseError>> + Send;
fn create(
&self,
schema: &ClassSchema,
row: &Row,
) -> impl Future<Output = Result<WriteResult, ParseError>> + Send;
fn find(
&self,
schema: &ClassSchema,
constraints: &[Constraint],
options: &QueryOptions,
) -> impl Future<Output = Result<Vec<Row>, ParseError>> + Send;
fn count(
&self,
schema: &ClassSchema,
constraints: &[Constraint],
) -> impl Future<Output = Result<u64, ParseError>> + Send;
fn update(
&self,
schema: &ClassSchema,
constraints: &[Constraint],
values: &Row,
) -> impl Future<Output = Result<u64, ParseError>> + Send;
fn delete(
&self,
schema: &ClassSchema,
constraints: &[Constraint],
) -> impl Future<Output = Result<u64, ParseError>> + Send;
fn ensure_unique_index(
&self,
class_name: &str,
fields: &[&str],
name: Option<&str>,
) -> impl Future<Output = Result<(), ParseError>> + Send;
}Expand description
Storage operations.
async fn in trait, so this is not object-safe. That is deliberate for now: the server holds
one concrete adapter chosen at construction, and boxing every call to support a dyn we do
not need would cost allocations on the hot path. If a deployment ever needs to swap adapters
at runtime, add a boxed wrapper rather than degrading this.
Required Methods§
Sourcefn all_schemas(
&self,
) -> impl Future<Output = Result<Vec<ClassSchema>, ParseError>> + Send
fn all_schemas( &self, ) -> impl Future<Output = Result<Vec<ClassSchema>, ParseError>> + Send
Load every class schema. Upstream has no per-class fetch: a miss on any class triggers a
full getAllClasses, and reproducing that shape keeps the caching behavior comparable.
Sourcefn upsert_schema(
&self,
schema: &ClassSchema,
) -> impl Future<Output = Result<(), ParseError>> + Send
fn upsert_schema( &self, schema: &ClassSchema, ) -> impl Future<Output = Result<(), ParseError>> + Send
Persist a class schema, creating the class if it does not exist.
Sourcefn create(
&self,
schema: &ClassSchema,
row: &Row,
) -> impl Future<Output = Result<WriteResult, ParseError>> + Send
fn create( &self, schema: &ClassSchema, row: &Row, ) -> impl Future<Output = Result<WriteResult, ParseError>> + Send
Insert one row. object_id is generated by the caller, not the adapter, because it is
part of the Parse contract rather than a storage detail.
Sourcefn find(
&self,
schema: &ClassSchema,
constraints: &[Constraint],
options: &QueryOptions,
) -> impl Future<Output = Result<Vec<Row>, ParseError>> + Send
fn find( &self, schema: &ClassSchema, constraints: &[Constraint], options: &QueryOptions, ) -> impl Future<Output = Result<Vec<Row>, ParseError>> + Send
Find rows matching every constraint.
Sourcefn count(
&self,
schema: &ClassSchema,
constraints: &[Constraint],
) -> impl Future<Output = Result<u64, ParseError>> + Send
fn count( &self, schema: &ClassSchema, constraints: &[Constraint], ) -> impl Future<Output = Result<u64, ParseError>> + Send
Count rows matching every constraint.
Sourcefn update(
&self,
schema: &ClassSchema,
constraints: &[Constraint],
values: &Row,
) -> impl Future<Output = Result<u64, ParseError>> + Send
fn update( &self, schema: &ClassSchema, constraints: &[Constraint], values: &Row, ) -> impl Future<Output = Result<u64, ParseError>> + Send
Update matching rows with the given field values.
Returns how many rows matched, so a caller can distinguish “updated nothing because the
object does not exist” from “updated nothing because the ACL excluded it”. Upstream
conflates those into OBJECT_NOT_FOUND, which is the behavior to reproduce at the REST
layer, but the adapter should not throw the information away before then.
Sourcefn delete(
&self,
schema: &ClassSchema,
constraints: &[Constraint],
) -> impl Future<Output = Result<u64, ParseError>> + Send
fn delete( &self, schema: &ClassSchema, constraints: &[Constraint], ) -> impl Future<Output = Result<u64, ParseError>> + Send
Delete matching rows. Returns how many, for the same reason as update.
Sourcefn ensure_unique_index(
&self,
class_name: &str,
fields: &[&str],
name: Option<&str>,
) -> impl Future<Output = Result<(), ParseError>> + Send
fn ensure_unique_index( &self, class_name: &str, fields: &[&str], name: Option<&str>, ) -> impl Future<Output = Result<(), ParseError>> + Send
Create a unique index.
Index names are part of the contract. Both adapters recover duplicated_field by regex
over the index name, and the Mongo regex matches only auto-generated <field>_1 names, so
a differently-named index changes the error a client sees. name: None means “let the
backend auto-name it”, which is what produces username_1.
Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".