use ff_core::contracts::*;
use crate::error::ScriptError;
use ff_core::keys::{ExecKeyContext, IndexKeys};
use ff_core::types::*;
use crate::result::{FcallResult, FromFcallResult};
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum ChangePriorityResultPartial {
Changed,
}
impl ChangePriorityResultPartial {
pub fn complete(self, execution_id: ExecutionId) -> ChangePriorityResult {
match self {
Self::Changed => ChangePriorityResult::Changed { execution_id },
}
}
}
pub struct SchedOpKeys<'a> {
pub ctx: &'a ExecKeyContext,
pub idx: &'a IndexKeys,
pub lane_id: &'a LaneId,
}
ff_function! {
pub ff_issue_claim_grant(args: IssueClaimGrantArgs) -> IssueClaimGrantResult {
keys(k: &SchedOpKeys<'_>) {
k.ctx.core(),
k.ctx.claim_grant(),
k.idx.lane_eligible(k.lane_id),
}
argv {
args.execution_id.to_string(),
args.worker_id.to_string(),
args.worker_instance_id.to_string(),
args.lane_id.to_string(),
args.capability_hash.clone().unwrap_or_default(),
args.grant_ttl_ms.to_string(),
args.route_snapshot_json.clone().unwrap_or_default(),
args.admission_summary.clone().unwrap_or_default(),
args.worker_capabilities.iter().cloned().collect::<Vec<_>>().join(","),
}
}
}
impl FromFcallResult for IssueClaimGrantResult {
fn from_fcall_result(raw: &ferriskey::Value) -> Result<Self, ScriptError> {
let r = FcallResult::parse(raw)?.into_success()?;
let eid_str = r.field_str(0);
let eid = ExecutionId::parse(&eid_str)
.map_err(|e| ScriptError::Parse {
fcall: "ff_issue_claim_grant".into(),
execution_id: None,
message: format!("bad execution_id: {e}"),
})?;
Ok(IssueClaimGrantResult::Granted { execution_id: eid })
}
}
ff_function! {
pub ff_change_priority(args: ChangePriorityArgs) -> ChangePriorityResultPartial {
keys(k: &SchedOpKeys<'_>) {
k.ctx.core(),
k.idx.lane_eligible(k.lane_id),
}
argv {
args.execution_id.to_string(),
args.new_priority.to_string(),
}
}
}
impl FromFcallResult for ChangePriorityResultPartial {
fn from_fcall_result(raw: &ferriskey::Value) -> Result<Self, ScriptError> {
let _r = FcallResult::parse(raw)?.into_success()?;
Ok(Self::Changed)
}
}
ff_function! {
pub ff_update_progress(args: UpdateProgressArgs) -> UpdateProgressResult {
keys(k: &SchedOpKeys<'_>) {
k.ctx.core(),
}
argv {
args.execution_id.to_string(),
args.lease_id.to_string(),
args.lease_epoch.to_string(),
args.progress_pct.map(|p| p.to_string()).unwrap_or_default(),
args.progress_message.clone().unwrap_or_default(),
}
}
}
impl FromFcallResult for UpdateProgressResult {
fn from_fcall_result(raw: &ferriskey::Value) -> Result<Self, ScriptError> {
let _r = FcallResult::parse(raw)?.into_success()?;
Ok(UpdateProgressResult::Updated)
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ClaimGrantOutcomePartial {
pub lease_id: LeaseId,
pub lease_epoch: LeaseEpoch,
pub attempt_index: AttemptIndex,
}
impl ClaimGrantOutcomePartial {
pub fn complete(self) -> ClaimGrantOutcome {
ClaimGrantOutcome::new(self.lease_id, self.lease_epoch, self.attempt_index)
}
}
ff_function! {
pub ff_issue_grant_and_claim(args: ClaimExecutionArgs) -> ClaimGrantOutcomePartial {
keys(k: &crate::functions::execution::ExecOpKeys<'_>) {
k.ctx.core(),
k.ctx.claim_grant(),
k.idx.lane_eligible(k.lane_id),
k.idx.lease_expiry(),
k.idx.worker_leases(k.worker_instance_id),
k.ctx.attempts(),
k.ctx.lease_current(),
k.ctx.lease_history(),
k.idx.lane_active(k.lane_id),
k.idx.attempt_timeout(),
k.idx.execution_deadline(),
}
argv {
args.execution_id.to_string(),
args.worker_id.to_string(),
args.worker_instance_id.to_string(),
args.lane_id.to_string(),
String::new(),
args.lease_id.to_string(),
args.lease_ttl_ms.to_string(),
args.attempt_id.to_string(),
args.attempt_policy_json.clone(),
args.attempt_timeout_ms.map(|t| t.to_string()).unwrap_or_default(),
args.execution_deadline_at.map(|t| t.to_string()).unwrap_or_default(),
}
}
}
impl FromFcallResult for ClaimGrantOutcomePartial {
fn from_fcall_result(raw: &ferriskey::Value) -> Result<Self, ScriptError> {
let r = FcallResult::parse(raw)?.into_success()?;
let lease_id = LeaseId::parse(&r.field_str(0))
.map_err(|e| ScriptError::Parse {
fcall: "ff_issue_grant_and_claim".into(),
execution_id: None,
message: format!("bad lease_id: {e}"),
})?;
let epoch = r
.field_str(1)
.parse::<u64>()
.map_err(|e| ScriptError::Parse {
fcall: "ff_issue_grant_and_claim".into(),
execution_id: None,
message: format!("bad epoch: {e}"),
})?;
let attempt_index = r
.field_str(2)
.parse::<u32>()
.map_err(|e| ScriptError::Parse {
fcall: "ff_issue_grant_and_claim".into(),
execution_id: None,
message: format!("bad attempt_index: {e}"),
})?;
Ok(Self {
lease_id,
lease_epoch: LeaseEpoch::new(epoch),
attempt_index: AttemptIndex::new(attempt_index),
})
}
}
#[cfg(test)]
mod partial_tests {
use super::*;
use ff_core::partition::PartitionConfig;
#[test]
fn change_priority_partial_complete_attaches_execution_id() {
let partial = ChangePriorityResultPartial::Changed;
let eid = ExecutionId::for_flow(&FlowId::new(), &PartitionConfig::default());
let full = partial.complete(eid.clone());
match full {
ChangePriorityResult::Changed { execution_id } => assert_eq!(execution_id, eid),
}
}
}