use std::fmt;
use std::sync::Arc;
use async_trait::async_trait;
use serde::{Deserialize, Serialize};
use serde_json::Value;
use crate::infra::execution::handle::ExecutionHandle;
use crate::infra::execution::placement::PlacementPolicy;
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum ExecutionBackendKind {
ResidentLocal,
ResidentWorker,
DockerJob,
K8sJob,
SparkSubmit,
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, Default)]
#[serde(rename_all = "snake_case")]
pub enum ExecutionProfileKind {
#[default]
Resident,
DockerJob,
K8sJob,
SparkSubmit,
}
impl ExecutionBackendKind {
pub fn profile_kind(self) -> ExecutionProfileKind {
match self {
Self::ResidentLocal | Self::ResidentWorker => ExecutionProfileKind::Resident,
Self::DockerJob => ExecutionProfileKind::DockerJob,
Self::K8sJob => ExecutionProfileKind::K8sJob,
Self::SparkSubmit => ExecutionProfileKind::SparkSubmit,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ExecutionRequest {
pub owner: String,
pub project: String,
pub file_rel_path: String,
#[serde(default)]
pub input: Value,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub placement: Option<PlacementPolicy>,
#[serde(default)]
pub metadata: Value,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct ExecutionError {
pub code: String,
pub message: String,
}
impl ExecutionError {
pub fn new(code: impl Into<String>, message: impl Into<String>) -> Self {
Self {
code: code.into(),
message: message.into(),
}
}
pub fn not_implemented(name: &str) -> Self {
Self::new(
"EXECUTION_BACKEND_NOT_IMPLEMENTED",
format!("execution backend '{name}' is not implemented yet"),
)
}
}
impl fmt::Display for ExecutionError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}: {}", self.code, self.message)
}
}
impl std::error::Error for ExecutionError {}
#[async_trait]
pub trait ExecutionBackend: Send + Sync {
fn id(&self) -> &'static str;
fn kind(&self) -> ExecutionBackendKind;
async fn execute(&self, request: ExecutionRequest) -> Result<ExecutionHandle, ExecutionError>;
}
pub type DynExecutionBackend = Arc<dyn ExecutionBackend>;