2022-04-24 22:10:15 +00:00
|
|
|
use crate::{
|
|
|
|
config,
|
|
|
|
details::Details,
|
2023-07-26 01:08:18 +00:00
|
|
|
store::{Identifier, StoreError},
|
2023-08-16 00:19:03 +00:00
|
|
|
stream::LocalBoxStream,
|
2022-04-24 22:10:15 +00:00
|
|
|
};
|
2023-08-15 01:00:00 +00:00
|
|
|
use std::{fmt::Debug, sync::Arc};
|
2023-07-23 15:23:37 +00:00
|
|
|
use url::Url;
|
2022-03-24 18:16:41 +00:00
|
|
|
use uuid::Uuid;
|
|
|
|
|
2023-08-14 03:06:42 +00:00
|
|
|
mod hash;
|
2023-08-16 00:19:03 +00:00
|
|
|
mod migrate;
|
2022-03-24 22:09:15 +00:00
|
|
|
pub(crate) mod sled;
|
|
|
|
|
2023-08-14 03:06:42 +00:00
|
|
|
pub(crate) use hash::Hash;
|
2023-08-16 00:19:03 +00:00
|
|
|
pub(crate) use migrate::migrate_04;
|
|
|
|
|
|
|
|
pub(crate) type ArcRepo = Arc<dyn FullRepo>;
|
2023-08-14 03:06:42 +00:00
|
|
|
|
2022-03-26 21:49:23 +00:00
|
|
|
#[derive(Clone, Debug)]
|
2022-03-25 23:47:50 +00:00
|
|
|
pub(crate) enum Repo {
|
|
|
|
Sled(self::sled::SledRepo),
|
|
|
|
}
|
|
|
|
|
2022-03-26 21:49:23 +00:00
|
|
|
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
|
|
|
enum MaybeUuid {
|
|
|
|
Uuid(Uuid),
|
|
|
|
Name(String),
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
2022-03-24 18:16:41 +00:00
|
|
|
pub(crate) struct Alias {
|
2022-03-26 21:49:23 +00:00
|
|
|
id: MaybeUuid,
|
|
|
|
extension: Option<String>,
|
2022-03-24 18:16:41 +00:00
|
|
|
}
|
2022-03-25 03:06:29 +00:00
|
|
|
|
2023-07-26 01:08:18 +00:00
|
|
|
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
2022-03-24 18:16:41 +00:00
|
|
|
pub(crate) struct DeleteToken {
|
2022-03-26 21:49:23 +00:00
|
|
|
id: MaybeUuid,
|
2022-03-24 18:16:41 +00:00
|
|
|
}
|
2022-03-25 03:06:29 +00:00
|
|
|
|
2023-08-16 00:19:03 +00:00
|
|
|
#[derive(Debug)]
|
2023-07-07 18:17:26 +00:00
|
|
|
pub(crate) struct HashAlreadyExists;
|
2023-08-16 00:19:03 +00:00
|
|
|
#[derive(Debug)]
|
2023-07-07 18:17:26 +00:00
|
|
|
pub(crate) struct AliasAlreadyExists;
|
2023-08-16 20:12:16 +00:00
|
|
|
#[derive(Debug)]
|
|
|
|
pub(crate) struct VariantAlreadyExists;
|
2023-07-07 18:17:26 +00:00
|
|
|
|
2022-04-03 01:56:29 +00:00
|
|
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
2022-04-01 21:51:12 +00:00
|
|
|
pub(crate) struct UploadId {
|
|
|
|
id: Uuid,
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) enum UploadResult {
|
|
|
|
Success { alias: Alias, token: DeleteToken },
|
|
|
|
Failure { message: String },
|
|
|
|
}
|
|
|
|
|
2023-06-20 20:59:08 +00:00
|
|
|
#[derive(Debug, thiserror::Error)]
|
|
|
|
pub(crate) enum RepoError {
|
|
|
|
#[error("Error in sled")]
|
|
|
|
SledError(#[from] crate::repo::sled::SledError),
|
|
|
|
|
|
|
|
#[error("Upload was already claimed")]
|
|
|
|
AlreadyClaimed,
|
|
|
|
|
|
|
|
#[error("Panic in blocking operation")]
|
|
|
|
Canceled,
|
2023-07-05 14:52:19 +00:00
|
|
|
}
|
|
|
|
|
2022-04-02 21:44:03 +00:00
|
|
|
#[async_trait::async_trait(?Send)]
|
|
|
|
pub(crate) trait FullRepo:
|
2023-02-25 17:34:48 +00:00
|
|
|
UploadRepo
|
2022-04-02 21:44:03 +00:00
|
|
|
+ SettingsRepo
|
2023-08-16 21:09:40 +00:00
|
|
|
+ DetailsRepo
|
2022-04-02 21:44:03 +00:00
|
|
|
+ AliasRepo
|
|
|
|
+ QueueRepo
|
|
|
|
+ HashRepo
|
2023-08-16 16:47:36 +00:00
|
|
|
+ StoreMigrationRepo
|
2023-07-19 02:56:13 +00:00
|
|
|
+ AliasAccessRepo
|
2023-07-22 22:57:52 +00:00
|
|
|
+ VariantAccessRepo
|
2023-07-23 15:23:37 +00:00
|
|
|
+ ProxyRepo
|
2022-04-02 21:44:03 +00:00
|
|
|
+ Send
|
|
|
|
+ Sync
|
|
|
|
+ Debug
|
|
|
|
{
|
2023-06-20 20:59:08 +00:00
|
|
|
async fn health_check(&self) -> Result<(), RepoError>;
|
2023-01-29 17:36:09 +00:00
|
|
|
|
2022-09-28 04:19:52 +00:00
|
|
|
#[tracing::instrument(skip(self))]
|
2023-08-16 00:19:03 +00:00
|
|
|
async fn identifier_from_alias(&self, alias: &Alias) -> Result<Option<Arc<[u8]>>, RepoError> {
|
2023-07-05 21:46:44 +00:00
|
|
|
let Some(hash) = self.hash(alias).await? else {
|
|
|
|
return Ok(None);
|
|
|
|
};
|
|
|
|
|
2023-07-07 18:17:26 +00:00
|
|
|
self.identifier(hash).await
|
2022-04-02 21:44:03 +00:00
|
|
|
}
|
|
|
|
|
2022-09-28 04:19:52 +00:00
|
|
|
#[tracing::instrument(skip(self))]
|
2023-06-20 20:59:08 +00:00
|
|
|
async fn aliases_from_alias(&self, alias: &Alias) -> Result<Vec<Alias>, RepoError> {
|
2023-07-05 21:46:44 +00:00
|
|
|
let Some(hash) = self.hash(alias).await? else {
|
|
|
|
return Ok(vec![]);
|
|
|
|
};
|
|
|
|
|
2023-07-26 01:08:18 +00:00
|
|
|
self.for_hash(hash).await
|
2022-04-02 21:44:03 +00:00
|
|
|
}
|
|
|
|
|
2022-09-28 04:19:52 +00:00
|
|
|
#[tracing::instrument(skip(self))]
|
2023-08-16 00:19:03 +00:00
|
|
|
async fn still_identifier_from_alias(
|
2022-04-02 21:44:03 +00:00
|
|
|
&self,
|
|
|
|
alias: &Alias,
|
2023-08-16 00:19:03 +00:00
|
|
|
) -> Result<Option<Arc<[u8]>>, StoreError> {
|
2023-07-05 21:46:44 +00:00
|
|
|
let Some(hash) = self.hash(alias).await? else {
|
|
|
|
return Ok(None);
|
|
|
|
};
|
|
|
|
|
2023-08-16 00:19:03 +00:00
|
|
|
let Some(identifier) = self.identifier(hash.clone()).await? else {
|
2023-07-07 18:17:26 +00:00
|
|
|
return Ok(None);
|
|
|
|
};
|
2022-04-02 21:44:03 +00:00
|
|
|
|
|
|
|
match self.details(&identifier).await? {
|
2023-08-16 00:19:03 +00:00
|
|
|
Some(details) if details.is_video() => {
|
|
|
|
self.motion_identifier(hash).await.map_err(From::from)
|
|
|
|
}
|
2022-04-02 21:44:03 +00:00
|
|
|
Some(_) => Ok(Some(identifier)),
|
|
|
|
None => Ok(None),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-29 17:36:09 +00:00
|
|
|
#[async_trait::async_trait(?Send)]
|
2023-08-16 00:19:03 +00:00
|
|
|
impl<T> FullRepo for Arc<T>
|
2023-01-29 17:47:28 +00:00
|
|
|
where
|
|
|
|
T: FullRepo,
|
|
|
|
{
|
2023-06-20 20:59:08 +00:00
|
|
|
async fn health_check(&self) -> Result<(), RepoError> {
|
2023-01-29 17:36:09 +00:00
|
|
|
T::health_check(self).await
|
|
|
|
}
|
|
|
|
}
|
2022-09-11 00:29:22 +00:00
|
|
|
|
2023-08-15 01:00:00 +00:00
|
|
|
pub(crate) trait BaseRepo {}
|
2022-03-29 17:51:16 +00:00
|
|
|
|
2023-08-16 00:19:03 +00:00
|
|
|
impl<T> BaseRepo for Arc<T> where T: BaseRepo {}
|
2022-09-11 00:29:22 +00:00
|
|
|
|
2023-07-23 15:23:37 +00:00
|
|
|
#[async_trait::async_trait(?Send)]
|
|
|
|
pub(crate) trait ProxyRepo: BaseRepo {
|
|
|
|
async fn relate_url(&self, url: Url, alias: Alias) -> Result<(), RepoError>;
|
|
|
|
|
|
|
|
async fn related(&self, url: Url) -> Result<Option<Alias>, RepoError>;
|
|
|
|
|
|
|
|
async fn remove_relation(&self, alias: Alias) -> Result<(), RepoError>;
|
|
|
|
}
|
|
|
|
|
|
|
|
#[async_trait::async_trait(?Send)]
|
2023-08-16 00:19:03 +00:00
|
|
|
impl<T> ProxyRepo for Arc<T>
|
2023-07-23 15:23:37 +00:00
|
|
|
where
|
|
|
|
T: ProxyRepo,
|
|
|
|
{
|
|
|
|
async fn relate_url(&self, url: Url, alias: Alias) -> Result<(), RepoError> {
|
|
|
|
T::relate_url(self, url, alias).await
|
|
|
|
}
|
|
|
|
|
|
|
|
async fn related(&self, url: Url) -> Result<Option<Alias>, RepoError> {
|
|
|
|
T::related(self, url).await
|
|
|
|
}
|
|
|
|
|
|
|
|
async fn remove_relation(&self, alias: Alias) -> Result<(), RepoError> {
|
|
|
|
T::remove_relation(self, alias).await
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-07-19 02:56:13 +00:00
|
|
|
#[async_trait::async_trait(?Send)]
|
|
|
|
pub(crate) trait AliasAccessRepo: BaseRepo {
|
2023-08-16 21:09:40 +00:00
|
|
|
async fn accessed_alias(&self, alias: Alias) -> Result<(), RepoError> {
|
|
|
|
self.set_accessed_alias(alias, time::OffsetDateTime::now_utc())
|
|
|
|
.await
|
|
|
|
}
|
|
|
|
|
|
|
|
async fn set_accessed_alias(
|
|
|
|
&self,
|
|
|
|
alias: Alias,
|
|
|
|
accessed: time::OffsetDateTime,
|
|
|
|
) -> Result<(), RepoError>;
|
|
|
|
|
|
|
|
async fn alias_accessed_at(
|
|
|
|
&self,
|
|
|
|
alias: Alias,
|
|
|
|
) -> Result<Option<time::OffsetDateTime>, RepoError>;
|
2023-07-19 02:56:13 +00:00
|
|
|
|
|
|
|
async fn older_aliases(
|
|
|
|
&self,
|
|
|
|
timestamp: time::OffsetDateTime,
|
2023-08-16 00:19:03 +00:00
|
|
|
) -> Result<LocalBoxStream<'static, Result<Alias, RepoError>>, RepoError>;
|
2023-07-19 02:56:13 +00:00
|
|
|
|
2023-08-16 21:09:40 +00:00
|
|
|
async fn remove_alias_access(&self, alias: Alias) -> Result<(), RepoError>;
|
2023-07-19 02:56:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[async_trait::async_trait(?Send)]
|
2023-08-16 00:19:03 +00:00
|
|
|
impl<T> AliasAccessRepo for Arc<T>
|
2023-07-19 02:56:13 +00:00
|
|
|
where
|
|
|
|
T: AliasAccessRepo,
|
|
|
|
{
|
2023-08-16 21:09:40 +00:00
|
|
|
async fn set_accessed_alias(
|
|
|
|
&self,
|
|
|
|
alias: Alias,
|
|
|
|
accessed: time::OffsetDateTime,
|
|
|
|
) -> Result<(), RepoError> {
|
|
|
|
T::set_accessed_alias(self, alias, accessed).await
|
|
|
|
}
|
|
|
|
|
|
|
|
async fn alias_accessed_at(
|
|
|
|
&self,
|
|
|
|
alias: Alias,
|
|
|
|
) -> Result<Option<time::OffsetDateTime>, RepoError> {
|
|
|
|
T::alias_accessed_at(self, alias).await
|
2023-07-19 02:56:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
async fn older_aliases(
|
|
|
|
&self,
|
|
|
|
timestamp: time::OffsetDateTime,
|
2023-08-16 00:19:03 +00:00
|
|
|
) -> Result<LocalBoxStream<'static, Result<Alias, RepoError>>, RepoError> {
|
2023-07-19 02:56:13 +00:00
|
|
|
T::older_aliases(self, timestamp).await
|
|
|
|
}
|
|
|
|
|
2023-08-16 21:09:40 +00:00
|
|
|
async fn remove_alias_access(&self, alias: Alias) -> Result<(), RepoError> {
|
|
|
|
T::remove_alias_access(self, alias).await
|
2023-07-19 02:56:13 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[async_trait::async_trait(?Send)]
|
2023-07-22 22:57:52 +00:00
|
|
|
pub(crate) trait VariantAccessRepo: BaseRepo {
|
2023-08-16 21:09:40 +00:00
|
|
|
async fn accessed_variant(&self, hash: Hash, variant: String) -> Result<(), RepoError> {
|
|
|
|
self.set_accessed_variant(hash, variant, time::OffsetDateTime::now_utc())
|
|
|
|
.await
|
|
|
|
}
|
2023-07-19 02:56:13 +00:00
|
|
|
|
2023-08-16 21:09:40 +00:00
|
|
|
async fn set_accessed_variant(
|
|
|
|
&self,
|
|
|
|
hash: Hash,
|
|
|
|
variant: String,
|
|
|
|
accessed: time::OffsetDateTime,
|
|
|
|
) -> Result<(), RepoError>;
|
|
|
|
|
|
|
|
async fn variant_accessed_at(
|
|
|
|
&self,
|
|
|
|
hash: Hash,
|
|
|
|
variant: String,
|
|
|
|
) -> Result<Option<time::OffsetDateTime>, RepoError>;
|
2023-07-22 23:50:04 +00:00
|
|
|
|
2023-07-22 22:57:52 +00:00
|
|
|
async fn older_variants(
|
2023-07-19 02:56:13 +00:00
|
|
|
&self,
|
|
|
|
timestamp: time::OffsetDateTime,
|
2023-08-16 00:19:03 +00:00
|
|
|
) -> Result<LocalBoxStream<'static, Result<(Hash, String), RepoError>>, RepoError>;
|
2023-07-19 02:56:13 +00:00
|
|
|
|
2023-08-16 21:09:40 +00:00
|
|
|
async fn remove_variant_access(&self, hash: Hash, variant: String) -> Result<(), RepoError>;
|
2023-07-19 02:56:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[async_trait::async_trait(?Send)]
|
2023-08-16 00:19:03 +00:00
|
|
|
impl<T> VariantAccessRepo for Arc<T>
|
2023-07-19 02:56:13 +00:00
|
|
|
where
|
2023-07-22 22:57:52 +00:00
|
|
|
T: VariantAccessRepo,
|
2023-07-19 02:56:13 +00:00
|
|
|
{
|
2023-08-16 21:09:40 +00:00
|
|
|
async fn set_accessed_variant(
|
|
|
|
&self,
|
|
|
|
hash: Hash,
|
|
|
|
variant: String,
|
|
|
|
accessed: time::OffsetDateTime,
|
|
|
|
) -> Result<(), RepoError> {
|
|
|
|
T::set_accessed_variant(self, hash, variant, accessed).await
|
2023-07-19 02:56:13 +00:00
|
|
|
}
|
|
|
|
|
2023-08-16 21:09:40 +00:00
|
|
|
async fn variant_accessed_at(
|
|
|
|
&self,
|
|
|
|
hash: Hash,
|
|
|
|
variant: String,
|
|
|
|
) -> Result<Option<time::OffsetDateTime>, RepoError> {
|
|
|
|
T::variant_accessed_at(self, hash, variant).await
|
2023-07-22 23:50:04 +00:00
|
|
|
}
|
|
|
|
|
2023-07-22 22:57:52 +00:00
|
|
|
async fn older_variants(
|
2023-07-19 02:56:13 +00:00
|
|
|
&self,
|
|
|
|
timestamp: time::OffsetDateTime,
|
2023-08-16 00:19:03 +00:00
|
|
|
) -> Result<LocalBoxStream<'static, Result<(Hash, String), RepoError>>, RepoError> {
|
2023-07-22 22:57:52 +00:00
|
|
|
T::older_variants(self, timestamp).await
|
2023-07-19 02:56:13 +00:00
|
|
|
}
|
|
|
|
|
2023-08-16 21:09:40 +00:00
|
|
|
async fn remove_variant_access(&self, hash: Hash, variant: String) -> Result<(), RepoError> {
|
|
|
|
T::remove_variant_access(self, hash, variant).await
|
2023-07-19 02:56:13 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-04-01 21:51:12 +00:00
|
|
|
#[async_trait::async_trait(?Send)]
|
|
|
|
pub(crate) trait UploadRepo: BaseRepo {
|
2023-08-16 21:09:40 +00:00
|
|
|
async fn create_upload(&self, upload_id: UploadId) -> Result<(), RepoError>;
|
2022-04-03 01:56:29 +00:00
|
|
|
|
2023-06-20 20:59:08 +00:00
|
|
|
async fn wait(&self, upload_id: UploadId) -> Result<UploadResult, RepoError>;
|
2022-04-01 21:51:12 +00:00
|
|
|
|
2023-06-20 20:59:08 +00:00
|
|
|
async fn claim(&self, upload_id: UploadId) -> Result<(), RepoError>;
|
2022-04-01 21:51:12 +00:00
|
|
|
|
2023-06-20 20:59:08 +00:00
|
|
|
async fn complete(&self, upload_id: UploadId, result: UploadResult) -> Result<(), RepoError>;
|
2022-04-01 21:51:12 +00:00
|
|
|
}
|
|
|
|
|
2022-09-11 00:29:22 +00:00
|
|
|
#[async_trait::async_trait(?Send)]
|
2023-08-16 00:19:03 +00:00
|
|
|
impl<T> UploadRepo for Arc<T>
|
2022-09-11 00:29:22 +00:00
|
|
|
where
|
|
|
|
T: UploadRepo,
|
|
|
|
{
|
2023-08-16 21:09:40 +00:00
|
|
|
async fn create_upload(&self, upload_id: UploadId) -> Result<(), RepoError> {
|
|
|
|
T::create_upload(self, upload_id).await
|
2022-09-11 00:29:22 +00:00
|
|
|
}
|
|
|
|
|
2023-06-20 20:59:08 +00:00
|
|
|
async fn wait(&self, upload_id: UploadId) -> Result<UploadResult, RepoError> {
|
2022-09-11 15:04:37 +00:00
|
|
|
T::wait(self, upload_id).await
|
2022-09-11 00:29:22 +00:00
|
|
|
}
|
|
|
|
|
2023-06-20 20:59:08 +00:00
|
|
|
async fn claim(&self, upload_id: UploadId) -> Result<(), RepoError> {
|
2022-09-11 15:04:37 +00:00
|
|
|
T::claim(self, upload_id).await
|
2022-09-11 00:29:22 +00:00
|
|
|
}
|
|
|
|
|
2023-06-20 20:59:08 +00:00
|
|
|
async fn complete(&self, upload_id: UploadId, result: UploadResult) -> Result<(), RepoError> {
|
2022-09-11 15:04:37 +00:00
|
|
|
T::complete(self, upload_id, result).await
|
2022-09-11 00:29:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-08-13 19:12:38 +00:00
|
|
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
|
|
|
pub(crate) struct JobId(Uuid);
|
|
|
|
|
|
|
|
impl JobId {
|
|
|
|
pub(crate) fn gen() -> Self {
|
2023-08-14 00:47:20 +00:00
|
|
|
Self(Uuid::now_v7())
|
2023-08-13 19:12:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) const fn as_bytes(&self) -> &[u8; 16] {
|
|
|
|
self.0.as_bytes()
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) const fn from_bytes(bytes: [u8; 16]) -> Self {
|
|
|
|
Self(Uuid::from_bytes(bytes))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-03-29 17:51:16 +00:00
|
|
|
#[async_trait::async_trait(?Send)]
|
|
|
|
pub(crate) trait QueueRepo: BaseRepo {
|
2023-08-15 01:00:00 +00:00
|
|
|
async fn push(&self, queue: &'static str, job: Arc<[u8]>) -> Result<JobId, RepoError>;
|
2022-03-24 18:16:41 +00:00
|
|
|
|
2023-08-15 02:17:57 +00:00
|
|
|
async fn pop(
|
|
|
|
&self,
|
|
|
|
queue: &'static str,
|
|
|
|
worker_id: Uuid,
|
|
|
|
) -> Result<(JobId, Arc<[u8]>), RepoError>;
|
2023-08-13 19:12:38 +00:00
|
|
|
|
2023-08-15 02:17:57 +00:00
|
|
|
async fn heartbeat(
|
|
|
|
&self,
|
|
|
|
queue: &'static str,
|
|
|
|
worker_id: Uuid,
|
|
|
|
job_id: JobId,
|
|
|
|
) -> Result<(), RepoError>;
|
2023-08-13 19:12:38 +00:00
|
|
|
|
2023-08-15 02:17:57 +00:00
|
|
|
async fn complete_job(
|
|
|
|
&self,
|
|
|
|
queue: &'static str,
|
|
|
|
worker_id: Uuid,
|
|
|
|
job_id: JobId,
|
|
|
|
) -> Result<(), RepoError>;
|
2022-03-29 17:51:16 +00:00
|
|
|
}
|
|
|
|
|
2022-09-11 00:29:22 +00:00
|
|
|
#[async_trait::async_trait(?Send)]
|
2023-08-16 00:19:03 +00:00
|
|
|
impl<T> QueueRepo for Arc<T>
|
2022-09-11 00:29:22 +00:00
|
|
|
where
|
|
|
|
T: QueueRepo,
|
|
|
|
{
|
2023-08-15 01:00:00 +00:00
|
|
|
async fn push(&self, queue: &'static str, job: Arc<[u8]>) -> Result<JobId, RepoError> {
|
2022-09-11 15:04:37 +00:00
|
|
|
T::push(self, queue, job).await
|
2022-09-11 00:29:22 +00:00
|
|
|
}
|
|
|
|
|
2023-08-15 02:17:57 +00:00
|
|
|
async fn pop(
|
|
|
|
&self,
|
|
|
|
queue: &'static str,
|
|
|
|
worker_id: Uuid,
|
|
|
|
) -> Result<(JobId, Arc<[u8]>), RepoError> {
|
|
|
|
T::pop(self, queue, worker_id).await
|
2022-09-11 00:29:22 +00:00
|
|
|
}
|
2023-08-13 19:12:38 +00:00
|
|
|
|
2023-08-15 02:17:57 +00:00
|
|
|
async fn heartbeat(
|
|
|
|
&self,
|
|
|
|
queue: &'static str,
|
|
|
|
worker_id: Uuid,
|
|
|
|
job_id: JobId,
|
|
|
|
) -> Result<(), RepoError> {
|
|
|
|
T::heartbeat(self, queue, worker_id, job_id).await
|
2023-08-13 19:12:38 +00:00
|
|
|
}
|
|
|
|
|
2023-08-15 02:17:57 +00:00
|
|
|
async fn complete_job(
|
|
|
|
&self,
|
|
|
|
queue: &'static str,
|
|
|
|
worker_id: Uuid,
|
|
|
|
job_id: JobId,
|
|
|
|
) -> Result<(), RepoError> {
|
|
|
|
T::complete_job(self, queue, worker_id, job_id).await
|
2023-08-13 19:12:38 +00:00
|
|
|
}
|
2022-09-11 00:29:22 +00:00
|
|
|
}
|
|
|
|
|
2022-03-29 17:51:16 +00:00
|
|
|
#[async_trait::async_trait(?Send)]
|
|
|
|
pub(crate) trait SettingsRepo: BaseRepo {
|
2023-08-15 01:00:00 +00:00
|
|
|
async fn set(&self, key: &'static str, value: Arc<[u8]>) -> Result<(), RepoError>;
|
|
|
|
async fn get(&self, key: &'static str) -> Result<Option<Arc<[u8]>>, RepoError>;
|
2023-06-20 20:59:08 +00:00
|
|
|
async fn remove(&self, key: &'static str) -> Result<(), RepoError>;
|
2022-03-24 18:16:41 +00:00
|
|
|
}
|
|
|
|
|
2022-09-11 00:29:22 +00:00
|
|
|
#[async_trait::async_trait(?Send)]
|
2023-08-16 00:19:03 +00:00
|
|
|
impl<T> SettingsRepo for Arc<T>
|
2022-09-11 00:29:22 +00:00
|
|
|
where
|
|
|
|
T: SettingsRepo,
|
|
|
|
{
|
2023-08-15 01:00:00 +00:00
|
|
|
async fn set(&self, key: &'static str, value: Arc<[u8]>) -> Result<(), RepoError> {
|
2022-09-11 15:04:37 +00:00
|
|
|
T::set(self, key, value).await
|
2022-09-11 00:29:22 +00:00
|
|
|
}
|
|
|
|
|
2023-08-15 01:00:00 +00:00
|
|
|
async fn get(&self, key: &'static str) -> Result<Option<Arc<[u8]>>, RepoError> {
|
2022-09-11 15:04:37 +00:00
|
|
|
T::get(self, key).await
|
2022-09-11 00:29:22 +00:00
|
|
|
}
|
|
|
|
|
2023-06-20 20:59:08 +00:00
|
|
|
async fn remove(&self, key: &'static str) -> Result<(), RepoError> {
|
2022-09-11 15:04:37 +00:00
|
|
|
T::remove(self, key).await
|
2022-09-11 00:29:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-03-26 21:49:23 +00:00
|
|
|
#[async_trait::async_trait(?Send)]
|
2023-08-16 21:09:40 +00:00
|
|
|
pub(crate) trait DetailsRepo: BaseRepo {
|
2023-08-16 00:19:03 +00:00
|
|
|
async fn relate_details(
|
2022-03-26 21:49:23 +00:00
|
|
|
&self,
|
2023-08-16 00:19:03 +00:00
|
|
|
identifier: &dyn Identifier,
|
2022-03-26 21:49:23 +00:00
|
|
|
details: &Details,
|
2023-06-20 20:59:08 +00:00
|
|
|
) -> Result<(), StoreError>;
|
2023-08-16 00:19:03 +00:00
|
|
|
async fn details(&self, identifier: &dyn Identifier) -> Result<Option<Details>, StoreError>;
|
2022-03-24 18:16:41 +00:00
|
|
|
|
2023-08-16 21:09:40 +00:00
|
|
|
async fn cleanup_details(&self, identifier: &dyn Identifier) -> Result<(), StoreError>;
|
2022-03-24 18:16:41 +00:00
|
|
|
}
|
|
|
|
|
2022-09-11 00:29:22 +00:00
|
|
|
#[async_trait::async_trait(?Send)]
|
2023-08-16 21:09:40 +00:00
|
|
|
impl<T> DetailsRepo for Arc<T>
|
2022-09-11 00:29:22 +00:00
|
|
|
where
|
2023-08-16 21:09:40 +00:00
|
|
|
T: DetailsRepo,
|
2022-09-11 00:29:22 +00:00
|
|
|
{
|
2023-08-16 00:19:03 +00:00
|
|
|
async fn relate_details(
|
2022-09-11 00:29:22 +00:00
|
|
|
&self,
|
2023-08-16 00:19:03 +00:00
|
|
|
identifier: &dyn Identifier,
|
2022-09-11 00:29:22 +00:00
|
|
|
details: &Details,
|
2023-06-20 20:59:08 +00:00
|
|
|
) -> Result<(), StoreError> {
|
2022-09-11 15:04:37 +00:00
|
|
|
T::relate_details(self, identifier, details).await
|
2022-09-11 00:29:22 +00:00
|
|
|
}
|
|
|
|
|
2023-08-16 00:19:03 +00:00
|
|
|
async fn details(&self, identifier: &dyn Identifier) -> Result<Option<Details>, StoreError> {
|
2022-09-11 15:04:37 +00:00
|
|
|
T::details(self, identifier).await
|
2022-09-11 00:29:22 +00:00
|
|
|
}
|
|
|
|
|
2023-08-16 21:09:40 +00:00
|
|
|
async fn cleanup_details(&self, identifier: &dyn Identifier) -> Result<(), StoreError> {
|
|
|
|
T::cleanup_details(self, identifier).await
|
2022-09-11 00:29:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-07-17 03:07:42 +00:00
|
|
|
#[async_trait::async_trait(?Send)]
|
2023-08-16 16:47:36 +00:00
|
|
|
pub(crate) trait StoreMigrationRepo: BaseRepo {
|
2023-07-17 03:07:42 +00:00
|
|
|
async fn is_continuing_migration(&self) -> Result<bool, RepoError>;
|
|
|
|
|
2023-08-16 00:19:03 +00:00
|
|
|
async fn mark_migrated(
|
2023-07-17 03:07:42 +00:00
|
|
|
&self,
|
2023-08-16 00:19:03 +00:00
|
|
|
old_identifier: &dyn Identifier,
|
|
|
|
new_identifier: &dyn Identifier,
|
2023-07-17 03:07:42 +00:00
|
|
|
) -> Result<(), StoreError>;
|
|
|
|
|
2023-08-16 00:19:03 +00:00
|
|
|
async fn is_migrated(&self, identifier: &dyn Identifier) -> Result<bool, StoreError>;
|
2023-07-17 03:07:42 +00:00
|
|
|
|
|
|
|
async fn clear(&self) -> Result<(), RepoError>;
|
|
|
|
}
|
|
|
|
|
|
|
|
#[async_trait::async_trait(?Send)]
|
2023-08-16 16:47:36 +00:00
|
|
|
impl<T> StoreMigrationRepo for Arc<T>
|
2023-07-17 03:07:42 +00:00
|
|
|
where
|
2023-08-16 16:47:36 +00:00
|
|
|
T: StoreMigrationRepo,
|
2023-07-17 03:07:42 +00:00
|
|
|
{
|
|
|
|
async fn is_continuing_migration(&self) -> Result<bool, RepoError> {
|
|
|
|
T::is_continuing_migration(self).await
|
|
|
|
}
|
|
|
|
|
2023-08-16 00:19:03 +00:00
|
|
|
async fn mark_migrated(
|
2023-07-17 03:07:42 +00:00
|
|
|
&self,
|
2023-08-16 00:19:03 +00:00
|
|
|
old_identifier: &dyn Identifier,
|
|
|
|
new_identifier: &dyn Identifier,
|
2023-07-17 03:07:42 +00:00
|
|
|
) -> Result<(), StoreError> {
|
|
|
|
T::mark_migrated(self, old_identifier, new_identifier).await
|
|
|
|
}
|
|
|
|
|
2023-08-16 00:19:03 +00:00
|
|
|
async fn is_migrated(&self, identifier: &dyn Identifier) -> Result<bool, StoreError> {
|
2023-07-17 03:07:42 +00:00
|
|
|
T::is_migrated(self, identifier).await
|
|
|
|
}
|
|
|
|
|
|
|
|
async fn clear(&self) -> Result<(), RepoError> {
|
|
|
|
T::clear(self).await
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-03-26 21:49:23 +00:00
|
|
|
#[async_trait::async_trait(?Send)]
|
2022-03-29 17:51:16 +00:00
|
|
|
pub(crate) trait HashRepo: BaseRepo {
|
2023-06-29 16:39:47 +00:00
|
|
|
async fn size(&self) -> Result<u64, RepoError>;
|
|
|
|
|
2023-08-16 00:19:03 +00:00
|
|
|
async fn hashes(&self) -> LocalBoxStream<'static, Result<Hash, RepoError>>;
|
2022-03-24 18:16:41 +00:00
|
|
|
|
2023-08-16 21:09:40 +00:00
|
|
|
async fn create_hash(
|
2023-07-26 01:08:18 +00:00
|
|
|
&self,
|
2023-08-14 03:06:42 +00:00
|
|
|
hash: Hash,
|
2023-08-16 00:19:03 +00:00
|
|
|
identifier: &dyn Identifier,
|
2023-07-26 01:08:18 +00:00
|
|
|
) -> Result<Result<(), HashAlreadyExists>, StoreError>;
|
2022-03-24 18:16:41 +00:00
|
|
|
|
2023-08-16 00:19:03 +00:00
|
|
|
async fn update_identifier(
|
2022-03-26 21:49:23 +00:00
|
|
|
&self,
|
2023-08-14 03:06:42 +00:00
|
|
|
hash: Hash,
|
2023-08-16 00:19:03 +00:00
|
|
|
identifier: &dyn Identifier,
|
2023-06-20 20:59:08 +00:00
|
|
|
) -> Result<(), StoreError>;
|
2023-07-26 01:08:18 +00:00
|
|
|
|
2023-08-16 00:19:03 +00:00
|
|
|
async fn identifier(&self, hash: Hash) -> Result<Option<Arc<[u8]>>, RepoError>;
|
2022-03-24 18:16:41 +00:00
|
|
|
|
2023-08-16 00:19:03 +00:00
|
|
|
async fn relate_variant_identifier(
|
2022-03-25 23:47:50 +00:00
|
|
|
&self,
|
2023-08-14 03:06:42 +00:00
|
|
|
hash: Hash,
|
2022-03-25 23:47:50 +00:00
|
|
|
variant: String,
|
2023-08-16 00:19:03 +00:00
|
|
|
identifier: &dyn Identifier,
|
2023-08-16 20:12:16 +00:00
|
|
|
) -> Result<Result<(), VariantAlreadyExists>, StoreError>;
|
2023-08-16 00:19:03 +00:00
|
|
|
async fn variant_identifier(
|
2022-03-25 23:47:50 +00:00
|
|
|
&self,
|
2023-08-14 03:06:42 +00:00
|
|
|
hash: Hash,
|
2022-03-25 23:47:50 +00:00
|
|
|
variant: String,
|
2023-08-16 00:19:03 +00:00
|
|
|
) -> Result<Option<Arc<[u8]>>, RepoError>;
|
|
|
|
async fn variants(&self, hash: Hash) -> Result<Vec<(String, Arc<[u8]>)>, RepoError>;
|
2023-08-14 03:06:42 +00:00
|
|
|
async fn remove_variant(&self, hash: Hash, variant: String) -> Result<(), RepoError>;
|
2022-03-25 23:47:50 +00:00
|
|
|
|
2023-08-16 00:19:03 +00:00
|
|
|
async fn relate_motion_identifier(
|
2022-03-25 23:47:50 +00:00
|
|
|
&self,
|
2023-08-14 03:06:42 +00:00
|
|
|
hash: Hash,
|
2023-08-16 00:19:03 +00:00
|
|
|
identifier: &dyn Identifier,
|
2023-06-20 20:59:08 +00:00
|
|
|
) -> Result<(), StoreError>;
|
2023-08-16 00:19:03 +00:00
|
|
|
async fn motion_identifier(&self, hash: Hash) -> Result<Option<Arc<[u8]>>, RepoError>;
|
2022-03-25 23:47:50 +00:00
|
|
|
|
2023-08-16 21:09:40 +00:00
|
|
|
async fn cleanup_hash(&self, hash: Hash) -> Result<(), RepoError>;
|
2022-03-24 18:16:41 +00:00
|
|
|
}
|
|
|
|
|
2022-09-11 00:29:22 +00:00
|
|
|
#[async_trait::async_trait(?Send)]
|
2023-08-16 00:19:03 +00:00
|
|
|
impl<T> HashRepo for Arc<T>
|
2022-09-11 00:29:22 +00:00
|
|
|
where
|
|
|
|
T: HashRepo,
|
|
|
|
{
|
2023-06-29 16:39:47 +00:00
|
|
|
async fn size(&self) -> Result<u64, RepoError> {
|
|
|
|
T::size(self).await
|
|
|
|
}
|
|
|
|
|
2023-08-16 00:19:03 +00:00
|
|
|
async fn hashes(&self) -> LocalBoxStream<'static, Result<Hash, RepoError>> {
|
2022-09-11 15:04:37 +00:00
|
|
|
T::hashes(self).await
|
2022-09-11 00:29:22 +00:00
|
|
|
}
|
|
|
|
|
2023-08-16 21:09:40 +00:00
|
|
|
async fn create_hash(
|
2023-07-26 01:08:18 +00:00
|
|
|
&self,
|
2023-08-14 03:06:42 +00:00
|
|
|
hash: Hash,
|
2023-08-16 00:19:03 +00:00
|
|
|
identifier: &dyn Identifier,
|
2023-07-26 01:08:18 +00:00
|
|
|
) -> Result<Result<(), HashAlreadyExists>, StoreError> {
|
2023-08-16 21:09:40 +00:00
|
|
|
T::create_hash(self, hash, identifier).await
|
2022-09-11 00:29:22 +00:00
|
|
|
}
|
|
|
|
|
2023-08-16 00:19:03 +00:00
|
|
|
async fn update_identifier(
|
2022-09-11 00:29:22 +00:00
|
|
|
&self,
|
2023-08-14 03:06:42 +00:00
|
|
|
hash: Hash,
|
2023-08-16 00:19:03 +00:00
|
|
|
identifier: &dyn Identifier,
|
2023-06-20 20:59:08 +00:00
|
|
|
) -> Result<(), StoreError> {
|
2023-07-26 01:08:18 +00:00
|
|
|
T::update_identifier(self, hash, identifier).await
|
2022-09-11 00:29:22 +00:00
|
|
|
}
|
|
|
|
|
2023-08-16 00:19:03 +00:00
|
|
|
async fn identifier(&self, hash: Hash) -> Result<Option<Arc<[u8]>>, RepoError> {
|
2022-09-11 15:04:37 +00:00
|
|
|
T::identifier(self, hash).await
|
2022-09-11 00:29:22 +00:00
|
|
|
}
|
|
|
|
|
2023-08-16 00:19:03 +00:00
|
|
|
async fn relate_variant_identifier(
|
2022-09-11 00:29:22 +00:00
|
|
|
&self,
|
2023-08-14 03:06:42 +00:00
|
|
|
hash: Hash,
|
2022-09-11 00:29:22 +00:00
|
|
|
variant: String,
|
2023-08-16 00:19:03 +00:00
|
|
|
identifier: &dyn Identifier,
|
2023-08-16 20:12:16 +00:00
|
|
|
) -> Result<Result<(), VariantAlreadyExists>, StoreError> {
|
2022-09-11 15:04:37 +00:00
|
|
|
T::relate_variant_identifier(self, hash, variant, identifier).await
|
2022-09-11 00:29:22 +00:00
|
|
|
}
|
|
|
|
|
2023-08-16 00:19:03 +00:00
|
|
|
async fn variant_identifier(
|
2022-09-11 00:29:22 +00:00
|
|
|
&self,
|
2023-08-14 03:06:42 +00:00
|
|
|
hash: Hash,
|
2022-09-11 00:29:22 +00:00
|
|
|
variant: String,
|
2023-08-16 00:19:03 +00:00
|
|
|
) -> Result<Option<Arc<[u8]>>, RepoError> {
|
2022-09-11 15:04:37 +00:00
|
|
|
T::variant_identifier(self, hash, variant).await
|
2022-09-11 00:29:22 +00:00
|
|
|
}
|
|
|
|
|
2023-08-16 00:19:03 +00:00
|
|
|
async fn variants(&self, hash: Hash) -> Result<Vec<(String, Arc<[u8]>)>, RepoError> {
|
2022-09-11 15:04:37 +00:00
|
|
|
T::variants(self, hash).await
|
2022-09-11 00:29:22 +00:00
|
|
|
}
|
|
|
|
|
2023-08-14 03:06:42 +00:00
|
|
|
async fn remove_variant(&self, hash: Hash, variant: String) -> Result<(), RepoError> {
|
2022-09-11 15:04:37 +00:00
|
|
|
T::remove_variant(self, hash, variant).await
|
2022-09-11 00:29:22 +00:00
|
|
|
}
|
|
|
|
|
2023-08-16 00:19:03 +00:00
|
|
|
async fn relate_motion_identifier(
|
2022-09-11 00:29:22 +00:00
|
|
|
&self,
|
2023-08-14 03:06:42 +00:00
|
|
|
hash: Hash,
|
2023-08-16 00:19:03 +00:00
|
|
|
identifier: &dyn Identifier,
|
2023-06-20 20:59:08 +00:00
|
|
|
) -> Result<(), StoreError> {
|
2022-09-11 15:04:37 +00:00
|
|
|
T::relate_motion_identifier(self, hash, identifier).await
|
2022-09-11 00:29:22 +00:00
|
|
|
}
|
|
|
|
|
2023-08-16 00:19:03 +00:00
|
|
|
async fn motion_identifier(&self, hash: Hash) -> Result<Option<Arc<[u8]>>, RepoError> {
|
2022-09-11 15:04:37 +00:00
|
|
|
T::motion_identifier(self, hash).await
|
2022-09-11 00:29:22 +00:00
|
|
|
}
|
|
|
|
|
2023-08-16 21:09:40 +00:00
|
|
|
async fn cleanup_hash(&self, hash: Hash) -> Result<(), RepoError> {
|
|
|
|
T::cleanup_hash(self, hash).await
|
2022-09-11 00:29:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-03-26 21:49:23 +00:00
|
|
|
#[async_trait::async_trait(?Send)]
|
2022-03-29 17:51:16 +00:00
|
|
|
pub(crate) trait AliasRepo: BaseRepo {
|
2023-08-16 21:09:40 +00:00
|
|
|
async fn create_alias(
|
2022-03-24 18:16:41 +00:00
|
|
|
&self,
|
2022-03-26 21:49:23 +00:00
|
|
|
alias: &Alias,
|
|
|
|
delete_token: &DeleteToken,
|
2023-08-14 03:06:42 +00:00
|
|
|
hash: Hash,
|
2023-07-26 01:08:18 +00:00
|
|
|
) -> Result<Result<(), AliasAlreadyExists>, RepoError>;
|
|
|
|
|
2023-07-07 18:17:26 +00:00
|
|
|
async fn delete_token(&self, alias: &Alias) -> Result<Option<DeleteToken>, RepoError>;
|
2022-03-24 18:16:41 +00:00
|
|
|
|
2023-08-14 03:06:42 +00:00
|
|
|
async fn hash(&self, alias: &Alias) -> Result<Option<Hash>, RepoError>;
|
2022-03-24 18:16:41 +00:00
|
|
|
|
2023-08-14 03:06:42 +00:00
|
|
|
async fn for_hash(&self, hash: Hash) -> Result<Vec<Alias>, RepoError>;
|
2023-07-26 01:08:18 +00:00
|
|
|
|
2023-08-16 21:09:40 +00:00
|
|
|
async fn cleanup_alias(&self, alias: &Alias) -> Result<(), RepoError>;
|
2022-03-24 18:16:41 +00:00
|
|
|
}
|
2022-03-25 23:47:50 +00:00
|
|
|
|
2022-09-11 00:29:22 +00:00
|
|
|
#[async_trait::async_trait(?Send)]
|
2023-08-16 00:19:03 +00:00
|
|
|
impl<T> AliasRepo for Arc<T>
|
2022-09-11 00:29:22 +00:00
|
|
|
where
|
|
|
|
T: AliasRepo,
|
|
|
|
{
|
2023-08-16 21:09:40 +00:00
|
|
|
async fn create_alias(
|
2022-09-11 00:29:22 +00:00
|
|
|
&self,
|
|
|
|
alias: &Alias,
|
|
|
|
delete_token: &DeleteToken,
|
2023-08-14 03:06:42 +00:00
|
|
|
hash: Hash,
|
2023-07-26 01:08:18 +00:00
|
|
|
) -> Result<Result<(), AliasAlreadyExists>, RepoError> {
|
2023-08-16 21:09:40 +00:00
|
|
|
T::create_alias(self, alias, delete_token, hash).await
|
2022-09-11 00:29:22 +00:00
|
|
|
}
|
|
|
|
|
2023-07-07 18:17:26 +00:00
|
|
|
async fn delete_token(&self, alias: &Alias) -> Result<Option<DeleteToken>, RepoError> {
|
2022-09-11 15:04:37 +00:00
|
|
|
T::delete_token(self, alias).await
|
2022-09-11 00:29:22 +00:00
|
|
|
}
|
|
|
|
|
2023-08-14 03:06:42 +00:00
|
|
|
async fn hash(&self, alias: &Alias) -> Result<Option<Hash>, RepoError> {
|
2022-09-11 15:04:37 +00:00
|
|
|
T::hash(self, alias).await
|
2022-09-11 00:29:22 +00:00
|
|
|
}
|
|
|
|
|
2023-08-14 03:06:42 +00:00
|
|
|
async fn for_hash(&self, hash: Hash) -> Result<Vec<Alias>, RepoError> {
|
2023-07-26 01:08:18 +00:00
|
|
|
T::for_hash(self, hash).await
|
|
|
|
}
|
|
|
|
|
2023-08-16 21:09:40 +00:00
|
|
|
async fn cleanup_alias(&self, alias: &Alias) -> Result<(), RepoError> {
|
|
|
|
T::cleanup_alias(self, alias).await
|
2022-09-11 00:29:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-03-25 23:47:50 +00:00
|
|
|
impl Repo {
|
2023-07-08 15:42:03 +00:00
|
|
|
#[tracing::instrument]
|
2022-03-29 01:47:46 +00:00
|
|
|
pub(crate) fn open(config: config::Repo) -> color_eyre::Result<Self> {
|
2022-03-25 23:47:50 +00:00
|
|
|
match config {
|
2022-03-28 04:27:07 +00:00
|
|
|
config::Repo::Sled(config::Sled {
|
2023-07-08 22:35:57 +00:00
|
|
|
path,
|
2022-03-25 23:47:50 +00:00
|
|
|
cache_capacity,
|
2023-07-08 22:35:57 +00:00
|
|
|
export_path,
|
2022-03-25 23:47:50 +00:00
|
|
|
}) => {
|
2023-07-08 22:35:57 +00:00
|
|
|
let repo = self::sled::SledRepo::build(path, cache_capacity, export_path)?;
|
2022-03-25 23:47:50 +00:00
|
|
|
|
2023-07-08 22:35:57 +00:00
|
|
|
Ok(Self::Sled(repo))
|
2022-03-25 23:47:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-08-16 00:19:03 +00:00
|
|
|
|
|
|
|
pub(crate) fn to_arc(&self) -> ArcRepo {
|
|
|
|
match self {
|
|
|
|
Self::Sled(sled_repo) => Arc::new(sled_repo.clone()),
|
|
|
|
}
|
|
|
|
}
|
2022-03-25 23:47:50 +00:00
|
|
|
}
|
|
|
|
|
2022-03-26 21:49:23 +00:00
|
|
|
impl MaybeUuid {
|
|
|
|
fn from_str(s: &str) -> Self {
|
|
|
|
if let Ok(uuid) = Uuid::parse_str(s) {
|
|
|
|
MaybeUuid::Uuid(uuid)
|
|
|
|
} else {
|
|
|
|
MaybeUuid::Name(s.into())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn as_bytes(&self) -> &[u8] {
|
|
|
|
match self {
|
|
|
|
Self::Uuid(uuid) => &uuid.as_bytes()[..],
|
|
|
|
Self::Name(name) => name.as_bytes(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn split_at_dot(s: &str) -> Option<(&str, &str)> {
|
|
|
|
let index = s.find('.')?;
|
|
|
|
|
|
|
|
Some(s.split_at(index))
|
|
|
|
}
|
|
|
|
|
2022-03-25 23:47:50 +00:00
|
|
|
impl Alias {
|
2022-03-26 21:49:23 +00:00
|
|
|
pub(crate) fn generate(extension: String) -> Self {
|
|
|
|
Alias {
|
|
|
|
id: MaybeUuid::Uuid(Uuid::new_v4()),
|
|
|
|
extension: Some(extension),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) fn from_existing(alias: &str) -> Self {
|
|
|
|
if let Some((start, end)) = split_at_dot(alias) {
|
|
|
|
Alias {
|
|
|
|
id: MaybeUuid::from_str(start),
|
|
|
|
extension: Some(end.into()),
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
Alias {
|
|
|
|
id: MaybeUuid::from_str(alias),
|
|
|
|
extension: None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) fn extension(&self) -> Option<&str> {
|
|
|
|
self.extension.as_deref()
|
|
|
|
}
|
|
|
|
|
2023-07-07 18:33:27 +00:00
|
|
|
pub(crate) fn to_bytes(&self) -> Vec<u8> {
|
2022-03-25 23:47:50 +00:00
|
|
|
let mut v = self.id.as_bytes().to_vec();
|
|
|
|
|
2022-03-26 21:49:23 +00:00
|
|
|
if let Some(ext) = self.extension() {
|
|
|
|
v.extend_from_slice(ext.as_bytes());
|
|
|
|
}
|
2022-03-25 23:47:50 +00:00
|
|
|
|
|
|
|
v
|
|
|
|
}
|
|
|
|
|
2023-07-07 18:33:27 +00:00
|
|
|
pub(crate) fn from_slice(bytes: &[u8]) -> Option<Self> {
|
2022-03-26 21:49:23 +00:00
|
|
|
if let Ok(s) = std::str::from_utf8(bytes) {
|
|
|
|
Some(Self::from_existing(s))
|
|
|
|
} else if bytes.len() >= 16 {
|
2022-03-25 23:47:50 +00:00
|
|
|
let id = Uuid::from_slice(&bytes[0..16]).expect("Already checked length");
|
|
|
|
|
2022-03-26 21:49:23 +00:00
|
|
|
let extension = if bytes.len() > 16 {
|
|
|
|
Some(String::from_utf8_lossy(&bytes[16..]).to_string())
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
};
|
|
|
|
|
|
|
|
Some(Self {
|
|
|
|
id: MaybeUuid::Uuid(id),
|
|
|
|
extension,
|
|
|
|
})
|
2022-03-25 23:47:50 +00:00
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl DeleteToken {
|
2022-03-26 21:49:23 +00:00
|
|
|
pub(crate) fn from_existing(existing: &str) -> Self {
|
|
|
|
if let Ok(uuid) = Uuid::parse_str(existing) {
|
|
|
|
DeleteToken {
|
|
|
|
id: MaybeUuid::Uuid(uuid),
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
DeleteToken {
|
|
|
|
id: MaybeUuid::Name(existing.into()),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) fn generate() -> Self {
|
|
|
|
Self {
|
|
|
|
id: MaybeUuid::Uuid(Uuid::new_v4()),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-08-16 00:19:03 +00:00
|
|
|
pub(crate) fn to_bytes(&self) -> Vec<u8> {
|
2022-03-25 23:47:50 +00:00
|
|
|
self.id.as_bytes().to_vec()
|
|
|
|
}
|
|
|
|
|
2023-08-16 00:19:03 +00:00
|
|
|
pub(crate) fn from_slice(bytes: &[u8]) -> Option<Self> {
|
2022-03-26 21:49:23 +00:00
|
|
|
if let Ok(s) = std::str::from_utf8(bytes) {
|
|
|
|
Some(DeleteToken::from_existing(s))
|
|
|
|
} else if bytes.len() == 16 {
|
|
|
|
Some(DeleteToken {
|
|
|
|
id: MaybeUuid::Uuid(Uuid::from_slice(bytes).ok()?),
|
|
|
|
})
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-04-01 21:51:12 +00:00
|
|
|
impl UploadId {
|
|
|
|
pub(crate) fn generate() -> Self {
|
|
|
|
Self { id: Uuid::new_v4() }
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) fn as_bytes(&self) -> &[u8] {
|
|
|
|
&self.id.as_bytes()[..]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-04-03 01:56:29 +00:00
|
|
|
impl std::str::FromStr for UploadId {
|
|
|
|
type Err = <Uuid as std::str::FromStr>::Err;
|
|
|
|
|
|
|
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
|
|
Ok(UploadId { id: s.parse()? })
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl std::fmt::Display for UploadId {
|
|
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
|
|
std::fmt::Display::fmt(&self.id, f)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-03-26 21:49:23 +00:00
|
|
|
impl std::fmt::Display for MaybeUuid {
|
|
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
|
|
match self {
|
2023-01-29 17:57:59 +00:00
|
|
|
Self::Uuid(id) => write!(f, "{id}"),
|
|
|
|
Self::Name(name) => write!(f, "{name}"),
|
2022-03-26 21:49:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-04-02 21:44:03 +00:00
|
|
|
impl std::str::FromStr for DeleteToken {
|
|
|
|
type Err = std::convert::Infallible;
|
|
|
|
|
|
|
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
|
|
Ok(DeleteToken::from_existing(s))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-03-26 21:49:23 +00:00
|
|
|
impl std::fmt::Display for DeleteToken {
|
|
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
|
|
write!(f, "{}", self.id)
|
2022-03-25 23:47:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-04-01 21:51:12 +00:00
|
|
|
impl std::str::FromStr for Alias {
|
|
|
|
type Err = std::convert::Infallible;
|
|
|
|
|
|
|
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
|
|
Ok(Alias::from_existing(s))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-03-25 23:47:50 +00:00
|
|
|
impl std::fmt::Display for Alias {
|
|
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
2022-03-26 21:49:23 +00:00
|
|
|
if let Some(ext) = self.extension() {
|
2023-01-29 17:57:59 +00:00
|
|
|
write!(f, "{}{ext}", self.id)
|
2022-03-26 21:49:23 +00:00
|
|
|
} else {
|
|
|
|
write!(f, "{}", self.id)
|
|
|
|
}
|
2022-03-25 23:47:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-03-26 21:49:23 +00:00
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
use super::{Alias, DeleteToken, MaybeUuid, Uuid};
|
2022-03-25 23:47:50 +00:00
|
|
|
|
2022-03-26 21:49:23 +00:00
|
|
|
#[test]
|
|
|
|
fn string_delete_token() {
|
|
|
|
let delete_token = DeleteToken::from_existing("blah");
|
|
|
|
|
|
|
|
assert_eq!(
|
|
|
|
delete_token,
|
|
|
|
DeleteToken {
|
|
|
|
id: MaybeUuid::Name(String::from("blah"))
|
|
|
|
}
|
|
|
|
)
|
2022-03-25 23:47:50 +00:00
|
|
|
}
|
|
|
|
|
2022-03-26 21:49:23 +00:00
|
|
|
#[test]
|
|
|
|
fn uuid_string_delete_token() {
|
|
|
|
let uuid = Uuid::new_v4();
|
|
|
|
|
|
|
|
let delete_token = DeleteToken::from_existing(&uuid.to_string());
|
|
|
|
|
|
|
|
assert_eq!(
|
|
|
|
delete_token,
|
|
|
|
DeleteToken {
|
|
|
|
id: MaybeUuid::Uuid(uuid),
|
|
|
|
}
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn bytes_delete_token() {
|
|
|
|
let delete_token = DeleteToken::from_slice(b"blah").unwrap();
|
|
|
|
|
|
|
|
assert_eq!(
|
|
|
|
delete_token,
|
|
|
|
DeleteToken {
|
|
|
|
id: MaybeUuid::Name(String::from("blah"))
|
|
|
|
}
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn uuid_bytes_delete_token() {
|
|
|
|
let uuid = Uuid::new_v4();
|
|
|
|
|
|
|
|
let delete_token = DeleteToken::from_slice(&uuid.as_bytes()[..]).unwrap();
|
|
|
|
|
|
|
|
assert_eq!(
|
|
|
|
delete_token,
|
|
|
|
DeleteToken {
|
|
|
|
id: MaybeUuid::Uuid(uuid),
|
|
|
|
}
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn uuid_bytes_string_delete_token() {
|
|
|
|
let uuid = Uuid::new_v4();
|
|
|
|
|
|
|
|
let delete_token = DeleteToken::from_slice(uuid.to_string().as_bytes()).unwrap();
|
|
|
|
|
|
|
|
assert_eq!(
|
|
|
|
delete_token,
|
|
|
|
DeleteToken {
|
|
|
|
id: MaybeUuid::Uuid(uuid),
|
|
|
|
}
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn string_alias() {
|
|
|
|
let alias = Alias::from_existing("blah");
|
|
|
|
|
|
|
|
assert_eq!(
|
|
|
|
alias,
|
|
|
|
Alias {
|
|
|
|
id: MaybeUuid::Name(String::from("blah")),
|
|
|
|
extension: None
|
|
|
|
}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn string_alias_ext() {
|
|
|
|
let alias = Alias::from_existing("blah.mp4");
|
|
|
|
|
|
|
|
assert_eq!(
|
|
|
|
alias,
|
|
|
|
Alias {
|
|
|
|
id: MaybeUuid::Name(String::from("blah")),
|
|
|
|
extension: Some(String::from(".mp4")),
|
|
|
|
}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn uuid_string_alias() {
|
|
|
|
let uuid = Uuid::new_v4();
|
|
|
|
|
|
|
|
let alias = Alias::from_existing(&uuid.to_string());
|
|
|
|
|
|
|
|
assert_eq!(
|
|
|
|
alias,
|
|
|
|
Alias {
|
|
|
|
id: MaybeUuid::Uuid(uuid),
|
|
|
|
extension: None,
|
|
|
|
}
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn uuid_string_alias_ext() {
|
|
|
|
let uuid = Uuid::new_v4();
|
|
|
|
|
2023-01-29 17:57:59 +00:00
|
|
|
let alias_str = format!("{uuid}.mp4");
|
2022-03-26 21:49:23 +00:00
|
|
|
let alias = Alias::from_existing(&alias_str);
|
|
|
|
|
|
|
|
assert_eq!(
|
|
|
|
alias,
|
|
|
|
Alias {
|
|
|
|
id: MaybeUuid::Uuid(uuid),
|
|
|
|
extension: Some(String::from(".mp4")),
|
|
|
|
}
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn bytes_alias() {
|
|
|
|
let alias = Alias::from_slice(b"blah").unwrap();
|
|
|
|
|
|
|
|
assert_eq!(
|
|
|
|
alias,
|
|
|
|
Alias {
|
|
|
|
id: MaybeUuid::Name(String::from("blah")),
|
|
|
|
extension: None
|
|
|
|
}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn bytes_alias_ext() {
|
|
|
|
let alias = Alias::from_slice(b"blah.mp4").unwrap();
|
|
|
|
|
|
|
|
assert_eq!(
|
|
|
|
alias,
|
|
|
|
Alias {
|
|
|
|
id: MaybeUuid::Name(String::from("blah")),
|
|
|
|
extension: Some(String::from(".mp4")),
|
|
|
|
}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn uuid_bytes_alias() {
|
|
|
|
let uuid = Uuid::new_v4();
|
|
|
|
|
|
|
|
let alias = Alias::from_slice(&uuid.as_bytes()[..]).unwrap();
|
|
|
|
|
|
|
|
assert_eq!(
|
|
|
|
alias,
|
|
|
|
Alias {
|
|
|
|
id: MaybeUuid::Uuid(uuid),
|
|
|
|
extension: None,
|
|
|
|
}
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn uuid_bytes_string_alias() {
|
|
|
|
let uuid = Uuid::new_v4();
|
|
|
|
|
|
|
|
let alias = Alias::from_slice(uuid.to_string().as_bytes()).unwrap();
|
|
|
|
|
|
|
|
assert_eq!(
|
|
|
|
alias,
|
|
|
|
Alias {
|
|
|
|
id: MaybeUuid::Uuid(uuid),
|
|
|
|
extension: None,
|
|
|
|
}
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn uuid_bytes_alias_ext() {
|
|
|
|
let uuid = Uuid::new_v4();
|
|
|
|
|
|
|
|
let mut alias_bytes = uuid.as_bytes().to_vec();
|
|
|
|
alias_bytes.extend_from_slice(b".mp4");
|
|
|
|
|
|
|
|
let alias = Alias::from_slice(&alias_bytes).unwrap();
|
|
|
|
|
|
|
|
assert_eq!(
|
|
|
|
alias,
|
|
|
|
Alias {
|
|
|
|
id: MaybeUuid::Uuid(uuid),
|
|
|
|
extension: Some(String::from(".mp4")),
|
|
|
|
}
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn uuid_bytes_string_alias_ext() {
|
|
|
|
let uuid = Uuid::new_v4();
|
|
|
|
|
2023-01-29 17:57:59 +00:00
|
|
|
let alias_str = format!("{uuid}.mp4");
|
2022-03-26 21:49:23 +00:00
|
|
|
let alias = Alias::from_slice(alias_str.as_bytes()).unwrap();
|
|
|
|
|
|
|
|
assert_eq!(
|
|
|
|
alias,
|
|
|
|
Alias {
|
|
|
|
id: MaybeUuid::Uuid(uuid),
|
|
|
|
extension: Some(String::from(".mp4")),
|
|
|
|
}
|
|
|
|
)
|
2022-03-25 23:47:50 +00:00
|
|
|
}
|
|
|
|
}
|