syntax = "proto3"; package bldr.plugin; import "github.com/s4wave/spacewave/bldr/manifest/manifest.proto"; import "github.com/aperturerobotics/controllerbus/controller/exec/exec.proto"; import "github.com/s4wave/spacewave/db/volume/volume.proto"; import "github.com/aperturerobotics/starpc/rpcstream/rpcstream.proto"; import "google/protobuf/timestamp.proto"; // PluginState is the scheduler state for a plugin instance. enum PluginState { // PluginState_UNKNOWN indicates the scheduler has no state yet. PluginState_UNKNOWN = 0; // PluginState_REQUESTED indicates the plugin has an active reference but no RPC client yet. PluginState_REQUESTED = 1; // PluginState_RUNNING indicates the plugin RPC client is ready. PluginState_RUNNING = 2; } // PluginStatus holds basic status for a plugin. message PluginStatus { // PluginId is the plugin identifier. string plugin_id = 1; // Running indicates the plugin is running. bool running = 2; // InstanceKey is the optional instance key for instanced plugins. string instance_key = 3; // State is the scheduler state for this plugin instance. PluginState state = 4; // LastErrorMessage is the most recent plugin execution error summary. string last_error_message = 5; // LastErrorAt is when LastErrorMessage was recorded. google.protobuf.Timestamp last_error_at = 6; } // PluginManifestRecoveryStatus describes the retained Manifest selection and // eligibility facts for one plugin instance. message PluginManifestRecoveryStatus { // PluginId is the plugin identifier. string plugin_id = 1; // InstanceKey is the optional instance key for instanced plugins. string instance_key = 2; // ExecuteManifestRef is the ref of the manifest selected for execution. string execute_manifest_ref = 3; // DownloadManifestRef is the ref of the manifest selected for download. string download_manifest_ref = 4; // SkippedCandidateCount is how many candidates were skipped. uint32 skipped_candidate_count = 5; // SkippedCandidateSummary summarizes the skipped candidates. string skipped_candidate_summary = 6; // IgnoredCandidateCount is how many candidates were ignored. uint32 ignored_candidate_count = 7; // IgnoredCandidateSummary summarizes the ignored candidates. string ignored_candidate_summary = 8; // QuarantinedCandidateCount is how many candidates were quarantined. uint32 quarantined_candidate_count = 9; // QuarantinedCandidateSummary summarizes the quarantined candidates. string quarantined_candidate_summary = 10; } // PluginStatusSnapshot describes a plugin host scheduler's plugin instances. message PluginStatusSnapshot { // Plugins lists the per-instance statuses sorted by plugin id and instance key. repeated PluginStatus plugins = 1; // ManifestRecovery lists the per-instance manifest selection facts sorted by // plugin id and instance key. repeated PluginManifestRecoveryStatus manifest_recovery = 2; } // PluginHost is the service exposed by the plugin host. // // Available at service ID plugin-host. service PluginHost { // GetPluginInfo returns the information for the current plugin. rpc GetPluginInfo(GetPluginInfoRequest) returns (GetPluginInfoResponse) {}; // ExecController executes a controller configuration on the bus. rpc ExecController(.controller.exec.ExecControllerRequest) returns (stream .controller.exec.ExecControllerResponse) {} // LoadPlugin requests to load the plugin with the given ID. // The plugin will remain loaded as long as the RPC is active. // Multiple requests to load the same plugin are de-duplicated. rpc LoadPlugin(LoadPluginRequest) returns (stream LoadPluginResponse) {}; // PluginRpc forwards an RPC call to a remote plugin. // The plugin will remain loaded as long as the RPC is active. // Component ID: plugin id, or plugin id / instance key for instanced plugins. rpc PluginRpc(stream .rpcstream.RpcStreamPacket) returns (stream .rpcstream.RpcStreamPacket); // PluginFsRpc accesses a FSCursorService to access plugin assets or dist filesystems. // The plugin will remain loaded as long as the RPC is active. // Component ID: plugin-assets or plugin-dist for current plugin // Component ID: plugin-assets/{plugin-id} or plugin-dist/{plugin-id} for remote plugin rpc PluginFsRpc(stream .rpcstream.RpcStreamPacket) returns (stream .rpcstream.RpcStreamPacket); // WatchPluginStatus streams the host scheduler's plugin status. // Sends the current snapshot, then each change. rpc WatchPluginStatus(WatchPluginStatusRequest) returns (stream WatchPluginStatusResponse); } // Plugin is the service exposed by the plugin. service Plugin { // PluginRpc handles an RPC call from a remote plugin. // Component ID: remote plugin id rpc PluginRpc(stream .rpcstream.RpcStreamPacket) returns (stream .rpcstream.RpcStreamPacket); } // UpdateGuard is implemented by plugins whose owned work must quiesce before // replacement. Hosts call it only for explicitly configured guarded plugins. service UpdateGuard { // Prepare waits for owned work to finish and prevents new work from starting. // Success authorizes replacement of this plugin generation. rpc Prepare(PrepareUpdateRequest) returns (PrepareUpdateResponse) {} } // Activation is implemented by plugins that stage their complete registration // set before the scheduler replaces an already running generation. service Activation { // Check confirms support for private startup and atomic registration admission. rpc Check(CheckActivationRequest) returns (CheckActivationResponse); // Activate admits this worker's prepared registrations after startup succeeds. rpc Activate(ActivatePluginRequest) returns (ActivatePluginResponse); } // CheckActivationRequest queries the running generation's replacement contract. message CheckActivationRequest { } // CheckActivationResponse confirms support for staged replacement. message CheckActivationResponse { } // ActivatePluginRequest asks a ready candidate to become the current generation. message ActivatePluginRequest { } // ActivatePluginResponse confirms admission of the complete registration set. message ActivatePluginResponse { } // PrepareUpdateRequest asks the current generation to relinquish its work. message PrepareUpdateRequest { } // PrepareUpdateResponse confirms the generation is ready for replacement. message PrepareUpdateResponse { } // WatchPluginStatusRequest is the request for WatchPluginStatus. message WatchPluginStatusRequest { } // WatchPluginStatusResponse is one plugin status update from the host. message WatchPluginStatusResponse { // InstanceKey is the instance key the host scheduler was configured with. string instance_key = 1; // Status is the scheduler's current plugin status snapshot. PluginStatusSnapshot status = 2; } // GetPluginInfoRequest is a request to return the information for the current plugin. message GetPluginInfoRequest { } // GetPluginInfoResponse is the response to the GetPluginInfo request. message GetPluginInfoResponse { // PluginId is the plugin identifier. string plugin_id = 1; // ManifestRef is the reference to the Manifest object. .bldr.manifest.ManifestRef manifest_ref = 2; // HostVolumeInfo is the optional information for the host Volume. // The volume is exposed with a ProxyVolume when present. .volume.VolumeInfo host_volume_info = 3; // Standalone reports that no PluginHost Resource graph is available. bool standalone = 4; // HostStorageId is the Storage ID on the plugin host bus that this plugin // instance allocates named volumes through. Empty selects the host default // storage. string host_storage_id = 5; // Historical reports an immutable execution used for accepted-operation replay. // The plugin serves handlers without publishing current UI or type registrations. bool historical = 6; // Prepared requires private registrations until Activation.Activate is called. bool prepared = 7; // InstanceKey is the logical installation binding, or empty for shared plugins. // A Space uses its World engine ID. Physical worker generations do not change it. string instance_key = 8; } // LoadPluginRequest is a request to load a plugin while the RPC is active. message LoadPluginRequest { // PluginId is the plugin identifier to load. string plugin_id = 1; // InstanceKey is an optional key for instanced plugins. // When non-empty, the plugin host uses (plugin_id, instance_key) as the // composite deduplication key, allowing multiple independent instances of the // same plugin to run concurrently in separate workers. // When empty, behavior is unchanged: a single shared instance per plugin_id. string instance_key = 2; // Manifests selects the installation and its recovery artifacts, newest first. repeated .bldr.manifest.ManifestRef manifests = 3; // ManifestRoot loads an exact historical executable without current registrations. string manifest_root = 4; } // LoadPluginResponse is a status response to a LoadPlugin request. message LoadPluginResponse { // PluginStatus contains the current plugin status object. PluginStatus plugin_status = 1; } // PluginMeta is metadata embedded in a plugin entrypoint. message PluginMeta { // ProjectId is the project identifier. // Must be a valid-dns-label. string project_id = 1; // PluginId is the plugin identifier. // Must be a valid-dns-label. string plugin_id = 2; // PlatformId is the destination platform ID. string platform_id = 3; // BuildType is the type of build this is. string build_type = 4; } // PluginStartInfo are details passed to the plugin by the plugin host in the environment. message PluginStartInfo { // InstanceId is the plugin instance id. string instance_id = 1; // PluginId is the plugin identifier. // Must be a valid-dns-label. string plugin_id = 2; // InstanceKey is the instance key from the LoadPlugin request. // Empty for non-instanced (shared) plugins. string instance_key = 3; // ManifestRoot identifies the exact executable whose assets this worker imports. // It is the base58-encoded manifest block hash, independent of the current revision. string manifest_root = 4; } // PluginContextInfo contains information about the running plugin attached to // the Context tree for access within controllers running on the plugin bus. message PluginContextInfo { // PluginMeta is the plugin metadata. PluginMeta plugin_meta = 1; // InstanceKey identifies the plugin installation the host runs. // Empty for a singleton plugin; a Space uses its World engine ID. // State private to one installation is scoped by this key. string instance_key = 2; // ManifestRoot is the root of the manifest the plugin runs, which names the // exact build of its files. Empty when the host did not report it. string manifest_root = 3; }