#![allow(dead_code)]
use serde::Serialize;
use utoipa::ToSchema;
#[derive(Serialize, ToSchema)]
pub(crate) struct StorageObject {
collection: String,
key: String,
owner: i64,
#[schema(value_type = Value)]
value: serde_json::Value,
version: i64,
write: String,
updated_at: i64,
}
#[derive(Serialize, ToSchema)]
pub(crate) struct StorageObjectInfo {
collection: String,
key: String,
version: i64,
write: String,
size_bytes: u64,
updated_at: i64,
}
#[derive(Serialize, ToSchema)]
pub(crate) struct StorageObjectInfoPage {
items: Vec<StorageObjectInfo>,
next_cursor: Option<String>,
}
#[derive(Serialize, ToSchema)]
pub(crate) struct ObjectAck {
collection: String,
key: String,
version: i64,
updated_at: i64,
}
#[derive(Serialize, ToSchema)]
pub(crate) struct PutObject {
#[schema(value_type = Value)]
value: serde_json::Value,
if_version: Option<i64>,
}
#[derive(Serialize, ToSchema)]
pub(crate) struct ObjectRef {
collection: String,
key: String,
}
#[derive(Serialize, ToSchema)]
pub(crate) struct BatchGet {
objects: Vec<ObjectRef>,
}
#[derive(Serialize, ToSchema)]
pub(crate) struct BatchObjects {
objects: Vec<StorageObject>,
}
#[derive(Serialize, ToSchema)]
pub(crate) struct BatchPutItem {
collection: String,
key: String,
#[schema(value_type = Value)]
value: serde_json::Value,
if_version: Option<i64>,
}
#[derive(Serialize, ToSchema)]
pub(crate) struct BatchPut {
objects: Vec<BatchPutItem>,
}
#[derive(Serialize, ToSchema)]
pub(crate) struct BatchAcks {
objects: Vec<ObjectAck>,
}
#[derive(Serialize, ToSchema)]
pub(crate) struct AdminPutObject {
#[schema(value_type = Value)]
value: serde_json::Value,
if_version: Option<i64>,
write: Option<String>,
}
#[derive(Serialize, ToSchema)]
pub(crate) struct VersionConflict {
index: Option<u32>,
current_version: Option<i64>,
}
#[derive(Serialize, ToSchema)]
pub(crate) struct Ack {}
#[cfg(test)]
mod tests {
use std::collections::BTreeSet;
use net_backend_protocol::admin as p_admin;
use net_backend_protocol::storage as p;
use net_backend_protocol::{Cursor, Page, UnixMillis, UserId};
use serde_json::{json, Value};
use utoipa::openapi::schema::Schema;
use utoipa::openapi::RefOr;
use utoipa::PartialSchema;
use super::*;
fn properties<T: PartialSchema>() -> BTreeSet<String> {
match T::schema() {
RefOr::T(Schema::Object(object)) => object.properties.keys().cloned().collect(),
_ => BTreeSet::new(),
}
}
fn keys(value: impl serde::Serialize) -> BTreeSet<String> {
match serde_json::to_value(value) {
Ok(Value::Object(map)) => map.keys().cloned().collect(),
_ => BTreeSet::new(),
}
}
#[test]
fn mirrors_match_the_protocol() {
let t = UnixMillis(1);
let object = p::StorageObject::new("s", "k", UserId(1), json!({}), p::ObjectVersion(1), t);
assert_eq!(properties::<StorageObject>(), keys(&object));
assert_eq!(properties::<StorageObjectInfo>(), keys(object.info()));
assert_eq!(properties::<StorageObjectInfoPage>(), keys(Page::new(vec![object.info()], Some(Cursor::new("k")))));
assert_eq!(properties::<ObjectAck>(), keys(p::ObjectAck::new("s", "k", p::ObjectVersion(1), t)));
assert_eq!(properties::<PutObject>(), keys(p::PutObject::new(json!(1)).if_absent()));
assert_eq!(properties::<ObjectRef>(), keys(p::ObjectRef::new("s", "k")));
assert_eq!(properties::<BatchGet>(), keys(p::BatchGet::new(vec![])));
assert_eq!(properties::<BatchObjects>(), keys(p::BatchObjects::new(vec![])));
assert_eq!(properties::<BatchPutItem>(), keys(p::BatchPutItem::new("s", "k", p::PutObject::new(json!(1)).if_absent())));
assert_eq!(properties::<BatchPut>(), keys(p::BatchPut::new(vec![])));
assert_eq!(properties::<BatchAcks>(), keys(p::BatchAcks::new(vec![])));
assert_eq!(
properties::<AdminPutObject>(),
keys(p_admin::AdminPutObject::new(json!(1)).if_version(p::ObjectVersion(1)).with_write(p::WriteAccess::Server))
);
assert_eq!(properties::<VersionConflict>(), keys(p::VersionConflict::new(Some(p::ObjectVersion(1))).at_index(0)));
}
}