ff_script/functions/
lease.rs1use crate::error::ScriptError;
8use ff_core::contracts::{
9 MarkLeaseExpiredArgs, MarkLeaseExpiredResult, RenewLeaseArgs, RenewLeaseResult,
10 RevokeLeaseArgs, RevokeLeaseResult,
11};
12use ff_core::keys::ExecKeyContext;
13use ff_core::types::TimestampMs;
14
15use crate::result::{FcallResult, FromFcallResult};
16
17impl FromFcallResult for RenewLeaseResult {
20 fn from_fcall_result(raw: &ferriskey::Value) -> Result<Self, ScriptError> {
21 let r = FcallResult::parse(raw)?.into_success()?;
22 let expires_str = r.field_str(0);
24 let expires_ms: i64 = expires_str
25 .parse()
26 .map_err(|_| ScriptError::Parse {
27 fcall: "ff_renew_lease".into(),
28 execution_id: None,
29 message: format!("invalid expires_at: {expires_str}"),
30 })?;
31 Ok(RenewLeaseResult::Renewed {
32 expires_at: TimestampMs::from_millis(expires_ms),
33 })
34 }
35}
36
37impl FromFcallResult for MarkLeaseExpiredResult {
38 fn from_fcall_result(raw: &ferriskey::Value) -> Result<Self, ScriptError> {
39 let r = FcallResult::parse(raw)?.into_success()?;
40 match r.status.as_str() {
42 "OK" => Ok(MarkLeaseExpiredResult::MarkedExpired),
43 "ALREADY_SATISFIED" => Ok(MarkLeaseExpiredResult::AlreadySatisfied {
44 reason: r.field_str(0),
45 }),
46 other => Err(ScriptError::Parse {
47 fcall: "ff_mark_lease_expired_if_due".into(),
48 execution_id: None,
49 message: format!(
50 "unexpected status from ff_mark_lease_expired_if_due: {other}"
51 ),
52 }),
53 }
54 }
55}
56
57impl FromFcallResult for RevokeLeaseResult {
58 fn from_fcall_result(raw: &ferriskey::Value) -> Result<Self, ScriptError> {
59 let r = FcallResult::parse(raw)?.into_success()?;
60 match r.status.as_str() {
63 "OK" => {
64 Ok(RevokeLeaseResult::Revoked {
66 lease_id: r.field_str(1),
67 lease_epoch: r.field_str(2),
68 })
69 }
70 "ALREADY_SATISFIED" => Ok(RevokeLeaseResult::AlreadySatisfied {
71 reason: r.field_str(0),
72 }),
73 other => Err(ScriptError::Parse {
74 fcall: "ff_revoke_lease".into(),
75 execution_id: None,
76 message: format!(
77 "unexpected status from ff_revoke_lease: {other}"
78 ),
79 }),
80 }
81 }
82}
83
84ff_function! {
87 pub ff_renew_lease(args: RenewLeaseArgs) -> RenewLeaseResult {
93 keys(ctx: &ExecKeyContext) {
94 ctx.core(),
95 ctx.lease_current(),
96 ctx.lease_history(),
97 format!("ff:idx:{}:lease_expiry", ctx.hash_tag()),
98 }
99 argv {
102 args.execution_id.to_string(),
103 args.attempt_index.to_string(),
104 args.fence.as_ref().map(|f| f.attempt_id.to_string()).unwrap_or_default(),
105 args.fence.as_ref().map(|f| f.lease_id.to_string()).unwrap_or_default(),
106 args.fence.as_ref().map(|f| f.lease_epoch.to_string()).unwrap_or_default(),
107 args.lease_ttl_ms.to_string(),
108 args.lease_history_grace_ms.to_string(),
109 }
110 }
111
112 pub ff_mark_lease_expired_if_due(args: MarkLeaseExpiredArgs) -> MarkLeaseExpiredResult {
118 keys(ctx: &ExecKeyContext) {
119 ctx.core(),
120 ctx.lease_current(),
121 format!("ff:idx:{}:lease_expiry", ctx.hash_tag()),
122 ctx.lease_history(),
123 }
124 argv {
125 args.execution_id.to_string(),
126 }
127 }
128
129 pub ff_revoke_lease(args: RevokeLeaseArgs) -> RevokeLeaseResult {
134 keys(ctx: &ExecKeyContext) {
135 ctx.core(),
136 ctx.lease_current(),
137 ctx.lease_history(),
138 format!("ff:idx:{}:lease_expiry", ctx.hash_tag()),
139 format!("ff:idx:{}:worker:{}:leases", ctx.hash_tag(), args.worker_instance_id),
140 }
141 argv {
142 args.execution_id.to_string(),
143 args.expected_lease_id.as_deref().unwrap_or("").to_string(),
144 args.reason.clone(),
145 }
146 }
147}