use crate::resource::{
ListQuery, RequestContext, version::RawVersion, versioned::VersionedResource,
};
use serde_json::Value;
use std::future::Future;
pub trait ResourceProvider {
type Error: std::error::Error + Send + Sync + 'static;
fn create_resource(
&self,
resource_type: &str,
data: Value,
context: &RequestContext,
) -> impl Future<Output = Result<VersionedResource, Self::Error>> + Send;
fn get_resource(
&self,
resource_type: &str,
id: &str,
context: &RequestContext,
) -> impl Future<Output = Result<Option<VersionedResource>, Self::Error>> + Send;
fn update_resource(
&self,
resource_type: &str,
id: &str,
data: Value,
expected_version: Option<&RawVersion>,
context: &RequestContext,
) -> impl Future<Output = Result<VersionedResource, Self::Error>> + Send;
fn delete_resource(
&self,
resource_type: &str,
id: &str,
expected_version: Option<&RawVersion>,
context: &RequestContext,
) -> impl Future<Output = Result<(), Self::Error>> + Send;
fn list_resources(
&self,
resource_type: &str,
_query: Option<&ListQuery>,
context: &RequestContext,
) -> impl Future<Output = Result<Vec<VersionedResource>, Self::Error>> + Send;
fn find_resources_by_attribute(
&self,
resource_type: &str,
attribute_name: &str,
attribute_value: &str,
context: &RequestContext,
) -> impl Future<Output = Result<Vec<VersionedResource>, Self::Error>> + Send;
fn patch_resource(
&self,
resource_type: &str,
id: &str,
patch_request: &Value,
expected_version: Option<&RawVersion>,
context: &RequestContext,
) -> impl Future<Output = Result<VersionedResource, Self::Error>> + Send;
fn resource_exists(
&self,
resource_type: &str,
id: &str,
context: &RequestContext,
) -> impl Future<Output = Result<bool, Self::Error>> + Send;
}
pub trait ResourceProviderExt: ResourceProvider {
fn create_single_tenant(
&self,
resource_type: &str,
data: Value,
request_id: Option<String>,
) -> impl Future<Output = Result<VersionedResource, Self::Error>> + Send
where
Self: Sync,
{
async move {
let context = match request_id {
Some(id) => RequestContext::new(id),
None => RequestContext::with_generated_id(),
};
self.create_resource(resource_type, data, &context).await
}
}
fn get_single_tenant(
&self,
resource_type: &str,
id: &str,
request_id: Option<String>,
) -> impl Future<Output = Result<Option<VersionedResource>, Self::Error>> + Send
where
Self: Sync,
{
async move {
let context = match request_id {
Some(id) => RequestContext::new(id),
None => RequestContext::with_generated_id(),
};
self.get_resource(resource_type, id, &context).await
}
}
fn update_single_tenant(
&self,
resource_type: &str,
id: &str,
data: Value,
expected_version: Option<&RawVersion>,
request_id: Option<String>,
) -> impl Future<Output = Result<VersionedResource, Self::Error>> + Send
where
Self: Sync,
{
async move {
let context = match request_id {
Some(id) => RequestContext::new(id),
None => RequestContext::with_generated_id(),
};
self.update_resource(resource_type, id, data, expected_version, &context)
.await
}
}
fn delete_single_tenant(
&self,
resource_type: &str,
id: &str,
expected_version: Option<&RawVersion>,
request_id: Option<String>,
) -> impl Future<Output = Result<(), Self::Error>> + Send
where
Self: Sync,
{
async move {
let context = match request_id {
Some(id) => RequestContext::new(id),
None => RequestContext::with_generated_id(),
};
self.delete_resource(resource_type, id, expected_version, &context)
.await
}
}
}
impl<T: ResourceProvider> ResourceProviderExt for T {}