mirror of
https://git.asonix.dog/asonix/pict-rs
synced 2024-12-22 19:31:35 +00:00
Queue generation jobs
This commit is contained in:
parent
cd6fb84cc4
commit
960f6487b7
5 changed files with 108 additions and 31 deletions
|
@ -6,7 +6,7 @@ use crate::{
|
||||||
error::{Error, UploadError},
|
error::{Error, UploadError},
|
||||||
formats::{ImageFormat, InputProcessableFormat, InternalVideoFormat, ProcessableFormat},
|
formats::{ImageFormat, InputProcessableFormat, InternalVideoFormat, ProcessableFormat},
|
||||||
future::{WithMetrics, WithPollTimer, WithTimeout},
|
future::{WithMetrics, WithPollTimer, WithTimeout},
|
||||||
repo::{Hash, VariantAlreadyExists},
|
repo::{Hash, NotificationEntry, VariantAlreadyExists},
|
||||||
state::State,
|
state::State,
|
||||||
store::Store,
|
store::Store,
|
||||||
};
|
};
|
||||||
|
@ -102,22 +102,17 @@ pub(crate) async fn generate<S: Store + 'static>(
|
||||||
|
|
||||||
break res???;
|
break res???;
|
||||||
}
|
}
|
||||||
Err(mut entry) => {
|
Err(entry) => {
|
||||||
let notified = entry.notified_timeout(Duration::from_secs(20));
|
if let Some(tuple) = wait_timeout(
|
||||||
|
hash.clone(),
|
||||||
if let Some(identifier) = state
|
variant.clone(),
|
||||||
.repo
|
entry,
|
||||||
.variant_identifier(hash.clone(), variant.clone())
|
state,
|
||||||
|
Duration::from_secs(20),
|
||||||
|
)
|
||||||
.await?
|
.await?
|
||||||
{
|
{
|
||||||
let details = crate::ensure_details_identifier(state, &identifier).await?;
|
break tuple;
|
||||||
|
|
||||||
break (details, identifier);
|
|
||||||
}
|
|
||||||
|
|
||||||
match notified.await {
|
|
||||||
Ok(()) => tracing::debug!("notified"),
|
|
||||||
Err(_) => tracing::debug!("timeout"),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
attempts += 1;
|
attempts += 1;
|
||||||
|
@ -129,6 +124,33 @@ pub(crate) async fn generate<S: Store + 'static>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) async fn wait_timeout<S: Store + 'static>(
|
||||||
|
hash: Hash,
|
||||||
|
variant: String,
|
||||||
|
mut entry: NotificationEntry,
|
||||||
|
state: &State<S>,
|
||||||
|
timeout: Duration,
|
||||||
|
) -> Result<Option<(Details, Arc<str>)>, Error> {
|
||||||
|
let notified = entry.notified_timeout(timeout);
|
||||||
|
|
||||||
|
if let Some(identifier) = state
|
||||||
|
.repo
|
||||||
|
.variant_identifier(hash.clone(), variant.clone())
|
||||||
|
.await?
|
||||||
|
{
|
||||||
|
let details = crate::ensure_details_identifier(state, &identifier).await?;
|
||||||
|
|
||||||
|
return Ok(Some((details, identifier)));
|
||||||
|
}
|
||||||
|
|
||||||
|
match notified.await {
|
||||||
|
Ok(()) => tracing::debug!("notified"),
|
||||||
|
Err(_) => tracing::debug!("timeout"),
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
|
||||||
async fn heartbeat<S, O>(
|
async fn heartbeat<S, O>(
|
||||||
state: &State<S>,
|
state: &State<S>,
|
||||||
hash: Hash,
|
hash: Hash,
|
||||||
|
|
39
src/lib.rs
39
src/lib.rs
|
@ -885,17 +885,34 @@ async fn process<S: Store + 'static>(
|
||||||
return Err(UploadError::ReadOnly.into());
|
return Err(UploadError::ReadOnly.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
let original_details = ensure_details(&state, &alias).await?;
|
queue_generate(&state.repo, format, alias, variant.clone(), variant_args).await?;
|
||||||
|
|
||||||
generate::generate(
|
let mut attempts = 0;
|
||||||
|
loop {
|
||||||
|
if attempts > 6 {
|
||||||
|
return Err(UploadError::ProcessTimeout.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
let entry = state
|
||||||
|
.repo
|
||||||
|
.variant_waiter(hash.clone(), variant.clone())
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
let opt = generate::wait_timeout(
|
||||||
|
hash.clone(),
|
||||||
|
variant.clone(),
|
||||||
|
entry,
|
||||||
&state,
|
&state,
|
||||||
format,
|
Duration::from_secs(5),
|
||||||
variant,
|
|
||||||
variant_args,
|
|
||||||
&original_details,
|
|
||||||
hash,
|
|
||||||
)
|
)
|
||||||
.await?
|
.await?;
|
||||||
|
|
||||||
|
if let Some(tuple) = opt {
|
||||||
|
break tuple;
|
||||||
|
}
|
||||||
|
|
||||||
|
attempts += 1;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(public_url) = state.store.public_url(&identifier) {
|
if let Some(public_url) = state.store.public_url(&identifier) {
|
||||||
|
@ -959,7 +976,7 @@ async fn process_head<S: Store + 'static>(
|
||||||
|
|
||||||
/// Process files
|
/// Process files
|
||||||
#[tracing::instrument(name = "Spawning image process", skip(state))]
|
#[tracing::instrument(name = "Spawning image process", skip(state))]
|
||||||
async fn process_backgrounded<S: Store>(
|
async fn process_backgrounded<S: Store + 'static>(
|
||||||
web::Query(ProcessQuery { source, operations }): web::Query<ProcessQuery>,
|
web::Query(ProcessQuery { source, operations }): web::Query<ProcessQuery>,
|
||||||
ext: web::Path<String>,
|
ext: web::Path<String>,
|
||||||
state: web::Data<State<S>>,
|
state: web::Data<State<S>>,
|
||||||
|
@ -976,7 +993,7 @@ async fn process_backgrounded<S: Store>(
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let (target_format, variant, process_args) =
|
let (target_format, variant, variant_args) =
|
||||||
prepare_process(&state.config, operations, ext.as_str())?;
|
prepare_process(&state.config, operations, ext.as_str())?;
|
||||||
|
|
||||||
let Some(hash) = state.repo.hash(&source).await? else {
|
let Some(hash) = state.repo.hash(&source).await? else {
|
||||||
|
@ -997,7 +1014,7 @@ async fn process_backgrounded<S: Store>(
|
||||||
return Err(UploadError::ReadOnly.into());
|
return Err(UploadError::ReadOnly.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
queue_generate(&state.repo, target_format, source, variant, process_args).await?;
|
queue_generate(&state.repo, target_format, source, variant, variant_args).await?;
|
||||||
|
|
||||||
Ok(HttpResponse::Accepted().finish())
|
Ok(HttpResponse::Accepted().finish())
|
||||||
}
|
}
|
||||||
|
|
17
src/repo.rs
17
src/repo.rs
|
@ -24,8 +24,7 @@ pub(crate) use alias::Alias;
|
||||||
pub(crate) use delete_token::DeleteToken;
|
pub(crate) use delete_token::DeleteToken;
|
||||||
pub(crate) use hash::Hash;
|
pub(crate) use hash::Hash;
|
||||||
pub(crate) use migrate::{migrate_04, migrate_repo};
|
pub(crate) use migrate::{migrate_04, migrate_repo};
|
||||||
|
pub(crate) use notification_map::NotificationEntry;
|
||||||
use self::notification_map::NotificationEntry;
|
|
||||||
|
|
||||||
pub(crate) type ArcRepo = Arc<dyn FullRepo>;
|
pub(crate) type ArcRepo = Arc<dyn FullRepo>;
|
||||||
|
|
||||||
|
@ -749,6 +748,12 @@ pub(crate) trait VariantRepo: BaseRepo {
|
||||||
variant: String,
|
variant: String,
|
||||||
) -> Result<Result<(), NotificationEntry>, RepoError>;
|
) -> Result<Result<(), NotificationEntry>, RepoError>;
|
||||||
|
|
||||||
|
async fn variant_waiter(
|
||||||
|
&self,
|
||||||
|
hash: Hash,
|
||||||
|
variant: String,
|
||||||
|
) -> Result<NotificationEntry, RepoError>;
|
||||||
|
|
||||||
async fn variant_heartbeat(&self, hash: Hash, variant: String) -> Result<(), RepoError>;
|
async fn variant_heartbeat(&self, hash: Hash, variant: String) -> Result<(), RepoError>;
|
||||||
|
|
||||||
async fn notify_variant(&self, hash: Hash, variant: String) -> Result<(), RepoError>;
|
async fn notify_variant(&self, hash: Hash, variant: String) -> Result<(), RepoError>;
|
||||||
|
@ -784,6 +789,14 @@ where
|
||||||
T::claim_variant_processing_rights(self, hash, variant).await
|
T::claim_variant_processing_rights(self, hash, variant).await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn variant_waiter(
|
||||||
|
&self,
|
||||||
|
hash: Hash,
|
||||||
|
variant: String,
|
||||||
|
) -> Result<NotificationEntry, RepoError> {
|
||||||
|
T::variant_waiter(self, hash, variant).await
|
||||||
|
}
|
||||||
|
|
||||||
async fn variant_heartbeat(&self, hash: Hash, variant: String) -> Result<(), RepoError> {
|
async fn variant_heartbeat(&self, hash: Hash, variant: String) -> Result<(), RepoError> {
|
||||||
T::variant_heartbeat(self, hash, variant).await
|
T::variant_heartbeat(self, hash, variant).await
|
||||||
}
|
}
|
||||||
|
|
|
@ -1117,6 +1117,19 @@ impl VariantRepo for PostgresRepo {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn variant_waiter(
|
||||||
|
&self,
|
||||||
|
hash: Hash,
|
||||||
|
variant: String,
|
||||||
|
) -> Result<NotificationEntry, RepoError> {
|
||||||
|
let key = Arc::from(format!("{}{variant}", hash.to_base64()));
|
||||||
|
let entry = self.listen_on_key(key);
|
||||||
|
|
||||||
|
self.register_interest().await?;
|
||||||
|
|
||||||
|
Ok(entry)
|
||||||
|
}
|
||||||
|
|
||||||
#[tracing::instrument(level = "debug", skip(self))]
|
#[tracing::instrument(level = "debug", skip(self))]
|
||||||
async fn variant_heartbeat(&self, hash: Hash, variant: String) -> Result<(), RepoError> {
|
async fn variant_heartbeat(&self, hash: Hash, variant: String) -> Result<(), RepoError> {
|
||||||
let key = format!("{}{variant}", hash.to_base64());
|
let key = format!("{}{variant}", hash.to_base64());
|
||||||
|
|
|
@ -1491,6 +1491,18 @@ impl VariantRepo for SledRepo {
|
||||||
Ok(Ok(()))
|
Ok(Ok(()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn variant_waiter(
|
||||||
|
&self,
|
||||||
|
hash: Hash,
|
||||||
|
variant: String,
|
||||||
|
) -> Result<NotificationEntry, RepoError> {
|
||||||
|
let entry = self
|
||||||
|
.notifications
|
||||||
|
.register_interest(Arc::from(format!("{}{variant}", hash.to_base64())));
|
||||||
|
|
||||||
|
Ok(entry)
|
||||||
|
}
|
||||||
|
|
||||||
#[tracing::instrument(level = "trace", skip(self))]
|
#[tracing::instrument(level = "trace", skip(self))]
|
||||||
async fn variant_heartbeat(&self, hash: Hash, variant: String) -> Result<(), RepoError> {
|
async fn variant_heartbeat(&self, hash: Hash, variant: String) -> Result<(), RepoError> {
|
||||||
let key = (hash, variant);
|
let key = (hash, variant);
|
||||||
|
|
Loading…
Reference in a new issue