use ff_core::backend::{BackendTag, Handle, HandleKind, HandleOpaque};
use ff_core::engine_error::{EngineError, ValidationKind};
use ff_core::handle_codec::{decode as core_decode, encode as core_encode, HandlePayload};
#[allow(dead_code)] pub(crate) fn encode_handle(payload: &HandlePayload, kind: HandleKind) -> Handle {
let opaque: HandleOpaque = core_encode(BackendTag::Postgres, payload);
Handle::new(BackendTag::Postgres, kind, opaque)
}
#[allow(dead_code)] pub(crate) fn decode_handle(handle: &Handle) -> Result<HandlePayload, EngineError> {
if handle.backend != BackendTag::Postgres {
return Err(EngineError::Validation {
kind: ValidationKind::HandleFromOtherBackend,
detail: format!(
"expected={:?} actual={:?}",
BackendTag::Postgres,
handle.backend
),
});
}
let decoded = core_decode(&handle.opaque)?;
if decoded.tag != BackendTag::Postgres {
return Err(EngineError::Validation {
kind: ValidationKind::HandleFromOtherBackend,
detail: format!(
"expected={:?} actual={:?} (embedded tag)",
BackendTag::Postgres,
decoded.tag
),
});
}
Ok(decoded.payload)
}
#[cfg(test)]
mod tests {
use super::*;
use ff_core::partition::PartitionConfig;
use ff_core::types::{
AttemptId, AttemptIndex, ExecutionId, LaneId, LeaseEpoch, LeaseId, WorkerInstanceId,
};
fn sample_payload() -> HandlePayload {
HandlePayload::new(
ExecutionId::solo(&LaneId::new("default"), &PartitionConfig::default()),
AttemptIndex::new(1),
AttemptId::new(),
LeaseId::new(),
LeaseEpoch(1),
30_000,
LaneId::new("default"),
WorkerInstanceId::new("pg-worker-1"),
)
}
#[test]
fn round_trip_fresh() {
let p = sample_payload();
let h = encode_handle(&p, HandleKind::Fresh);
assert_eq!(h.backend, BackendTag::Postgres);
let back = decode_handle(&h).expect("round-trip");
assert_eq!(back, p);
}
#[test]
fn valkey_handle_rejected_as_other_backend() {
let p = sample_payload();
let valkey_opaque = ff_core::handle_codec::encode(BackendTag::Valkey, &p);
let handle = Handle::new(BackendTag::Valkey, HandleKind::Fresh, valkey_opaque);
let err = decode_handle(&handle).unwrap_err();
match err {
EngineError::Validation { kind, .. } => {
assert_eq!(kind, ValidationKind::HandleFromOtherBackend);
}
other => panic!("expected Validation, got {other:?}"),
}
}
}