use std::any::Any;
use std::path::PathBuf;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use serde_json::Value;
use specta::Type;
use tokio::sync::oneshot;
use uuid::Uuid;
use crate::auth::{Jwt, MachineIssuerId};
use crate::bus::BusRpcContext;
use super::FlowDomain;
use super::ast::{ContentAddressedPath, ContentAddressedRoot, FlowNode};
use super::cron::FlowTriggerRecord;
use super::mobility::{
FlowActivationAcknowledgement, FlowMobilityCommitAcknowledgement, FlowMobilitySnapshot, FlowYieldAcknowledgement,
};
use super::registration::NodeKind;
use super::types::{
FlowDefinition, FlowError, FlowExecutionDetail, FlowExecutionId, FlowExecutionSnapshot, FlowFailure, FlowId,
FlowInvocationKind, FlowMobilityDestination, FlowMobilityReadiness, FlowNodeId, NodeExecutionId,
ScriptSourceLocation,
};
#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize, Type, JsonSchema)]
pub struct LifecycleCorrelation {
pub node_kind: NodeKind,
pub flow_id: FlowId,
pub flow_node_id: FlowNodeId,
pub flow_execution_id: FlowExecutionId,
pub node_execution_id: NodeExecutionId,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct LifecycleStart<T> {
pub correlation: LifecycleCorrelation,
pub payload: T,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct LifecycleTick<T> {
pub correlation: LifecycleCorrelation,
pub payload: T,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct LifecycleSuccess<T> {
pub correlation: LifecycleCorrelation,
pub payload: T,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct LifecycleError<T> {
pub correlation: LifecycleCorrelation,
pub payload: T,
}
pub type ErasedLifecyclePayload = Box<dyn Any + Send + Sync>;
pub struct ErasedLifecycleMessage {
pub correlation: LifecycleCorrelation,
pub node: FlowNode,
pub execution_root: PathBuf,
pub node_token: Option<Jwt>,
pub payload: ErasedLifecyclePayload,
}
pub(crate) struct FlowRequest {
pub payload: FlowRequestPayload,
pub reply_to: oneshot::Sender<Result<FlowResponse, FlowError>>,
}
#[aves::bus_requests(
marker = FlowDomain,
context = BusRpcContext,
root_error = FlowError,
domain_error = FlowError
)]
#[derive(Clone, Debug, Deserialize, Serialize, Type, JsonSchema)]
pub enum FlowRequestPayload {
#[privileged(reason = "Flow runtime lifecycle is owned by Aves")]
StartRuntime,
#[privileged(reason = "Flow runtime lifecycle is owned by Aves")]
StopRuntime,
#[operation(name = "createFlow", kind = "mutation", response = FlowCreatedOutput, response_variant = "FlowCreated")]
CreateFlow { flow: FlowDefinition },
#[operation(name = "createFlowTrigger", kind = "mutation", response = FlowTriggerCreatedOutput, response_variant = "FlowTriggerCreated")]
CreateFlowTrigger { trigger: FlowTriggerRecord },
#[operation(name = "createFlowNode", kind = "mutation", response = FlowNodeCreatedOutput, response_variant = "FlowNodeCreated")]
CreateFlowNode { flow_id: FlowId, node: FlowNode },
#[operation(name = "listFlows", kind = "query", response = FlowsListedOutput, response_variant = "FlowsListed")]
ListFlows,
#[operation(name = "listFlowTriggers", kind = "query", response = FlowTriggersListedOutput, response_variant = "FlowTriggersListed")]
ListFlowTriggers { flow_id: FlowId },
#[privileged(reason = "Source-domain runtime reconciliation")]
ListSourceTriggers { adapter_kind: String },
#[operation(name = "listActiveExecutions", kind = "query", response = ActiveExecutionsListedOutput, response_variant = "ActiveExecutionsListed")]
ListActiveExecutions,
#[operation(name = "listTerminalExecutions", kind = "query", response = TerminalExecutionsListedOutput, response_variant = "TerminalExecutionsListed")]
ListTerminalExecutions,
#[operation(name = "getFlow", kind = "query", response = FlowRetrievedOutput, response_variant = "FlowRetrieved")]
GetFlow { flow_id: FlowId },
#[operation(name = "getExecutionDetail", kind = "query", response = ExecutionDetailRetrievedOutput, response_variant = "ExecutionDetailRetrieved")]
GetExecutionDetail { execution_id: FlowExecutionId },
#[operation(name = "readScriptSource", kind = "query", response = ScriptSourceReadOutput, response_variant = "ScriptSourceRead")]
ReadScriptSource {
location: ScriptSourceLocation,
path: String,
},
#[operation(name = "start", kind = "mutation", response = StartedOutput, response_variant = "Started")]
Start {
flow_id: FlowId,
pulse: Value,
automatic: bool,
#[serde(default)]
invocation_kind: FlowInvocationKind,
},
#[privileged(reason = "Source-domain event admission")]
FireSourceTrigger {
#[specta(type = String)]
#[schemars(with = "String")]
trigger_id: uuid::Uuid,
pulse: Value,
},
#[operation(name = "abort", kind = "mutation", response = AbortedOutput, response_variant = "Aborted")]
Abort { execution_id: FlowExecutionId },
#[operation(name = "importWorkspace", kind = "mutation", response = WorkspaceImportedOutput, response_variant = "WorkspaceImported")]
ImportWorkspace { source_path: String },
#[operation(name = "downloadWorkspaceBlob", kind = "mutation", response = WorkspaceImportedOutput, response_variant = "WorkspaceImported")]
DownloadWorkspaceBlob { ticket: String },
#[operation(name = "setEnabled", kind = "mutation", response = FlowUpdatedOutput, response_variant = "FlowUpdated")]
SetEnabled { flow_id: FlowId, enabled: bool },
#[operation(name = "updateFlow", kind = "mutation", response = FlowUpdatedOutput, response_variant = "FlowUpdated")]
UpdateFlow { flow: FlowDefinition },
#[operation(name = "updateFlowTrigger", kind = "mutation", response = FlowTriggerUpdatedOutput, response_variant = "FlowTriggerUpdated")]
UpdateFlowTrigger { trigger: FlowTriggerRecord },
#[operation(name = "updateFlowNode", kind = "mutation", response = FlowNodeUpdatedOutput, response_variant = "FlowNodeUpdated")]
UpdateFlowNode { flow_id: FlowId, node: FlowNode },
#[operation(name = "saveScriptSource", kind = "mutation", response = ScriptSourceSavedOutput, response_variant = "ScriptSourceSaved")]
SaveScriptSource {
location: ScriptSourceLocation,
path: String,
source: String,
},
#[privileged(reason = "Flow retention is runtime-owned")]
UpdateRetention { retention_completed_runs: u32 },
#[operation(name = "deleteFlow", kind = "mutation", response = FlowDeletedOutput, response_variant = "FlowDeleted")]
DeleteFlow { flow_id: FlowId },
#[operation(name = "deleteFlowTrigger", kind = "mutation", response = FlowTriggerDeletedOutput, response_variant = "FlowTriggerDeleted")]
DeleteFlowTrigger {
#[specta(type = String)]
#[schemars(with = "String")]
trigger_id: Uuid,
},
#[operation(name = "deleteFlowNode", kind = "mutation", response = FlowNodeDeletedOutput, response_variant = "FlowNodeDeleted")]
DeleteFlowNode { flow_id: FlowId, node_id: FlowNodeId },
#[operation(name = "selectMobilityDestination", kind = "mutation", response = MobilityDestinationSelectedOutput, response_variant = "MobilityDestinationSelected")]
SelectMobilityDestination {
flow_id: FlowId,
destinations: Vec<FlowMobilityDestination>,
},
#[operation(name = "getFlowMobilityReadiness", kind = "query", response = FlowMobilityReadinessOutput, response_variant = "FlowMobilityReadiness")]
GetFlowMobilityReadiness { flow_id: FlowId },
#[operation(name = "importMobilitySnapshot", kind = "mutation", response = FlowMobilityCommitAcknowledgementOutput, response_variant = "FlowMobilityCommitAcknowledgement")]
ImportMobilitySnapshot {
snapshot: FlowMobilitySnapshot,
source_peer_key: MachineIssuerId,
},
#[operation(name = "synchronizeFlow", kind = "mutation", response = FlowMobilityReadinessOutput, response_variant = "FlowMobilityReadiness")]
SynchronizeFlow { flow_id: FlowId },
#[operation(name = "yieldFlowAuthority", kind = "mutation", response = FlowAuthorityYieldedOutput, response_variant = "FlowAuthorityYielded")]
YieldFlowAuthority { flow_id: FlowId },
#[operation(name = "promoteFlowReplica", kind = "mutation", response = FlowReplicaPromotedOutput, response_variant = "FlowReplicaPromoted")]
PromoteFlowReplica {
flow_id: FlowId,
acknowledgement: FlowYieldAcknowledgement,
},
#[operation(name = "finalizeFlowTransfer", kind = "mutation", response = FlowTransferFinalizedOutput, response_variant = "FlowTransferFinalized")]
FinalizeFlowTransfer { flow_id: FlowId },
}
#[aves::bus_responses]
#[derive(Clone, Debug, Deserialize, Serialize, Type, JsonSchema)]
pub enum FlowResponse {
SourceTriggersListed {
triggers: Vec<FlowTriggerRecord>,
},
RuntimeStarted,
RuntimeStopped,
FlowCreated {
flow: FlowDefinition,
},
WorkspaceImported {
root: ContentAddressedRoot,
},
ScriptSourceRead {
source: String,
},
ScriptSourceSaved {
stored: Option<ContentAddressedPath>,
},
FlowUpdated {
flow: FlowDefinition,
},
FlowRetrieved {
flow: FlowDefinition,
},
FlowsListed {
flows: Vec<FlowDefinition>,
},
FlowTriggersListed {
triggers: Vec<FlowTriggerRecord>,
},
FlowTriggerCreated {
trigger: FlowTriggerRecord,
},
FlowTriggerUpdated {
trigger: FlowTriggerRecord,
},
FlowTriggerDeleted {
#[specta(type = String)]
#[schemars(with = "String")]
trigger_id: Uuid,
},
FlowNodeCreated {
node: FlowNode,
},
FlowNodeUpdated {
node: FlowNode,
},
FlowNodeDeleted {
flow_id: FlowId,
node_id: FlowNodeId,
},
FlowDeleted {
flow_id: FlowId,
},
ActiveExecutionsListed {
executions: Vec<FlowExecutionSnapshot>,
},
TerminalExecutionsListed {
executions: Vec<FlowExecutionSnapshot>,
},
ExecutionDetailRetrieved {
detail: FlowExecutionDetail,
},
Started {
execution_id: FlowExecutionId,
},
Aborted {
execution_id: FlowExecutionId,
},
MobilityDestinationSelected {
flow_id: FlowId,
destination: FlowMobilityDestination,
},
FlowMobilityReadiness {
readiness: FlowMobilityReadiness,
},
FlowMobilityCommitAcknowledgement {
acknowledgement: FlowMobilityCommitAcknowledgement,
},
FlowAuthorityYielded {
acknowledgement: FlowYieldAcknowledgement,
},
FlowReplicaPromoted {
acknowledgement: FlowActivationAcknowledgement,
},
FlowTransferFinalized {
flow_id: FlowId,
},
RetentionUpdated,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub enum FlowBroadcast {
TriggersChanged,
DefinitionChanged { flow: Box<FlowDefinition> },
ExecutionStatusChanged {
flow_name: String,
snapshot: FlowExecutionSnapshot,
},
Ready { correlation: LifecycleCorrelation },
Failed {
correlation: LifecycleCorrelation,
failure: FlowFailure,
},
Succeeded { correlation: LifecycleCorrelation },
Started {
execution_id: FlowExecutionId,
flow_name: String,
},
Aborted { execution_id: FlowExecutionId },
}