ff_script/functions/
scheduling.rs1use ff_core::contracts::*;
7use crate::error::ScriptError;
8use ff_core::keys::{ExecKeyContext, IndexKeys};
9use ff_core::types::*;
10
11use crate::result::{FcallResult, FromFcallResult};
12
13#[derive(Clone, Debug, PartialEq, Eq)]
15pub enum ChangePriorityResultPartial {
16 Changed,
17}
18
19impl ChangePriorityResultPartial {
20 pub fn complete(self, execution_id: ExecutionId) -> ChangePriorityResult {
21 match self {
22 Self::Changed => ChangePriorityResult::Changed { execution_id },
23 }
24 }
25}
26
27pub struct SchedOpKeys<'a> {
29 pub ctx: &'a ExecKeyContext,
30 pub idx: &'a IndexKeys,
31 pub lane_id: &'a LaneId,
32}
33
34ff_function! {
43 pub ff_issue_claim_grant(args: IssueClaimGrantArgs) -> IssueClaimGrantResult {
44 keys(k: &SchedOpKeys<'_>) {
45 k.ctx.core(),
46 k.ctx.claim_grant(),
47 k.idx.lane_eligible(k.lane_id),
48 }
49 argv {
50 args.execution_id.to_string(),
51 args.worker_id.to_string(),
52 args.worker_instance_id.to_string(),
53 args.lane_id.to_string(),
54 args.capability_hash.clone().unwrap_or_default(),
55 args.grant_ttl_ms.to_string(),
56 args.route_snapshot_json.clone().unwrap_or_default(),
57 args.admission_summary.clone().unwrap_or_default(),
58 args.worker_capabilities.iter().cloned().collect::<Vec<_>>().join(","),
60 }
61 }
62}
63
64impl FromFcallResult for IssueClaimGrantResult {
65 fn from_fcall_result(raw: &ferriskey::Value) -> Result<Self, ScriptError> {
66 let r = FcallResult::parse(raw)?.into_success()?;
67 let eid_str = r.field_str(0);
69 let eid = ExecutionId::parse(&eid_str)
70 .map_err(|e| ScriptError::Parse {
71 fcall: "ff_issue_claim_grant".into(),
72 execution_id: None,
73 message: format!("bad execution_id: {e}"),
74 })?;
75 Ok(IssueClaimGrantResult::Granted { execution_id: eid })
76 }
77}
78
79ff_function! {
85 pub ff_change_priority(args: ChangePriorityArgs) -> ChangePriorityResultPartial {
86 keys(k: &SchedOpKeys<'_>) {
87 k.ctx.core(),
88 k.idx.lane_eligible(k.lane_id),
89 }
90 argv {
91 args.execution_id.to_string(),
92 args.new_priority.to_string(),
93 }
94 }
95}
96
97impl FromFcallResult for ChangePriorityResultPartial {
98 fn from_fcall_result(raw: &ferriskey::Value) -> Result<Self, ScriptError> {
99 let _r = FcallResult::parse(raw)?.into_success()?;
100 Ok(Self::Changed)
102 }
103}
104
105ff_function! {
111 pub ff_update_progress(args: UpdateProgressArgs) -> UpdateProgressResult {
112 keys(k: &SchedOpKeys<'_>) {
113 k.ctx.core(),
114 }
115 argv {
116 args.execution_id.to_string(),
117 args.lease_id.to_string(),
118 args.lease_epoch.to_string(),
119 args.progress_pct.map(|p| p.to_string()).unwrap_or_default(),
120 args.progress_message.clone().unwrap_or_default(),
121 }
122 }
123}
124
125impl FromFcallResult for UpdateProgressResult {
126 fn from_fcall_result(raw: &ferriskey::Value) -> Result<Self, ScriptError> {
127 let _r = FcallResult::parse(raw)?.into_success()?;
128 Ok(UpdateProgressResult::Updated)
130 }
131}
132
133#[cfg(test)]
135mod partial_tests {
136 use super::*;
137 use ff_core::partition::PartitionConfig;
138
139 #[test]
140 fn change_priority_partial_complete_attaches_execution_id() {
141 let partial = ChangePriorityResultPartial::Changed;
142 let eid = ExecutionId::for_flow(&FlowId::new(), &PartitionConfig::default());
143 let full = partial.complete(eid.clone());
144 match full {
145 ChangePriorityResult::Changed { execution_id } => assert_eq!(execution_id, eid),
146 }
147 }
148}