Files
ScadaBridge/src/ZB.MOM.WW.ScadaBridge.Communication/Protos/site_command.proto
T
Joseph Doherty a5256e9b12 chore(comm): delete dead IntegrationCallRequest routing (Gitea #32)
'Pattern 4: Integration Routing' — RouteIntegrationCallAsync →
SiteEnvelope(IntegrationCallRequest) → SiteCommunicationActor integration
handler — was plumbed end to end but connected at neither end: no
producer (zero callers) and no handler (AkkaHostedService never
registered LocalHandlerType.Integration). It was an early scaffold the
architecture routed around — the brokered External→Central→Site→Central
round-trip is served by the Inbound API's routed-site-script path (the
RouteTo* verbs, driven from CommunicationServiceInstanceRouter), which is
live, tested, and shares IntegrationTimeout.

Decision (#32): delete. Removed the IntegrationCall{Request,Response}
messages, RouteIntegrationCallAsync, the SiteCommunicationActor receive
block + _integrationHandler field + LocalHandlerType.Integration, and the
four tests that covered them (2 actor, 2 message-contract, 1 dispatcher-
reject, 1 mapper-reject). KEPT IntegrationTimeout — it is the live
timeout for the RouteTo* verbs. Updated the exclusion-narrative comments
(proto/mapper/dispatcher), design §4, the components doc timeout table,
and marked the known-issue RESOLVED.

Full solution build clean (0/0); Communication 634 + Host 421 green.
Net -172/+20 across 14 files. Not in the gRPC proto (was deliberately
excluded there), so no wire-format change.
2026-07-23 14:27:32 -04:00

854 lines
31 KiB
Protocol Buffer

syntax = "proto3";
option csharp_namespace = "ZB.MOM.WW.ScadaBridge.Communication.Grpc";
package scadabridge.sitecommand.v1;
import "google/protobuf/timestamp.proto";
import "google/protobuf/duration.proto";
import "google/protobuf/wrappers.proto";
// ─────────────────────────────────────────────────────────────────────────────
// Site command plane (central → site) — the gRPC replacement for the per-site
// ClusterClient command/control channel handled by SiteCommunicationActor.
//
// The 28 migrated commands are grouped into six domain RPCs rather than 28
// individual RPCs, because the grouping is what carries the DEADLINE policy:
// every command inside one group shares a timeout class today (see
// CommunicationOptions), so one RPC per group keeps the deadline choice in one
// place on the client and one dispatch switch on the server. A `oneof` request
// / reply envelope preserves per-command typing inside the group.
//
// EVOLUTION RULE (same as sitestream.proto): field numbers are never reused and
// changes are additive only. New commands take the next free oneof tag; an
// older peer simply sees an unset oneof and answers with a clean error.
//
// The generated C# is CHECKED IN under Communication/SiteCommandGrpc/ because
// protoc segfaults inside the linux_arm64 Docker build image. Regenerate with
// docker/regen-proto.sh (or by hand per the recipe in the .csproj) — never by
// leaving an active <Protobuf> item in the project file.
// ─────────────────────────────────────────────────────────────────────────────
service SiteCommandService {
// Deployment + instance lifecycle (6 commands).
rpc ExecuteLifecycle(LifecycleRequest) returns (LifecycleReply);
// Interactive OPC UA / MxGateway design-time commands (8 commands).
rpc ExecuteOpcUa(OpcUaRequest) returns (OpcUaReply);
// Remote read-only queries: event log + debug view (4 commands).
rpc ExecuteQuery(QueryRequest) returns (QueryReply);
// Parked store-and-forward message + cached-operation actions (5 commands).
rpc ExecuteParked(ParkedRequest) returns (ParkedReply);
// Inbound-API Route.To() relays (4 commands).
rpc ExecuteRoute(RouteRequest) returns (RouteReply);
// Operator-initiated manual site-pair failover (1 command).
rpc TriggerFailover(TriggerSiteFailoverDto) returns (SiteFailoverAckDto);
}
// ─────────────────────────────────────────────────────────────────────────────
// Shared value carrier
// ─────────────────────────────────────────────────────────────────────────────
// Explicit null marker. Needed because a map<string, LooseValue> entry always
// has a value message present, so "the dictionary holds a null for this key"
// cannot be expressed by absence the way a nullable message FIELD can.
message LooseNull {}
message LooseValueList { repeated LooseValue items = 1; }
message LooseValueMap { map<string, LooseValue> entries = 1; }
// Type-tagged carrier for the `object?` members the command plane still uses
// (script parameters and return values, attribute values, tag read/write
// values). The tags cover every CLR type these fields actually carry, so those
// values round-trip with their runtime type intact; anything else falls back to
// `json_value` (see the mapper's documented lossiness note).
//
// Date/time and decimal ride as invariant round-trip STRINGS rather than
// google.protobuf.Timestamp: Timestamp normalises everything to UTC and would
// silently drop DateTime.Kind / DateTimeOffset.Offset, which for an operator's
// tag value is data loss, not normalisation.
message LooseValue {
oneof kind {
LooseNull null_value = 1;
bool bool_value = 2;
int32 int32_value = 3;
int64 int64_value = 4;
double double_value = 5;
float float_value = 6;
string string_value = 7;
string decimal_value = 8; // invariant-culture round-trip
string date_time_value = 9; // DateTime, "O" (preserves Kind)
string date_time_offset_value = 10; // DateTimeOffset, "O" (preserves Offset)
string guid_value = 11; // "D"
string time_span_value = 12; // "c" (constant/round-trip)
bytes bytes_value = 13;
LooseValueList list_value = 14;
LooseValueMap map_value = 15;
string json_value = 16; // fallback; decodes to JsonElement
}
}
// ─────────────────────────────────────────────────────────────────────────────
// Enums. Every enum reserves 0 for _UNSPECIFIED so a value that is absent on
// the wire is never mistaken for the first CLR member. The mapper translates
// explicitly in both directions (never by ordinal), so reordering a C# enum
// cannot silently re-map the wire.
// ─────────────────────────────────────────────────────────────────────────────
enum DeploymentStatusDto {
DEPLOYMENT_STATUS_DTO_UNSPECIFIED = 0;
DEPLOYMENT_STATUS_DTO_PENDING = 1;
DEPLOYMENT_STATUS_DTO_IN_PROGRESS = 2;
DEPLOYMENT_STATUS_DTO_SUCCESS = 3;
DEPLOYMENT_STATUS_DTO_FAILED = 4;
}
enum BrowseNodeClassDto {
BROWSE_NODE_CLASS_DTO_UNSPECIFIED = 0;
BROWSE_NODE_CLASS_DTO_OBJECT = 1;
BROWSE_NODE_CLASS_DTO_VARIABLE = 2;
BROWSE_NODE_CLASS_DTO_METHOD = 3;
BROWSE_NODE_CLASS_DTO_OTHER = 4;
}
enum BrowseFailureKindDto {
BROWSE_FAILURE_KIND_DTO_UNSPECIFIED = 0;
BROWSE_FAILURE_KIND_DTO_CONNECTION_NOT_FOUND = 1;
BROWSE_FAILURE_KIND_DTO_CONNECTION_NOT_CONNECTED = 2;
BROWSE_FAILURE_KIND_DTO_NOT_BROWSABLE = 3;
BROWSE_FAILURE_KIND_DTO_TIMEOUT = 4;
BROWSE_FAILURE_KIND_DTO_SERVER_ERROR = 5;
}
enum ReadTagValuesFailureKindDto {
READ_TAG_VALUES_FAILURE_KIND_DTO_UNSPECIFIED = 0;
READ_TAG_VALUES_FAILURE_KIND_DTO_CONNECTION_NOT_FOUND = 1;
READ_TAG_VALUES_FAILURE_KIND_DTO_CONNECTION_NOT_CONNECTED = 2;
READ_TAG_VALUES_FAILURE_KIND_DTO_TIMEOUT = 3;
READ_TAG_VALUES_FAILURE_KIND_DTO_SERVER_ERROR = 4;
}
enum VerifyFailureKindDto {
VERIFY_FAILURE_KIND_DTO_UNSPECIFIED = 0;
VERIFY_FAILURE_KIND_DTO_UNREACHABLE = 1;
VERIFY_FAILURE_KIND_DTO_AUTH_FAILED = 2;
VERIFY_FAILURE_KIND_DTO_UNTRUSTED_CERTIFICATE = 3;
VERIFY_FAILURE_KIND_DTO_TIMEOUT = 4;
VERIFY_FAILURE_KIND_DTO_SERVER_ERROR = 5;
}
enum StoreAndForwardCategoryDto {
STORE_AND_FORWARD_CATEGORY_DTO_UNSPECIFIED = 0;
STORE_AND_FORWARD_CATEGORY_DTO_EXTERNAL_SYSTEM = 1;
STORE_AND_FORWARD_CATEGORY_DTO_NOTIFICATION = 2;
STORE_AND_FORWARD_CATEGORY_DTO_CACHED_DB_WRITE = 3;
}
enum AlarmStateDto {
ALARM_STATE_DTO_UNSPECIFIED = 0;
ALARM_STATE_DTO_ACTIVE = 1;
ALARM_STATE_DTO_NORMAL = 2;
}
enum AlarmLevelDto {
ALARM_LEVEL_DTO_UNSPECIFIED = 0;
ALARM_LEVEL_DTO_NONE = 1;
ALARM_LEVEL_DTO_LOW = 2;
ALARM_LEVEL_DTO_LOW_LOW = 3;
ALARM_LEVEL_DTO_HIGH = 4;
ALARM_LEVEL_DTO_HIGH_HIGH = 5;
}
enum AlarmKindDto {
ALARM_KIND_DTO_UNSPECIFIED = 0;
ALARM_KIND_DTO_COMPUTED = 1;
ALARM_KIND_DTO_NATIVE_OPC_UA = 2;
ALARM_KIND_DTO_NATIVE_MX_ACCESS = 3;
}
enum AlarmShelveStateDto {
ALARM_SHELVE_STATE_DTO_UNSPECIFIED = 0;
ALARM_SHELVE_STATE_DTO_UNSHELVED = 1;
ALARM_SHELVE_STATE_DTO_ONE_SHOT_SHELVED = 2;
ALARM_SHELVE_STATE_DTO_TIMED_SHELVED = 3;
ALARM_SHELVE_STATE_DTO_PERMANENT_SHELVED = 4;
}
// ─────────────────────────────────────────────────────────────────────────────
// RPC 1 — ExecuteLifecycle
// ─────────────────────────────────────────────────────────────────────────────
message RefreshDeploymentCommandDto {
string deployment_id = 1;
string instance_unique_name = 2;
string revision_hash = 3;
string deployed_by = 4;
google.protobuf.Timestamp timestamp = 5;
string central_fetch_base_url = 6;
string fetch_token = 7;
}
message EnableInstanceCommandDto {
string command_id = 1;
string instance_unique_name = 2;
google.protobuf.Timestamp timestamp = 3;
}
message DisableInstanceCommandDto {
string command_id = 1;
string instance_unique_name = 2;
google.protobuf.Timestamp timestamp = 3;
}
message DeleteInstanceCommandDto {
string command_id = 1;
string instance_unique_name = 2;
google.protobuf.Timestamp timestamp = 3;
}
message DeploymentStateQueryRequestDto {
string correlation_id = 1;
string instance_unique_name = 2;
google.protobuf.Timestamp timestamp = 3;
}
message SharedScriptArtifactDto {
string name = 1;
string code = 2;
string parameter_definitions = 3; // empty string represents null
string return_definition = 4; // empty string represents null
}
message ExternalSystemArtifactDto {
string name = 1;
string endpoint_url = 2;
string auth_type = 3;
string auth_configuration = 4; // empty string represents null
string method_definitions_json = 5; // empty string represents null
int32 timeout_seconds = 6;
}
message DatabaseConnectionArtifactDto {
string name = 1;
string connection_string = 2;
int32 max_retries = 3;
google.protobuf.Duration retry_delay = 4;
}
message NotificationListArtifactDto {
string name = 1;
repeated string recipient_emails = 2;
}
message DataConnectionArtifactDto {
string name = 1;
string protocol = 2;
string primary_configuration_json = 3; // empty string represents null
string backup_configuration_json = 4; // empty string represents null
int32 failover_retry_count = 5;
}
message SmtpConfigurationArtifactDto {
string name = 1;
string server = 2;
int32 port = 3;
string auth_mode = 4;
string from_address = 5;
string username = 6; // empty string represents null
string password = 7; // empty string represents null
string oauth_config = 8; // empty string represents null
}
// Each artifact collection on DeployArtifactsCommand is a NULLABLE list, and
// proto3 `repeated` cannot distinguish null from empty. Wrapping each in its
// own message makes the null/empty distinction a message-presence question,
// which proto3 does model — the same silent-data-loss class the transport
// round-trip guard caught in PLAN-05 T8.
message SharedScriptArtifactListDto { repeated SharedScriptArtifactDto items = 1; }
message ExternalSystemArtifactListDto { repeated ExternalSystemArtifactDto items = 1; }
message DatabaseConnectionArtifactListDto { repeated DatabaseConnectionArtifactDto items = 1; }
message NotificationListArtifactListDto { repeated NotificationListArtifactDto items = 1; }
message DataConnectionArtifactListDto { repeated DataConnectionArtifactDto items = 1; }
message SmtpConfigurationArtifactListDto { repeated SmtpConfigurationArtifactDto items = 1; }
message DeployArtifactsCommandDto {
string deployment_id = 1;
SharedScriptArtifactListDto shared_scripts = 2; // absent => null
ExternalSystemArtifactListDto external_systems = 3; // absent => null
DatabaseConnectionArtifactListDto database_connections = 4; // absent => null
NotificationListArtifactListDto notification_lists = 5; // absent => null
DataConnectionArtifactListDto data_connections = 6; // absent => null
SmtpConfigurationArtifactListDto smtp_configurations = 7; // absent => null
google.protobuf.Timestamp timestamp = 8;
}
message DeploymentStatusResponseDto {
string deployment_id = 1;
string instance_unique_name = 2;
DeploymentStatusDto status = 3;
string error_message = 4; // empty string represents null
google.protobuf.Timestamp timestamp = 5;
}
message InstanceLifecycleResponseDto {
string command_id = 1;
string instance_unique_name = 2;
bool success = 3;
string error_message = 4; // empty string represents null
google.protobuf.Timestamp timestamp = 5;
}
message DeploymentStateQueryResponseDto {
string correlation_id = 1;
string instance_unique_name = 2;
bool is_deployed = 3;
string applied_deployment_id = 4; // empty string represents null
string applied_revision_hash = 5; // empty string represents null
google.protobuf.Timestamp timestamp = 6;
}
message ArtifactDeploymentResponseDto {
string deployment_id = 1;
string site_id = 2;
bool success = 3;
string error_message = 4; // empty string represents null
google.protobuf.Timestamp timestamp = 5;
}
message LifecycleRequest {
oneof command {
RefreshDeploymentCommandDto refresh_deployment = 1;
EnableInstanceCommandDto enable_instance = 2;
DisableInstanceCommandDto disable_instance = 3;
DeleteInstanceCommandDto delete_instance = 4;
DeploymentStateQueryRequestDto deployment_state_query = 5;
DeployArtifactsCommandDto deploy_artifacts = 6;
}
}
message LifecycleReply {
oneof reply {
DeploymentStatusResponseDto deployment_status = 1;
InstanceLifecycleResponseDto instance_lifecycle = 2;
DeploymentStateQueryResponseDto deployment_state_query = 3;
ArtifactDeploymentResponseDto artifact_deployment = 4;
}
}
// ─────────────────────────────────────────────────────────────────────────────
// RPC 2 — ExecuteOpcUa
// ─────────────────────────────────────────────────────────────────────────────
message BrowseNodeCommandDto {
string connection_name = 1;
string parent_node_id = 2; // empty string represents null (browse root)
string continuation_token = 3; // empty string represents null (first page)
string site_identifier = 4; // empty string represents null
}
message BrowseNodeDto {
string node_id = 1;
string display_name = 2;
BrowseNodeClassDto node_class = 3;
bool has_children = 4;
string data_type = 5; // empty string represents null
google.protobuf.Int32Value value_rank = 6; // absent => null
google.protobuf.BoolValue writable = 7; // absent => null
}
message BrowseFailureDto {
BrowseFailureKindDto kind = 1;
string message = 2;
}
message BrowseNodeResultDto {
repeated BrowseNodeDto children = 1;
bool truncated = 2;
BrowseFailureDto failure = 3; // absent => null (success)
string continuation_token = 4; // empty string represents null (final page)
}
message SearchAddressSpaceCommandDto {
string connection_name = 1;
string query = 2;
int32 max_depth = 3;
int32 max_results = 4;
string site_identifier = 5; // empty string represents null
}
message AddressSpaceMatchDto {
BrowseNodeDto node = 1;
string path = 2;
}
message SearchAddressSpaceResultDto {
repeated AddressSpaceMatchDto matches = 1;
bool cap_reached = 2;
BrowseFailureDto failure = 3; // absent => null (success)
}
message ReadTagValuesCommandDto {
string connection_name = 1;
repeated string tag_paths = 2;
}
message TagReadOutcomeDto {
string tag_path = 1;
bool success = 2;
LooseValue value = 3; // absent => null
string quality = 4;
google.protobuf.Timestamp timestamp = 5;
string error_message = 6; // empty string represents null
}
message ReadTagValuesFailureDto {
ReadTagValuesFailureKindDto kind = 1;
string message = 2;
}
message ReadTagValuesResultDto {
repeated TagReadOutcomeDto outcomes = 1;
ReadTagValuesFailureDto failure = 2; // absent => null (success)
}
message VerifyEndpointCommandDto {
string connection_name = 1;
string protocol = 2;
string config_json = 3;
string site_identifier = 4; // empty string represents null
}
message ServerCertInfoDto {
string thumbprint = 1;
string subject = 2;
string issuer = 3;
google.protobuf.Timestamp not_before_utc = 4;
google.protobuf.Timestamp not_after_utc = 5;
string der_base64 = 6;
}
// failure_kind is a NULLABLE enum on the CLR side, and proto3 enums have no
// presence, so it rides inside a one-field message exactly like Int32Value.
message VerifyFailureKindValue { VerifyFailureKindDto value = 1; }
message VerifyEndpointResultDto {
bool success = 1;
VerifyFailureKindValue failure_kind = 2; // absent => null (success)
string error = 3; // empty string represents null
ServerCertInfoDto cert = 4; // absent => null
}
message TrustServerCertCommandDto {
string connection_name = 1;
string der_base64 = 2;
string thumbprint = 3;
string site_identifier = 4; // empty string represents null
}
message ListServerCertsCommandDto {
string site_identifier = 1; // empty string represents null
}
message RemoveServerCertCommandDto {
string thumbprint = 1;
string site_identifier = 2; // empty string represents null
}
message TrustedCertInfoDto {
string thumbprint = 1;
string subject = 2;
string issuer = 3;
google.protobuf.Timestamp not_before_utc = 4;
google.protobuf.Timestamp not_after_utc = 5;
bool rejected = 6;
}
// CertTrustResult.Certs is a nullable list (null for trust/remove, populated
// for list) — same null-vs-empty problem as the artifact collections.
message TrustedCertInfoListDto { repeated TrustedCertInfoDto items = 1; }
message CertTrustResultDto {
bool success = 1;
string error = 2; // empty string represents null
TrustedCertInfoListDto certs = 3; // absent => null
}
message WriteTagRequestDto {
string correlation_id = 1;
string connection_name = 2;
string tag_path = 3;
LooseValue value = 4; // absent => null
google.protobuf.Timestamp timestamp = 5;
}
message WriteTagResponseDto {
string correlation_id = 1;
bool success = 2;
string error_message = 3; // empty string represents null
google.protobuf.Timestamp timestamp = 4;
}
message OpcUaRequest {
oneof command {
BrowseNodeCommandDto browse_node = 1;
SearchAddressSpaceCommandDto search_address_space = 2;
ReadTagValuesCommandDto read_tag_values = 3;
VerifyEndpointCommandDto verify_endpoint = 4;
TrustServerCertCommandDto trust_server_cert = 5;
ListServerCertsCommandDto list_server_certs = 6;
RemoveServerCertCommandDto remove_server_cert = 7;
WriteTagRequestDto write_tag = 8;
}
}
message OpcUaReply {
oneof reply {
BrowseNodeResultDto browse_node = 1;
SearchAddressSpaceResultDto search_address_space = 2;
ReadTagValuesResultDto read_tag_values = 3;
VerifyEndpointResultDto verify_endpoint = 4;
CertTrustResultDto cert_trust = 5;
WriteTagResponseDto write_tag = 6;
}
}
// ─────────────────────────────────────────────────────────────────────────────
// RPC 3 — ExecuteQuery
// ─────────────────────────────────────────────────────────────────────────────
message EventLogQueryRequestDto {
string correlation_id = 1;
string site_id = 2;
google.protobuf.Timestamp from = 3; // absent => null
google.protobuf.Timestamp to = 4; // absent => null
string event_type = 5; // empty string represents null
string severity = 6; // empty string represents null
string instance_id = 7; // empty string represents null
string keyword_filter = 8; // empty string represents null
string continuation_token = 9; // empty string represents null
int32 page_size = 10;
google.protobuf.Timestamp timestamp = 11;
}
message EventLogEntryDto {
string id = 1;
google.protobuf.Timestamp timestamp = 2;
string event_type = 3;
string severity = 4;
string instance_id = 5; // empty string represents null
string source = 6;
string message = 7;
string details = 8; // empty string represents null
}
message EventLogQueryResponseDto {
string correlation_id = 1;
string site_id = 2;
repeated EventLogEntryDto entries = 3;
string continuation_token = 4; // empty string represents null
bool has_more = 5;
bool success = 6;
string error_message = 7; // empty string represents null
google.protobuf.Timestamp timestamp = 8;
}
message DebugSnapshotRequestDto {
string instance_unique_name = 1;
string correlation_id = 2;
}
message SubscribeDebugViewRequestDto {
string instance_unique_name = 1;
string correlation_id = 2;
}
message UnsubscribeDebugViewRequestDto {
string instance_unique_name = 1;
string correlation_id = 2;
}
// UnsubscribeDebugView is a Tell today (CommunicationService.UnsubscribeDebugView
// fires and forgets). A unary RPC must still answer something, so the site sends
// this empty ack; the central transport ignores it to keep the caller-visible
// fire-and-forget semantics identical.
message UnsubscribeDebugViewAckDto {}
message AlarmConditionStateDto {
bool active = 1;
bool acknowledged = 2;
google.protobuf.BoolValue confirmed = 3; // absent => null (not confirmable)
AlarmShelveStateDto shelve = 4;
bool suppressed = 5;
int32 severity = 6;
}
message DebugAttributeValueDto {
string instance_unique_name = 1;
string attribute_path = 2;
string attribute_name = 3;
LooseValue value = 4; // absent => null
string quality = 5;
google.protobuf.Timestamp timestamp = 6;
}
// Full-fidelity projection of Commons AlarmStateChanged. Deliberately NOT the
// sitestream AlarmStateUpdate: that one flattens the value to a display string
// and the shelve state to free text, which is right for a live stream but would
// lose data on a snapshot the central UI renders as authoritative state.
message DebugAlarmStateDto {
string instance_unique_name = 1;
string alarm_name = 2;
AlarmStateDto state = 3;
int32 priority = 4;
google.protobuf.Timestamp timestamp = 5;
AlarmLevelDto level = 6;
string message = 7;
AlarmKindDto kind = 8;
// Absent means "not explicitly set" — the CLR record then derives the
// computed default from state + priority. See the mapper's note on why the
// encoder omits a condition that already equals that derived default.
AlarmConditionStateDto condition = 9;
string source_reference = 10;
string alarm_type_name = 11;
string category = 12;
string operator_user = 13;
string operator_comment = 14;
google.protobuf.Timestamp original_raise_time = 15; // absent => null
string current_value = 16;
string limit_value = 17;
string native_source_canonical_name = 18;
bool is_configured_placeholder = 19;
}
message DebugViewSnapshotDto {
string instance_unique_name = 1;
repeated DebugAttributeValueDto attribute_values = 2;
repeated DebugAlarmStateDto alarm_states = 3;
google.protobuf.Timestamp snapshot_timestamp = 4;
bool instance_not_found = 5;
}
message QueryRequest {
oneof command {
EventLogQueryRequestDto event_log_query = 1;
DebugSnapshotRequestDto debug_snapshot = 2;
SubscribeDebugViewRequestDto subscribe_debug_view = 3;
UnsubscribeDebugViewRequestDto unsubscribe_debug_view = 4;
}
}
message QueryReply {
oneof reply {
EventLogQueryResponseDto event_log_query = 1;
DebugViewSnapshotDto debug_view_snapshot = 2;
UnsubscribeDebugViewAckDto unsubscribe_debug_view = 3;
}
}
// ─────────────────────────────────────────────────────────────────────────────
// RPC 4 — ExecuteParked
// ─────────────────────────────────────────────────────────────────────────────
message ParkedMessageQueryRequestDto {
string correlation_id = 1;
string site_id = 2;
int32 page_number = 3;
int32 page_size = 4;
google.protobuf.Timestamp timestamp = 5;
}
message ParkedMessageEntryDto {
string message_id = 1;
string target_system = 2;
string method_name = 3;
string error_message = 4;
int32 attempt_count = 5;
google.protobuf.Timestamp original_timestamp = 6;
google.protobuf.Timestamp last_attempt_timestamp = 7;
int32 max_attempts = 8;
StoreAndForwardCategoryDto category = 9;
string origin_instance = 10; // empty string represents null
}
message ParkedMessageQueryResponseDto {
string correlation_id = 1;
string site_id = 2;
repeated ParkedMessageEntryDto messages = 3;
int32 total_count = 4;
int32 page_number = 5;
int32 page_size = 6;
bool success = 7;
string error_message = 8; // empty string represents null
google.protobuf.Timestamp timestamp = 9;
}
message ParkedMessageRetryRequestDto {
string correlation_id = 1;
string site_id = 2;
string message_id = 3;
google.protobuf.Timestamp timestamp = 4;
}
message ParkedMessageRetryResponseDto {
string correlation_id = 1;
bool success = 2;
string error_message = 3; // empty string represents null
}
message ParkedMessageDiscardRequestDto {
string correlation_id = 1;
string site_id = 2;
string message_id = 3;
google.protobuf.Timestamp timestamp = 4;
}
message ParkedMessageDiscardResponseDto {
string correlation_id = 1;
bool success = 2;
string error_message = 3; // empty string represents null
}
message RetryParkedOperationDto {
string correlation_id = 1;
string tracked_operation_id = 2; // TrackedOperationId GUID, "D" format
}
message DiscardParkedOperationDto {
string correlation_id = 1;
string tracked_operation_id = 2; // TrackedOperationId GUID, "D" format
}
message ParkedOperationActionAckDto {
string correlation_id = 1;
bool applied = 2;
string error_message = 3; // empty string represents null
}
message ParkedRequest {
oneof command {
ParkedMessageQueryRequestDto parked_message_query = 1;
ParkedMessageRetryRequestDto parked_message_retry = 2;
ParkedMessageDiscardRequestDto parked_message_discard = 3;
RetryParkedOperationDto retry_parked_operation = 4;
DiscardParkedOperationDto discard_parked_operation = 5;
}
}
message ParkedReply {
oneof reply {
ParkedMessageQueryResponseDto parked_message_query = 1;
ParkedMessageRetryResponseDto parked_message_retry = 2;
ParkedMessageDiscardResponseDto parked_message_discard = 3;
ParkedOperationActionAckDto parked_operation_action = 4;
}
}
// ─────────────────────────────────────────────────────────────────────────────
// RPC 5 — ExecuteRoute
// ─────────────────────────────────────────────────────────────────────────────
message RouteToCallRequestDto {
string correlation_id = 1;
string instance_unique_name = 2;
string script_name = 3;
LooseValueMap parameters = 4; // absent => null (distinct from empty)
google.protobuf.Timestamp timestamp = 5;
string parent_execution_id = 6; // empty string represents null
}
message RouteToCallResponseDto {
string correlation_id = 1;
bool success = 2;
LooseValue return_value = 3; // absent => null
string error_message = 4; // empty string represents null
google.protobuf.Timestamp timestamp = 5;
}
message RouteToGetAttributesRequestDto {
string correlation_id = 1;
string instance_unique_name = 2;
repeated string attribute_names = 3;
google.protobuf.Timestamp timestamp = 4;
string parent_execution_id = 5; // empty string represents null
}
message RouteToGetAttributesResponseDto {
string correlation_id = 1;
LooseValueMap values = 2; // non-nullable on the CLR side; absent => empty
bool success = 3;
string error_message = 4; // empty string represents null
google.protobuf.Timestamp timestamp = 5;
}
message RouteToSetAttributesRequestDto {
string correlation_id = 1;
string instance_unique_name = 2;
map<string, string> attribute_values = 3;
google.protobuf.Timestamp timestamp = 4;
string parent_execution_id = 5; // empty string represents null
}
message RouteToSetAttributesResponseDto {
string correlation_id = 1;
bool success = 2;
string error_message = 3; // empty string represents null
google.protobuf.Timestamp timestamp = 4;
}
message RouteToWaitForAttributeRequestDto {
string correlation_id = 1;
string instance_unique_name = 2;
string attribute_name = 3;
// NOT the empty-string-means-null convention: "wait for this attribute to
// become the empty string" is a legitimate target that must stay distinct
// from "no target supplied", so this one nullable string rides a wrapper.
google.protobuf.StringValue target_value_encoded = 4;
google.protobuf.Duration timeout = 5;
google.protobuf.Timestamp timestamp = 6;
string parent_execution_id = 7; // empty string represents null
bool require_good_quality = 8;
}
message RouteToWaitForAttributeResponseDto {
string correlation_id = 1;
bool matched = 2;
LooseValue value = 3; // absent => null
string quality = 4; // empty string represents null
bool timed_out = 5;
bool success = 6;
string error_message = 7; // empty string represents null
google.protobuf.Timestamp timestamp = 8;
}
message RouteRequest {
oneof command {
RouteToCallRequestDto route_to_call = 1;
RouteToGetAttributesRequestDto route_to_get_attributes = 2;
RouteToSetAttributesRequestDto route_to_set_attributes = 3;
RouteToWaitForAttributeRequestDto route_to_wait_for_attribute = 4;
}
}
message RouteReply {
oneof reply {
RouteToCallResponseDto route_to_call = 1;
RouteToGetAttributesResponseDto route_to_get_attributes = 2;
RouteToSetAttributesResponseDto route_to_set_attributes = 3;
RouteToWaitForAttributeResponseDto route_to_wait_for_attribute = 4;
}
}
// ─────────────────────────────────────────────────────────────────────────────
// RPC 6 — TriggerFailover
// ─────────────────────────────────────────────────────────────────────────────
message TriggerSiteFailoverDto {
string correlation_id = 1;
string site_id = 2;
}
message SiteFailoverAckDto {
string correlation_id = 1;
bool accepted = 2;
string target_address = 3; // empty string represents null
string error_message = 4; // empty string represents null
}