#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct RemoteTriggerOccurrenceRequest {
pub protocol_version: u32,
pub source_type: String,
pub source_key: String,
#[serde(default)]
pub payload: serde_json::Value,
pub idempotency_key: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub source: Option<serde_json::Value>,
}
impl RemoteTriggerOccurrenceRequest {
pub fn new(
source_type: impl Into<String>,
source_key: impl Into<String>,
payload: serde_json::Value,
idempotency_key: impl Into<String>,
) -> Self {
Self {
protocol_version: REMOTE_PROTOCOL_VERSION,
source_type: source_type.into(),
source_key: source_key.into(),
payload,
idempotency_key: idempotency_key.into(),
source: None,
}
}
pub fn with_source(mut self, source: serde_json::Value) -> Self {
self.source = Some(source);
self
}
pub fn validate(&self) -> Result<(), RemoteProtocolError> {
ensure_protocol_version(self.protocol_version)?;
require_non_empty(
"RemoteTriggerOccurrenceRequest",
"source_type",
&self.source_type,
)?;
require_non_empty(
"RemoteTriggerOccurrenceRequest",
"source_key",
&self.source_key,
)?;
require_non_empty(
"RemoteTriggerOccurrenceRequest",
"idempotency_key",
&self.idempotency_key,
)
}
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct RemoteTriggerOccurrenceRecord {
pub occurrence_id: String,
pub source_type: String,
pub source_key: String,
#[serde(default)]
pub payload: serde_json::Value,
pub idempotency_key: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub source: Option<serde_json::Value>,
pub occurred_at_ms: u64,
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
pub struct RemoteTriggerEmitReport {
pub protocol_version: u32,
#[serde(default, skip_serializing_if = "String::is_empty")]
pub occurrence_id: String,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub started_process_ids: Vec<String>,
}
impl RemoteTriggerEmitReport {
pub fn validate(&self) -> Result<(), RemoteProtocolError> {
ensure_protocol_version(self.protocol_version)
}
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct RemoteTriggerSubscriptionFilter {
pub protocol_version: u32,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub session_id: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub handle: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub name: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub source_type: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub source_key: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub target: Option<RemoteProcessDefinitionIdentity>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub enabled: Option<bool>,
}
impl Default for RemoteTriggerSubscriptionFilter {
fn default() -> Self {
Self {
protocol_version: REMOTE_PROTOCOL_VERSION,
session_id: None,
handle: None,
name: None,
source_type: None,
source_key: None,
target: None,
enabled: None,
}
}
}
impl RemoteTriggerSubscriptionFilter {
pub fn for_session(session_id: impl Into<String>) -> Self {
Self {
protocol_version: REMOTE_PROTOCOL_VERSION,
session_id: Some(session_id.into()),
..Self::default()
}
}
pub fn for_source_type(source_type: impl Into<String>) -> Self {
Self {
protocol_version: REMOTE_PROTOCOL_VERSION,
source_type: Some(source_type.into()),
..Self::default()
}
}
pub fn validate(&self) -> Result<(), RemoteProtocolError> {
ensure_protocol_version(self.protocol_version)
}
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct RemoteTriggerRegistration {
pub handle: String,
pub source_key: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub name: Option<String>,
pub source_type: String,
#[serde(default)]
pub source: serde_json::Value,
pub target: RemoteTriggerTargetSummary,
#[serde(default = "default_true")]
pub enabled: bool,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct RemoteTriggerTargetSummary {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub label: Option<String>,
pub identity: RemoteProcessIdentity,
pub input: RemoteProcessInput,
#[serde(default)]
pub inputs: RemoteTriggerInputTemplate,
}
fn default_true() -> bool {
true
}
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize, JsonSchema)]
#[serde(transparent)]
pub struct RemoteTriggerInputTemplate {
pub entries: BTreeMap<String, RemoteTriggerInputBinding>,
}
impl RemoteTriggerInputTemplate {
pub fn new(entries: BTreeMap<String, RemoteTriggerInputBinding>) -> Self {
Self { entries }
}
pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
for name in self.entries.keys() {
require_non_empty(type_name, "input_template key", name)?;
}
Ok(())
}
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
#[serde(tag = "kind", rename_all = "snake_case")]
pub enum RemoteTriggerInputBinding {
Event,
Fixed { value: serde_json::Value },
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct RemoteTriggerSubscriptionDraft {
pub protocol_version: u32,
pub registrant: RemoteProcessOriginator,
pub env_ref: RemoteProcessExecutionEnvRef,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub wake_target: Option<RemoteSessionScope>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub name: Option<String>,
pub source_type: String,
pub source_key: String,
#[serde(default)]
pub source: serde_json::Value,
#[serde(default)]
pub payload_schema: serde_json::Value,
pub target: RemoteProcessInput,
pub target_identity: RemoteProcessIdentity,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub event_types: Vec<RemoteProcessEventType>,
#[serde(default)]
pub input_template: RemoteTriggerInputTemplate,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub target_label: Option<String>,
}
impl RemoteTriggerSubscriptionDraft {
pub fn for_process(
registrant: RemoteProcessOriginator,
env_ref: RemoteProcessExecutionEnvRef,
source_type: impl Into<String>,
source_key: impl Into<String>,
target: RemoteProcessInput,
target_identity: RemoteProcessIdentity,
) -> Self {
let target_label = target_identity.label.clone();
Self {
protocol_version: REMOTE_PROTOCOL_VERSION,
registrant,
env_ref,
wake_target: None,
name: None,
source_type: source_type.into(),
source_key: source_key.into(),
source: serde_json::Value::Object(serde_json::Map::new()),
payload_schema: serde_json::Value::Object(serde_json::Map::new()),
target,
target_identity,
event_types: Vec::new(),
input_template: RemoteTriggerInputTemplate::default(),
target_label,
}
}
pub fn with_name(mut self, name: impl Into<String>) -> Self {
self.name = Some(name.into());
self
}
pub fn with_source(mut self, source: serde_json::Value) -> Self {
self.source = source;
self
}
pub fn with_payload_schema(mut self, payload_schema: serde_json::Value) -> Self {
self.payload_schema = payload_schema;
self
}
pub fn with_wake_target(mut self, wake_target: RemoteSessionScope) -> Self {
self.wake_target = Some(wake_target);
self
}
pub fn with_event_types(
mut self,
event_types: impl IntoIterator<Item = RemoteProcessEventType>,
) -> Self {
self.event_types = event_types.into_iter().collect();
self
}
pub fn with_input_template(mut self, input_template: RemoteTriggerInputTemplate) -> Self {
self.input_template = input_template;
self
}
pub fn with_target_label(mut self, target_label: impl Into<String>) -> Self {
self.target_label = Some(target_label.into());
self
}
pub fn validate(&self) -> Result<(), RemoteProtocolError> {
ensure_protocol_version(self.protocol_version)?;
self.registrant.validate("RemoteTriggerSubscriptionDraft")?;
self.env_ref.validate("RemoteTriggerSubscriptionDraft")?;
if let Some(wake_target) = &self.wake_target {
wake_target.validate("RemoteTriggerSubscriptionDraft")?;
}
require_non_empty(
"RemoteTriggerSubscriptionDraft",
"source_type",
&self.source_type,
)?;
require_non_empty(
"RemoteTriggerSubscriptionDraft",
"source_key",
&self.source_key,
)?;
self.target.validate("RemoteTriggerSubscriptionDraft")?;
self.target_identity
.validate("RemoteTriggerSubscriptionDraft")?;
for event_type in &self.event_types {
event_type.validate("RemoteTriggerSubscriptionDraft")?;
}
validate_remote_trigger_target_label(
"RemoteTriggerSubscriptionDraft",
self.target_label.as_deref(),
self.target_identity.label.as_deref(),
)?;
self.input_template
.validate("RemoteTriggerSubscriptionDraft")
}
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct RemoteTriggerSubscriptionRecord {
pub subscription_id: String,
pub registrant: RemoteProcessOriginator,
pub env_ref: RemoteProcessExecutionEnvRef,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub wake_target: Option<RemoteSessionScope>,
pub handle: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub name: Option<String>,
pub source_type: String,
pub source_key: String,
#[serde(default)]
pub source: serde_json::Value,
#[serde(default)]
pub payload_schema: serde_json::Value,
pub target: RemoteProcessInput,
pub target_identity: RemoteProcessIdentity,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub event_types: Vec<RemoteProcessEventType>,
#[serde(default)]
pub input_template: RemoteTriggerInputTemplate,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub target_label: Option<String>,
#[serde(default = "default_true")]
pub enabled: bool,
pub created_at_ms: u64,
pub updated_at_ms: u64,
}
impl RemoteTriggerSubscriptionRecord {
pub fn validate(&self, type_name: &'static str) -> Result<(), RemoteProtocolError> {
require_non_empty(type_name, "subscription_id", &self.subscription_id)?;
self.registrant.validate(type_name)?;
self.env_ref.validate(type_name)?;
if let Some(wake_target) = &self.wake_target {
wake_target.validate(type_name)?;
}
require_non_empty(type_name, "handle", &self.handle)?;
require_non_empty(type_name, "source_type", &self.source_type)?;
require_non_empty(type_name, "source_key", &self.source_key)?;
self.target.validate(type_name)?;
self.target_identity.validate(type_name)?;
for event_type in &self.event_types {
event_type.validate(type_name)?;
}
validate_remote_trigger_target_label(
type_name,
self.target_label.as_deref(),
self.target_identity.label.as_deref(),
)?;
self.input_template.validate(type_name)
}
}
fn validate_remote_trigger_target_label(
type_name: &'static str,
target_label: Option<&str>,
identity_label: Option<&str>,
) -> Result<(), RemoteProtocolError> {
match (target_label, identity_label) {
(Some(target_label), Some(identity_label)) if target_label != identity_label => {
Err(RemoteProtocolError::InvalidEnvelope {
type_name,
message:
"target_label must match target_identity.label when both are present"
.to_string(),
})
}
_ => Ok(()),
}
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct RemoteTriggerRegisterSubscriptionRequest {
pub protocol_version: u32,
pub draft: RemoteTriggerSubscriptionDraft,
}
impl RemoteTriggerRegisterSubscriptionRequest {
pub fn validate(&self) -> Result<(), RemoteProtocolError> {
ensure_protocol_version(self.protocol_version)?;
if self.draft.protocol_version != self.protocol_version {
return Err(RemoteProtocolError::MismatchedNestedProtocolVersion {
parent: "RemoteTriggerRegisterSubscriptionRequest",
child: "draft",
parent_version: self.protocol_version,
child_version: self.draft.protocol_version,
});
}
self.draft.validate()
}
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct RemoteTriggerRegisterSubscriptionResult {
pub protocol_version: u32,
pub record: RemoteTriggerSubscriptionRecord,
}
impl RemoteTriggerRegisterSubscriptionResult {
pub fn validate(&self) -> Result<(), RemoteProtocolError> {
ensure_protocol_version(self.protocol_version)?;
self.record
.validate("RemoteTriggerRegisterSubscriptionResult")
}
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct RemoteTriggerListSubscriptionsResponse {
pub protocol_version: u32,
#[serde(default)]
pub subscriptions: Vec<RemoteTriggerSubscriptionRecord>,
}
impl RemoteTriggerListSubscriptionsResponse {
pub fn validate(&self) -> Result<(), RemoteProtocolError> {
ensure_protocol_version(self.protocol_version)?;
for record in &self.subscriptions {
record.validate("RemoteTriggerListSubscriptionsResponse")?;
}
Ok(())
}
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
pub struct RemoteTriggerCancelSubscriptionRequest {
pub protocol_version: u32,
pub session_id: String,
pub handle: String,
}
impl RemoteTriggerCancelSubscriptionRequest {
pub fn validate(&self) -> Result<(), RemoteProtocolError> {
ensure_protocol_version(self.protocol_version)?;
require_non_empty(
"RemoteTriggerCancelSubscriptionRequest",
"session_id",
&self.session_id,
)?;
require_non_empty(
"RemoteTriggerCancelSubscriptionRequest",
"handle",
&self.handle,
)
}
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
pub struct RemoteTriggerCancelSubscriptionResult {
pub protocol_version: u32,
pub session_id: String,
pub handle: String,
pub cancelled: bool,
}
impl RemoteTriggerCancelSubscriptionResult {
pub fn validate(&self) -> Result<(), RemoteProtocolError> {
ensure_protocol_version(self.protocol_version)?;
require_non_empty(
"RemoteTriggerCancelSubscriptionResult",
"session_id",
&self.session_id,
)?;
require_non_empty(
"RemoteTriggerCancelSubscriptionResult",
"handle",
&self.handle,
)
}
}