Add fenced attempt mutation and outcome publication
This commit is contained in:
parent
2db0e22232
commit
80c631f780
1 changed files with 1868 additions and 18 deletions
|
|
@ -10,12 +10,13 @@ use remora_durable::{
|
|||
};
|
||||
use serde::Serialize;
|
||||
use serde_json::json;
|
||||
use sqlx::PgPool;
|
||||
use sqlx::{PgPool, types::Json};
|
||||
use time::OffsetDateTime;
|
||||
|
||||
use crate::{
|
||||
ActivationOutcome, AttemptAuthority, AttemptError, AttemptFaultInjector, AttemptFaultPoint,
|
||||
AttemptState, ClaimOutcome, ClaimRejection, RecoveryOutcome, RenewalOutcome,
|
||||
AttemptState, CheckpointProjection, ClaimOutcome, ClaimRejection, RecoveryOutcome,
|
||||
RenewalOutcome,
|
||||
};
|
||||
|
||||
struct NoFaults;
|
||||
|
|
@ -41,12 +42,12 @@ impl Default for AttemptConfig {
|
|||
|
||||
#[derive(Clone)]
|
||||
pub struct AttemptService {
|
||||
pool: PgPool,
|
||||
coordination: CoordinationStore,
|
||||
pub(crate) pool: PgPool,
|
||||
pub(crate) coordination: CoordinationStore,
|
||||
local_permits: LocalPermitGate,
|
||||
operation_subject: OpaqueId,
|
||||
pub(crate) operation_subject: OpaqueId,
|
||||
faults: Arc<dyn AttemptFaultInjector>,
|
||||
config: AttemptConfig,
|
||||
pub(crate) config: AttemptConfig,
|
||||
}
|
||||
|
||||
impl AttemptService {
|
||||
|
|
@ -477,14 +478,26 @@ async fn authorize_attempt(
|
|||
tx: &mut remora_durable::PgTx<'_>,
|
||||
input: AuthorizeInput<'_>,
|
||||
) -> Result<ClaimOutcome, DurableError> {
|
||||
let row = sqlx::query_as::<_, (String, bool, i64, Option<String>)>(
|
||||
"SELECT phase, dispatch_needed, current_fence, authority_attempt_id
|
||||
let row = sqlx::query_as::<
|
||||
_,
|
||||
(
|
||||
String,
|
||||
bool,
|
||||
i64,
|
||||
Option<String>,
|
||||
Option<Json<crate::DurableDescriptor>>,
|
||||
Option<Json<CheckpointProjection>>,
|
||||
),
|
||||
>(
|
||||
"SELECT phase, dispatch_needed, current_fence, authority_attempt_id,
|
||||
resolved_source, checkpoint
|
||||
FROM jobs WHERE job_id = $1 FOR UPDATE",
|
||||
)
|
||||
.bind(input.job_id.as_str())
|
||||
.fetch_optional(tx.as_mut())
|
||||
.await?;
|
||||
let Some((phase, dispatch_needed, current_fence, authority)) = row else {
|
||||
let Some((phase, dispatch_needed, current_fence, authority, resolved_source, checkpoint)) = row
|
||||
else {
|
||||
return Ok(claim_rejected(ClaimRejection::JobUnavailable));
|
||||
};
|
||||
if phase != "queued" || !dispatch_needed || authority.is_some() {
|
||||
|
|
@ -509,17 +522,29 @@ async fn authorize_attempt(
|
|||
input.reserved.store(true, Ordering::Release);
|
||||
input.faults.hit(AttemptFaultPoint::ClaimAfterReserve);
|
||||
let fence = current_fence + 1;
|
||||
let initial_progress = match (resolved_source, checkpoint) {
|
||||
(Some(source), Some(checkpoint))
|
||||
if checkpoint
|
||||
.0
|
||||
.reusable()
|
||||
.is_some_and(|value| value.resolved_source_id == source.0.id) =>
|
||||
{
|
||||
checkpoint.0.reusable().unwrap().validated_bytes
|
||||
}
|
||||
_ => 0,
|
||||
};
|
||||
let now = OffsetDateTime::now_utc();
|
||||
sqlx::query(
|
||||
"INSERT INTO attempts (
|
||||
attempt_id, job_id, fence, worker_incarnation, state,
|
||||
initial_progress, authorized_at, executing_at, reaped_at
|
||||
) VALUES ($1, $2, $3, $4, 'authorized', 0, $5, NULL, NULL)",
|
||||
) VALUES ($1, $2, $3, $4, 'authorized', $5, $6, NULL, NULL)",
|
||||
)
|
||||
.bind(input.attempt_id.as_str())
|
||||
.bind(input.job_id.as_str())
|
||||
.bind(i64::try_from(fence).map_err(DurableError::effect)?)
|
||||
.bind(input.worker.as_str())
|
||||
.bind(i64::try_from(initial_progress).map_err(DurableError::effect)?)
|
||||
.bind(now)
|
||||
.execute(tx.as_mut())
|
||||
.await?;
|
||||
|
|
|
|||
Loading…
Reference in a new issue