use std::fmt::Debug;
use anyhow::Result;
use bytes::Bytes;
use serde::{Deserialize, Serialize};
use crate::{
__private::OPERATIONS,
operation::Operation,
serializer::{Serializable, Serializer},
};
#[derive(Debug)]
pub struct Task<'a, Op: Operation, Metadata: Serializable> {
pub routing_key: String,
pub metadata: Metadata,
pub op: &'a Op,
pub input: Op::Input,
}
#[derive(Serialize, Deserialize, Debug)]
#[serde(bound = "Op: Operation")]
pub struct TaskOutput<Op: Operation, Metadata: Serializable> {
pub metadata: Metadata,
pub output: Op::Output,
}
pub type TaskResult<Op, Metadata> = Result<TaskOutput<Op, Metadata>>;
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct AnyTask {
pub routing_key: String,
pub metadata: Bytes,
pub op: Bytes,
pub operation_id: u8,
pub input: Bytes,
pub serializer: Serializer,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct AnyTaskOutput {
pub metadata: Bytes,
pub output: Bytes,
pub serializer: Serializer,
}
impl<Op: Operation, Metadata: Serializable> TryFrom<AnyTaskOutput> for TaskOutput<Op, Metadata> {
type Error = anyhow::Error;
fn try_from(
AnyTaskOutput {
metadata,
output,
serializer,
}: AnyTaskOutput,
) -> Result<Self> {
let metadata = serializer.from_bytes(&metadata)?;
let output = serializer.from_bytes(&output)?;
Ok(TaskOutput { metadata, output })
}
}
#[derive(Serialize, Deserialize, Debug)]
pub enum AnyTaskResult {
Ok(AnyTaskOutput),
Err(String),
}
impl<'a, Op: Operation, Metadata: Serializable> Task<'a, Op, Metadata> {
pub fn as_any_task(&self, serializer: Serializer) -> Result<AnyTask> {
let routing_key = self.routing_key.clone();
let metadata = serializer.to_bytes(&self.metadata)?;
let input = serializer.to_bytes(&self.input)?;
let op = serializer.to_bytes(self.op)?;
Ok(AnyTask {
routing_key,
metadata,
operation_id: Op::ID,
op,
input,
serializer,
})
}
}
impl AnyTaskResult {
pub fn into_task_result<Op: Operation, Metadata: Serializable>(
self,
) -> TaskResult<Op, Metadata> {
match self {
Self::Ok(any_task_output) => Ok(any_task_output.try_into()?),
Self::Err(msg) => Err(anyhow::anyhow!(msg)),
}
}
}
impl<Op: Operation, Metadata: Serializable> From<AnyTaskResult>
for Result<TaskOutput<Op, Metadata>>
{
fn from(value: AnyTaskResult) -> Self {
value.into_task_result()
}
}
impl AnyTask {
pub async fn remote_execute(self) -> crate::operation::Result<AnyTaskOutput> {
OPERATIONS[self.operation_id as usize](self).await
}
}