add id to response
All checks were successful
Build & Test / build-and-test (push) Successful in 24s
All checks were successful
Build & Test / build-and-test (push) Successful in 24s
This commit is contained in:
@@ -6,7 +6,7 @@ pub trait Compressor: Send {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
pub(self) mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::compressor::*;
|
use crate::compressor::*;
|
||||||
use rstest::*;
|
use rstest::*;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
sha256::Sha256,
|
sha256::Sha256,
|
||||||
shard::{StoreArgs, StoreResult},
|
shard::{StoreArgs, StoreResult, StoreResultKind},
|
||||||
shards::ShardsArc,
|
shards::ShardsArc,
|
||||||
};
|
};
|
||||||
use axum::http::StatusCode;
|
use axum::http::StatusCode;
|
||||||
@@ -19,60 +19,30 @@ pub struct StoreRequest {
|
|||||||
#[derive(Serialize, Debug, PartialEq)]
|
#[derive(Serialize, Debug, PartialEq)]
|
||||||
#[serde(rename_all = "snake_case", tag = "status")]
|
#[serde(rename_all = "snake_case", tag = "status")]
|
||||||
pub enum StoreResponse {
|
pub enum StoreResponse {
|
||||||
Created {
|
Ok(StoreResult),
|
||||||
stored_size: usize,
|
Sha256Mismatch { expected_sha256: String },
|
||||||
data_size: usize,
|
InternalError { message: String },
|
||||||
created_at: String,
|
}
|
||||||
},
|
|
||||||
Exists {
|
impl From<StoreResultKind> for StatusCode {
|
||||||
stored_size: usize,
|
fn from(val: StoreResultKind) -> Self {
|
||||||
data_size: usize,
|
match val {
|
||||||
created_at: String,
|
StoreResultKind::Created => StatusCode::CREATED,
|
||||||
},
|
StoreResultKind::Exists => StatusCode::OK,
|
||||||
Sha256Mismatch {
|
}
|
||||||
expected_sha256: String,
|
}
|
||||||
},
|
|
||||||
InternalError {
|
|
||||||
message: String,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl StoreResponse {
|
impl StoreResponse {
|
||||||
fn status_code(&self) -> StatusCode {
|
fn status_code(&self) -> StatusCode {
|
||||||
match self {
|
match self {
|
||||||
StoreResponse::Created { .. } => StatusCode::CREATED,
|
StoreResponse::Ok(StoreResult { kind, .. }) => (*kind).into(),
|
||||||
StoreResponse::Exists { .. } => StatusCode::OK,
|
|
||||||
StoreResponse::Sha256Mismatch { .. } => StatusCode::BAD_REQUEST,
|
StoreResponse::Sha256Mismatch { .. } => StatusCode::BAD_REQUEST,
|
||||||
StoreResponse::InternalError { .. } => StatusCode::INTERNAL_SERVER_ERROR,
|
StoreResponse::InternalError { .. } => StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<StoreResult> for StoreResponse {
|
|
||||||
fn from(result: StoreResult) -> Self {
|
|
||||||
match result {
|
|
||||||
StoreResult::Created {
|
|
||||||
stored_size,
|
|
||||||
data_size,
|
|
||||||
created_at,
|
|
||||||
} => StoreResponse::Created {
|
|
||||||
stored_size,
|
|
||||||
data_size,
|
|
||||||
created_at: created_at.to_string(),
|
|
||||||
},
|
|
||||||
StoreResult::Exists {
|
|
||||||
stored_size,
|
|
||||||
data_size,
|
|
||||||
created_at,
|
|
||||||
} => StoreResponse::Exists {
|
|
||||||
stored_size,
|
|
||||||
data_size,
|
|
||||||
created_at: created_at.to_string(),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl IntoResponse for StoreResponse {
|
impl IntoResponse for StoreResponse {
|
||||||
fn into_response(self) -> axum::response::Response {
|
fn into_response(self) -> axum::response::Response {
|
||||||
(self.status_code(), Json(self)).into_response()
|
(self.status_code(), Json(self)).into_response()
|
||||||
@@ -91,7 +61,7 @@ pub async fn store_handler(
|
|||||||
if sha256 != req_sha256 {
|
if sha256 != req_sha256 {
|
||||||
let sha256_str = sha256.hex_string();
|
let sha256_str = sha256.hex_string();
|
||||||
error!(
|
error!(
|
||||||
"client sent mismatched sha256: (client) {} != (computed) {}",
|
"sent mismatched sha256: (sent) {} != (computed) {}",
|
||||||
req_sha256, sha256_str
|
req_sha256, sha256_str
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -108,7 +78,7 @@ pub async fn store_handler(
|
|||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
Ok(store_result) => store_result.into(),
|
Ok(store_result) => StoreResponse::Ok(store_result),
|
||||||
Err(err) => StoreResponse::InternalError {
|
Err(err) => StoreResponse::InternalError {
|
||||||
message: err.to_string(),
|
message: err.to_string(),
|
||||||
},
|
},
|
||||||
@@ -117,22 +87,21 @@ pub async fn store_handler(
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
pub mod test {
|
pub mod test {
|
||||||
use crate::{compression_manager::test::make_compressor_with, shards::test::make_shards_with};
|
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::CompressionPolicy;
|
use crate::CompressionPolicy;
|
||||||
|
use crate::{compression_manager::test::make_compressor_with, shards::test::make_shards_with};
|
||||||
use axum::body::Bytes;
|
use axum::body::Bytes;
|
||||||
use axum_typed_multipart::FieldData;
|
use axum_typed_multipart::FieldData;
|
||||||
use rstest::rstest;
|
use rstest::rstest;
|
||||||
|
|
||||||
async fn send_request<D: Into<Bytes>>(
|
async fn send_request_with<D: Into<Bytes>>(
|
||||||
compression_policy: CompressionPolicy,
|
shards: ShardsArc,
|
||||||
sha256: Option<Sha256>,
|
sha256: Option<Sha256>,
|
||||||
content_type: &str,
|
content_type: &str,
|
||||||
data: D,
|
data: D,
|
||||||
) -> StoreResponse {
|
) -> StoreResponse {
|
||||||
store_handler(
|
store_handler(
|
||||||
Extension(make_shards_with(make_compressor_with(compression_policy).into_arc()).await),
|
Extension(shards),
|
||||||
TypedMultipart(StoreRequest {
|
TypedMultipart(StoreRequest {
|
||||||
sha256: sha256.map(|s| s.hex_string()),
|
sha256: sha256.map(|s| s.hex_string()),
|
||||||
content_type: content_type.to_string(),
|
content_type: content_type.to_string(),
|
||||||
@@ -145,12 +114,31 @@ pub mod test {
|
|||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn send_request<D: Into<Bytes>>(
|
||||||
|
compression_policy: CompressionPolicy,
|
||||||
|
sha256: Option<Sha256>,
|
||||||
|
content_type: &str,
|
||||||
|
data: D,
|
||||||
|
) -> StoreResponse {
|
||||||
|
send_request_with(
|
||||||
|
make_shards(compression_policy).await,
|
||||||
|
sha256,
|
||||||
|
content_type,
|
||||||
|
data,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn make_shards(compression_policy: CompressionPolicy) -> ShardsArc {
|
||||||
|
make_shards_with(make_compressor_with(compression_policy).into_arc()).await
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_store_handler() {
|
async fn test_store_handler() {
|
||||||
let result =
|
let result =
|
||||||
send_request(CompressionPolicy::Auto, None, "text/plain", "hello, world!").await;
|
send_request(CompressionPolicy::Auto, None, "text/plain", "hello, world!").await;
|
||||||
assert_eq!(result.status_code(), StatusCode::CREATED, "{:?}", result);
|
assert_eq!(result.status_code(), StatusCode::CREATED, "{:?}", result);
|
||||||
assert!(matches!(result, StoreResponse::Created { .. }));
|
assert!(matches!(result, StoreResponse::Ok(..)));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
@@ -184,7 +172,32 @@ pub mod test {
|
|||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(result.status_code(), StatusCode::CREATED);
|
assert_eq!(result.status_code(), StatusCode::CREATED);
|
||||||
assert!(matches!(result, StoreResponse::Created { .. }));
|
assert!(matches!(result, StoreResponse::Ok(..)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_id() {
|
||||||
|
let shards = make_shards(CompressionPolicy::Auto).await;
|
||||||
|
let data = "hello, world!";
|
||||||
|
let sha256 = Sha256::from_bytes(data.as_bytes());
|
||||||
|
let result = send_request_with(shards.clone(), Some(sha256), "text/plain", data).await;
|
||||||
|
assert_eq!(result.status_code(), StatusCode::CREATED);
|
||||||
|
let result = match result {
|
||||||
|
StoreResponse::Ok(result) => result,
|
||||||
|
_ => panic!("expected StoreResponse::Ok"),
|
||||||
|
};
|
||||||
|
assert_eq!(result.sha256, sha256);
|
||||||
|
assert_eq!(result.kind, StoreResultKind::Created);
|
||||||
|
let id = result.id;
|
||||||
|
|
||||||
|
let result = send_request_with(shards, Some(sha256), "text/plain", data).await;
|
||||||
|
assert_eq!(result.status_code(), StatusCode::OK);
|
||||||
|
let result = match result {
|
||||||
|
StoreResponse::Ok(result) => result,
|
||||||
|
_ => panic!("expected StoreResponse::Ok"),
|
||||||
|
};
|
||||||
|
assert_eq!(result.kind, StoreResultKind::Exists);
|
||||||
|
assert_eq!(result.id, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_assert_eq<T: PartialEq + std::fmt::Debug>(value: T) -> impl Fn(T) {
|
fn make_assert_eq<T: PartialEq + std::fmt::Debug>(value: T) -> impl Fn(T) {
|
||||||
@@ -212,13 +225,15 @@ pub mod test {
|
|||||||
let result = send_request(compression_policy, None, content_type, vec![0; 1024]).await;
|
let result = send_request(compression_policy, None, content_type, vec![0; 1024]).await;
|
||||||
assert_eq!(result.status_code(), StatusCode::CREATED);
|
assert_eq!(result.status_code(), StatusCode::CREATED);
|
||||||
match result {
|
match result {
|
||||||
StoreResponse::Created {
|
StoreResponse::Ok(StoreResult {
|
||||||
|
kind,
|
||||||
stored_size,
|
stored_size,
|
||||||
data_size,
|
data_size,
|
||||||
..
|
..
|
||||||
} => {
|
}) => {
|
||||||
assert_stored_size(stored_size);
|
assert_stored_size(stored_size);
|
||||||
assert_eq!(data_size, 1024);
|
assert_eq!(data_size, 1024);
|
||||||
|
assert_eq!(kind, StoreResultKind::Created);
|
||||||
}
|
}
|
||||||
_ => panic!("expected StoreResponse::Created"),
|
_ => panic!("expected StoreResponse::Created"),
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ use rusqlite::{
|
|||||||
types::{FromSql, ToSqlOutput},
|
types::{FromSql, ToSqlOutput},
|
||||||
ToSql,
|
ToSql,
|
||||||
};
|
};
|
||||||
|
use serde::Serialize;
|
||||||
use sha2::Digest;
|
use sha2::Digest;
|
||||||
use std::{
|
use std::{
|
||||||
error::Error,
|
error::Error,
|
||||||
@@ -50,6 +51,12 @@ impl Sha256 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Serialize for Sha256 {
|
||||||
|
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||||
|
serializer.serialize_bytes(&self.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl ToSql for Sha256 {
|
impl ToSql for Sha256 {
|
||||||
fn to_sql(&self) -> rusqlite::Result<rusqlite::types::ToSqlOutput> {
|
fn to_sql(&self) -> rusqlite::Result<rusqlite::types::ToSqlOutput> {
|
||||||
Ok(ToSqlOutput::Borrowed(rusqlite::types::ValueRef::Blob(
|
Ok(ToSqlOutput::Borrowed(rusqlite::types::ValueRef::Blob(
|
||||||
|
|||||||
@@ -1,23 +1,27 @@
|
|||||||
|
use serde::Serialize;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::{
|
use crate::{
|
||||||
compressible_data::CompressibleData,
|
compressible_data::CompressibleData,
|
||||||
concat_lines, into_tokio_rusqlite_err,
|
concat_lines, into_tokio_rusqlite_err,
|
||||||
sql_types::{CompressionId, UtcDateTime},
|
sql_types::{CompressionId, EntryId, UtcDateTime},
|
||||||
AsyncBoxError,
|
AsyncBoxError,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(PartialEq, Debug)]
|
#[derive(PartialEq, Debug, Serialize, Copy, Clone)]
|
||||||
pub enum StoreResult {
|
pub enum StoreResultKind {
|
||||||
Created {
|
Created,
|
||||||
stored_size: usize,
|
Exists,
|
||||||
data_size: usize,
|
}
|
||||||
created_at: UtcDateTime,
|
|
||||||
},
|
#[derive(PartialEq, Debug, Serialize)]
|
||||||
Exists {
|
pub struct StoreResult {
|
||||||
stored_size: usize,
|
pub kind: StoreResultKind,
|
||||||
data_size: usize,
|
pub id: EntryId,
|
||||||
created_at: UtcDateTime,
|
pub sha256: Sha256,
|
||||||
},
|
pub stored_size: usize,
|
||||||
|
pub data_size: usize,
|
||||||
|
pub created_at: UtcDateTime,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
@@ -75,16 +79,19 @@ fn find_with_sha256(
|
|||||||
) -> Result<Option<StoreResult>, rusqlite::Error> {
|
) -> Result<Option<StoreResult>, rusqlite::Error> {
|
||||||
conn.query_row(
|
conn.query_row(
|
||||||
concat_lines!(
|
concat_lines!(
|
||||||
"SELECT uncompressed_size, compressed_size, created_at",
|
"SELECT rowid, uncompressed_size, compressed_size, created_at",
|
||||||
"FROM entries",
|
"FROM entries",
|
||||||
"WHERE sha256 = ?"
|
"WHERE sha256 = ?"
|
||||||
),
|
),
|
||||||
params![sha256],
|
params![sha256],
|
||||||
|row| {
|
|row| {
|
||||||
Ok(StoreResult::Exists {
|
Ok(StoreResult {
|
||||||
stored_size: row.get(0)?,
|
kind: StoreResultKind::Exists,
|
||||||
data_size: row.get(1)?,
|
id: row.get(0)?,
|
||||||
created_at: row.get(2)?,
|
sha256: *sha256,
|
||||||
|
stored_size: row.get(1)?,
|
||||||
|
data_size: row.get(2)?,
|
||||||
|
created_at: row.get(3)?,
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@@ -102,11 +109,12 @@ fn insert(
|
|||||||
let created_at = UtcDateTime::now();
|
let created_at = UtcDateTime::now();
|
||||||
let compressed_size = data.len();
|
let compressed_size = data.len();
|
||||||
|
|
||||||
conn.execute(
|
let id = conn.query_row(
|
||||||
concat_lines!(
|
concat_lines!(
|
||||||
"INSERT INTO entries",
|
"INSERT INTO entries",
|
||||||
" (sha256, content_type, dict_id, uncompressed_size, compressed_size, data, created_at)",
|
" (sha256, content_type, dict_id, uncompressed_size, compressed_size, data, created_at)",
|
||||||
"VALUES (?, ?, ?, ?, ?, ?, ?)",
|
"VALUES (?, ?, ?, ?, ?, ?, ?)",
|
||||||
|
"RETURNING rowid"
|
||||||
),
|
),
|
||||||
params![
|
params![
|
||||||
sha256,
|
sha256,
|
||||||
@@ -117,9 +125,13 @@ fn insert(
|
|||||||
data.as_ref(),
|
data.as_ref(),
|
||||||
created_at,
|
created_at,
|
||||||
],
|
],
|
||||||
|
|row| row.get(0),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
Ok(StoreResult::Created {
|
Ok(StoreResult {
|
||||||
|
kind: StoreResultKind::Created,
|
||||||
|
id,
|
||||||
|
sha256: *sha256,
|
||||||
stored_size: compressed_size,
|
stored_size: compressed_size,
|
||||||
data_size: uncompressed_size,
|
data_size: uncompressed_size,
|
||||||
created_at,
|
created_at,
|
||||||
|
|||||||
@@ -5,15 +5,15 @@ pub mod shard_error;
|
|||||||
mod shard_struct;
|
mod shard_struct;
|
||||||
|
|
||||||
pub use fn_get::{GetArgs, GetResult};
|
pub use fn_get::{GetArgs, GetResult};
|
||||||
pub use fn_store::{StoreArgs, StoreResult};
|
pub use fn_store::{StoreArgs, StoreResult, StoreResultKind};
|
||||||
pub use shard_struct::Shard;
|
pub use shard_struct::Shard;
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
pub mod test {
|
|
||||||
pub use super::shard_struct::test::*;
|
|
||||||
}
|
|
||||||
use crate::{sha256::Sha256, shard::shard_error::ShardError};
|
use crate::{sha256::Sha256, shard::shard_error::ShardError};
|
||||||
use axum::body::Bytes;
|
use axum::body::Bytes;
|
||||||
use rusqlite::{params, types::FromSql, OptionalExtension};
|
use rusqlite::{params, types::FromSql, OptionalExtension};
|
||||||
use tokio_rusqlite::Connection;
|
use tokio_rusqlite::Connection;
|
||||||
use tracing::debug;
|
use tracing::debug;
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
pub mod test {
|
||||||
|
pub use super::shard_struct::test::*;
|
||||||
|
}
|
||||||
|
|||||||
@@ -64,10 +64,11 @@ async fn get_num_entries(conn: &Connection) -> Result<usize, tokio_rusqlite::Err
|
|||||||
pub mod test {
|
pub mod test {
|
||||||
use crate::compression_manager::test::make_compressor_with;
|
use crate::compression_manager::test::make_compressor_with;
|
||||||
use crate::compression_manager::CompressionManagerArc;
|
use crate::compression_manager::CompressionManagerArc;
|
||||||
|
use crate::shard::fn_store::StoreResultKind;
|
||||||
use crate::{
|
use crate::{
|
||||||
compression_manager::test::make_compressor,
|
compression_manager::test::make_compressor,
|
||||||
sha256::Sha256,
|
sha256::Sha256,
|
||||||
shard::{GetArgs, StoreArgs, StoreResult},
|
shard::{GetArgs, StoreArgs},
|
||||||
CompressionPolicy,
|
CompressionPolicy,
|
||||||
};
|
};
|
||||||
use rstest::rstest;
|
use rstest::rstest;
|
||||||
@@ -113,22 +114,14 @@ pub mod test {
|
|||||||
sha256,
|
sha256,
|
||||||
content_type: "text/plain".to_string(),
|
content_type: "text/plain".to_string(),
|
||||||
data: data.into(),
|
data: data.into(),
|
||||||
..Default::default()
|
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
match store_result {
|
|
||||||
StoreResult::Created {
|
assert_eq!(store_result.kind, StoreResultKind::Created);
|
||||||
stored_size: _,
|
assert_eq!(store_result.sha256, sha256);
|
||||||
data_size,
|
assert_eq!(store_result.data_size, data.len());
|
||||||
created_at,
|
assert!(store_result.created_at > chrono::Utc::now() - chrono::Duration::seconds(1));
|
||||||
} => {
|
|
||||||
// assert_eq!(stored_size, data.len());
|
|
||||||
assert_eq!(data_size, data.len());
|
|
||||||
assert!(created_at > chrono::Utc::now() - chrono::Duration::seconds(1));
|
|
||||||
}
|
|
||||||
_ => panic!("expected StoreResult::Created"),
|
|
||||||
}
|
|
||||||
assert_eq!(shard.num_entries().await.unwrap(), 1);
|
assert_eq!(shard.num_entries().await.unwrap(), 1);
|
||||||
|
|
||||||
let get_result = shard.get(GetArgs { sha256 }).await.unwrap().unwrap();
|
let get_result = shard.get(GetArgs { sha256 }).await.unwrap().unwrap();
|
||||||
@@ -148,42 +141,31 @@ pub mod test {
|
|||||||
sha256,
|
sha256,
|
||||||
content_type: "text/plain".to_string(),
|
content_type: "text/plain".to_string(),
|
||||||
data: data.into(),
|
data: data.into(),
|
||||||
..Default::default()
|
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert!(matches!(store_result, StoreResult::Created { .. }));
|
|
||||||
|
|
||||||
let created_at = match store_result {
|
assert_eq!(store_result.kind, StoreResultKind::Created);
|
||||||
StoreResult::Created {
|
assert_eq!(store_result.sha256, sha256);
|
||||||
stored_size,
|
assert_eq!(store_result.stored_size, data.len());
|
||||||
data_size,
|
assert_eq!(store_result.data_size, data.len());
|
||||||
created_at,
|
let created_at = store_result.created_at;
|
||||||
} => {
|
|
||||||
assert_eq!(stored_size, data.len());
|
|
||||||
assert_eq!(data_size, data.len());
|
|
||||||
created_at
|
|
||||||
}
|
|
||||||
_ => panic!("expected StoreResult::Created"),
|
|
||||||
};
|
|
||||||
|
|
||||||
let store_result = shard
|
let store_result = shard
|
||||||
.store(StoreArgs {
|
.store(StoreArgs {
|
||||||
sha256,
|
sha256,
|
||||||
content_type: "text/plain".to_string(),
|
content_type: "text/plain".to_string(),
|
||||||
data: data.into(),
|
data: data.into(),
|
||||||
..Default::default()
|
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(
|
|
||||||
store_result,
|
assert_eq!(store_result.kind, StoreResultKind::Exists);
|
||||||
StoreResult::Exists {
|
assert_eq!(store_result.sha256, sha256);
|
||||||
data_size: data.len(),
|
assert_eq!(store_result.data_size, data.len(),);
|
||||||
stored_size: data.len(),
|
assert_eq!(store_result.stored_size, data.len(),);
|
||||||
created_at
|
assert_eq!(store_result.created_at, created_at);
|
||||||
}
|
|
||||||
);
|
|
||||||
assert_eq!(shard.num_entries().await.unwrap(), 1);
|
assert_eq!(shard.num_entries().await.unwrap(), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -213,11 +195,10 @@ pub mod test {
|
|||||||
sha256,
|
sha256,
|
||||||
content_type: content_type.clone(),
|
content_type: content_type.clone(),
|
||||||
data: data.clone().into(),
|
data: data.clone().into(),
|
||||||
..Default::default()
|
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert!(matches!(store_result, StoreResult::Created { .. }));
|
assert_eq!(store_result.kind, StoreResultKind::Created);
|
||||||
|
|
||||||
let get_result = shard.get(GetArgs { sha256 }).await.unwrap().unwrap();
|
let get_result = shard.get(GetArgs { sha256 }).await.unwrap().unwrap();
|
||||||
assert_eq!(get_result.content_type, content_type);
|
assert_eq!(get_result.content_type, content_type);
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ use rusqlite::{
|
|||||||
types::{FromSql, FromSqlResult, ToSqlOutput, ValueRef},
|
types::{FromSql, FromSqlResult, ToSqlOutput, ValueRef},
|
||||||
ToSql,
|
ToSql,
|
||||||
};
|
};
|
||||||
|
use serde::Serialize;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)]
|
#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)]
|
||||||
pub struct EntryId(pub i64);
|
pub struct EntryId(pub i64);
|
||||||
@@ -11,6 +12,12 @@ impl From<i64> for EntryId {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Serialize for EntryId {
|
||||||
|
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||||
|
self.0.serialize(serializer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl FromSql for EntryId {
|
impl FromSql for EntryId {
|
||||||
fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self> {
|
fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self> {
|
||||||
Ok(value.as_i64()?.into())
|
Ok(value.as_i64()?.into())
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
mod compression_id;
|
mod compression_id;
|
||||||
|
mod entry_id;
|
||||||
mod utc_date_time;
|
mod utc_date_time;
|
||||||
|
|
||||||
pub use compression_id::CompressionId;
|
pub use compression_id::CompressionId;
|
||||||
|
pub use entry_id::EntryId;
|
||||||
pub use utc_date_time::UtcDateTime;
|
pub use utc_date_time::UtcDateTime;
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ use rusqlite::{
|
|||||||
types::{FromSql, FromSqlError, ToSqlOutput, ValueRef},
|
types::{FromSql, FromSqlError, ToSqlOutput, ValueRef},
|
||||||
Result, ToSql,
|
Result, ToSql,
|
||||||
};
|
};
|
||||||
|
use serde::Serialize;
|
||||||
|
|
||||||
#[derive(PartialEq, Debug, PartialOrd)]
|
#[derive(PartialEq, Debug, PartialOrd)]
|
||||||
pub struct UtcDateTime(DateTime<chrono::Utc>);
|
pub struct UtcDateTime(DateTime<chrono::Utc>);
|
||||||
@@ -24,6 +25,12 @@ impl ToString for UtcDateTime {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Serialize for UtcDateTime {
|
||||||
|
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||||
|
serializer.serialize_str(&self.to_string())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl PartialEq<DateTime<chrono::Utc>> for UtcDateTime {
|
impl PartialEq<DateTime<chrono::Utc>> for UtcDateTime {
|
||||||
fn eq(&self, other: &DateTime<chrono::Utc>) -> bool {
|
fn eq(&self, other: &DateTime<chrono::Utc>) -> bool {
|
||||||
self.0 == *other
|
self.0 == *other
|
||||||
|
|||||||
Reference in New Issue
Block a user