swactor/crates/mvp-system/src/orchestration/actor.rs

492 lines
15 KiB
Rust
Raw Normal View History

use iroh::EndpointAddr;
use serde::{Deserialize, Serialize};
use swactor::actor::{ActorAddress, ActorInterface};
use swactor::runtime::Ctx;
use swactor_transport::{CodecRegistry, NetworkMessage};
refactor: prune public api Collapse mvp-system's public surface to three binary entrypoints and make every domain module private, deleting dead provider/worker/membership implementations and inlining provider config. - lib.rs: expose only run_chat_from_args/run_orchestrator_from_args/run_worker_node_from_env (plus a crate-private in-process helper) and the cached-model consts, and demote chat/node/observability/orchestration/prompt/staging/transport to private mods - orchestration/mod.rs: make app private, gate engine_builder behind cfg(test), drop docker_cluster from provider_adapters, tighten vastai to pub(super), and replace pub re-exports with pub(super) run_from_args/run_in_process_from_args - orchestration/config.rs: inline VastAiConfig/ResolvedVastAiConfig/looks_remote_image (removing provider_adapters/vastai/config.rs) and drop the DEFAULT_PIPELINE_CACHED_MODEL_* consts (hoisted to lib.rs) - orchestration/provider_adapters/vastai: delete the ProviderPlugin impl VastAiProviderPlugin and all client/bootstrap/config accessors; repoint call sites to crate-level #[path] mods for provisioning/node_provisioning/node_actor/gguf_shard/run_fsm/run_plan - delete orchestration/{membership_readiness,token_endpoint,resource_inventory}, node/{boot_lifecycle,data_plane_bridge(-74)}, and the worker crate-internal modules (control/device_bridge/process_adapter) along with their guarantees tests - chat/node: narrow node_image and worker_node_runtime to private and expose only pub(super) run_from_args / run_worker_node_from_env Signed-off-by: Zachery Aaron Shores-Chmielewski <zacheryasc@gmail.com>
2026-07-29 10:02:50 +00:00
use crate::run_fsm as core;
refactor: final filetree shape Reorganize crates/mvp-system from flat files into domain module trees (chat, node, node_data, observability, orchestration, prompt, staging, transport, worker) with documented mod.rs boundaries, and drop the stale inline spec docs. - lib.rs: replace ~20 flat mod declarations with one pub-mod-per-domain (chat/node/node_data/observability/orchestration/prompt/staging/transport/worker) - node/, chat/, observability/, orchestration/, staging/, prompt/, transport/, worker/: add mod.rs files with module-boundary doc comments and re-exports (e.g. chat re-exports run_from_args; orchestration re-exports RunConfig/RunId/GgufSource/TokenizerSource/ProviderKind) - orchestration: group providers under provider_adapters/{docker_cluster,relay,vastai} and fold engine_builder/, config, run_fsm, run_plan, provisioning, resource_inventory, membership_readiness, and token_endpoint under orchestration/ - transport: consolidate codec registration into transport/codec_registry::register_mvp_actor_codecs (was crate::actors::register_mvp_actor_codecs) and rename actors/codec.rs to transport/json_codec.rs - rename and relocate files into their domains (arena_manager->node_data/arena, actors/node_agent->node/actor, actors/orchestrator->orchestration/actor, stage_controller->staging/actor, telemetry/dashboard_view/etc->observability/, benchmark_observability->observability::benchmark, edge_establisher->node::edge_lifecycle, prompt_rpc->prompt::rpc) and update all crate:: imports accordingly - remove the stale crates/mvp-system/specs/*.md (MVP_SYSTEM_MODULE_BOUNDARY_SPEC, mvp_chat, orchestrator) now that module boundaries live in mod.rs docs Signed-off-by: Zachery Aaron Shores-Chmielewski <zacheryasc@gmail.com>
2026-07-28 09:04:13 +00:00
use crate::transport::json_codec::JsonCodec;
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub(crate) struct StageRefWire {
pub stage_index: u32,
pub node_id: u64,
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub(crate) enum OrchestratorMsg {
ObservePoolReady {
nodes: Vec<u64>,
},
ObservePlanAvailable {
run_id: u64,
stages: Vec<StageRefWire>,
},
ObserveStageReady {
run_id: u64,
stage_index: u32,
},
ObserveNodeRuntimeReady {
run_id: u64,
node_id: u64,
stage_index: u32,
endpoint: EndpointAddr,
node_actor: ActorAddress,
datastream_publisher: ActorAddress,
readiness_id: u64,
},
ObserveNodeRuntimeReadyAck {
run_id: u64,
node_id: u64,
stage_index: u32,
readiness_id: u64,
},
ObserveWeightsReady {
run_id: u64,
node_id: u64,
stage_index: u32,
},
ObserveTokenInEndpointReady,
ObserveTokenOutEndpointReady,
ObserveTokenReceived {
sequence: u64,
token_id: u32,
eos: bool,
},
ObserveStageFault {
run_id: u64,
stage_index: u32,
refactor: actorization polish and stability Convert the remaining thread/mpsc-based provider monitor and stage-shard fetch loops into swactor actors, propagate worker-crash reasons through the actor message chain, and validate cached stage shards before reuse. - orchestration/provider_adapters/vastai: replace the thread+AtomicBool VastAiProviderMonitor with VastAiProviderMonitorActor driven by Poll/Stop messages on its own RuntimeHandle (schedule_provider_monitor_poll), preserving the status/terminal-failure observation logic - node/worker_node_runtime: convert the blocking stage-shard-fetch mpsc loop into StageShardFetchActor (Start/PollChild/ProcessLine/ReaderError/ReaderClosed via ExternalSender, on_stop kills and joins the child) reporting Progress/Done/Failed - staging/gguf_shard: add validate_stage_shard_cache (tensor count/alignment/name/dims/type) and mix STAGE_SHARD_CACHE_FORMAT_VERSION into the shard_cache_key; materialize_stage_shard_with_process now validates a cached shard, emitting StageShardCacheInvalid and refetching when stale - node/actor + orchestration/actor: NodeAgentMsg::WorkerCrashed now carries Option<reason>, surfaced as ObserveStageFault{reason}/StageFault{reason} up to the orchestrator; NodeAgentActor records last_worker_crash - orchestration/app: complete_bootstrap now runs after runtime-ready without dropping stop handles (ProvisionedClusterGuard) and folds worker-crash reasons into stage-fault errors; chat/runtime adds cached-model config selection - xtask: relax the data-path requirement to accept activation-step-executed OR downstream-activation-loaded Signed-off-by: Zachery Aaron Shores-Chmielewski <zacheryasc@gmail.com>
2026-07-29 08:14:52 +00:00
reason: Option<String>,
},
ObserveEndpointFault {
run_id: u64,
endpoint: EndpointKindWire,
},
ObserveStageStopped {
run_id: u64,
stage_index: u32,
},
ObserveTokenEndpointsStopped,
AdvanceTimeMs(u64),
Snapshot {
reply_to: ActorAddress,
},
}
impl NetworkMessage for OrchestratorMsg {
fn type_tag() -> &'static str {
"mvp_system::OrchestratorMsg"
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub(crate) enum EndpointKindWire {
TokenIn,
TokenOut,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub(crate) struct SamplingDataWire {
pub source_sequence: u64,
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub(crate) enum TokenObjectPayloadWire {
Prompt {
tokens: Vec<u32>,
},
Decode {
token_id: u32,
sampling: SamplingDataWire,
},
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub(crate) enum RunCommandWire {
ProvisionStage {
run_id: u64,
stage_index: u32,
node_id: u64,
},
CreateTokenInEndpoint {
run_id: u64,
},
CreateTokenOutEndpoint {
run_id: u64,
},
InjectTokenObject {
run_id: u64,
sequence: u64,
payload: TokenObjectPayloadWire,
},
StopRun {
run_id: u64,
stage_index: u32,
},
TearDownTokenEndpoints {
run_id: u64,
},
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub(crate) enum LifecycleEventWire {
RunRejected { run_id: u64 },
RunFaulted { run_id: u64 },
RunCompleted { run_id: u64 },
RunOperatorStopped { run_id: u64 },
RunTornDown { run_id: u64 },
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub(crate) enum OrchestratorReport {
Command(RunCommandWire),
Lifecycle(LifecycleEventWire),
NodeRuntimeReady {
run_id: u64,
node_id: u64,
stage_index: u32,
endpoint: EndpointAddr,
node_actor: ActorAddress,
datastream_publisher: ActorAddress,
readiness_id: u64,
},
NodeRuntimeReadyAck {
run_id: u64,
node_id: u64,
stage_index: u32,
readiness_id: u64,
},
WeightsReady {
run_id: u64,
node_id: u64,
stage_index: u32,
},
StageReady {
run_id: u64,
stage_index: u32,
},
StageFault {
run_id: u64,
stage_index: u32,
refactor: actorization polish and stability Convert the remaining thread/mpsc-based provider monitor and stage-shard fetch loops into swactor actors, propagate worker-crash reasons through the actor message chain, and validate cached stage shards before reuse. - orchestration/provider_adapters/vastai: replace the thread+AtomicBool VastAiProviderMonitor with VastAiProviderMonitorActor driven by Poll/Stop messages on its own RuntimeHandle (schedule_provider_monitor_poll), preserving the status/terminal-failure observation logic - node/worker_node_runtime: convert the blocking stage-shard-fetch mpsc loop into StageShardFetchActor (Start/PollChild/ProcessLine/ReaderError/ReaderClosed via ExternalSender, on_stop kills and joins the child) reporting Progress/Done/Failed - staging/gguf_shard: add validate_stage_shard_cache (tensor count/alignment/name/dims/type) and mix STAGE_SHARD_CACHE_FORMAT_VERSION into the shard_cache_key; materialize_stage_shard_with_process now validates a cached shard, emitting StageShardCacheInvalid and refetching when stale - node/actor + orchestration/actor: NodeAgentMsg::WorkerCrashed now carries Option<reason>, surfaced as ObserveStageFault{reason}/StageFault{reason} up to the orchestrator; NodeAgentActor records last_worker_crash - orchestration/app: complete_bootstrap now runs after runtime-ready without dropping stop handles (ProvisionedClusterGuard) and folds worker-crash reasons into stage-fault errors; chat/runtime adds cached-model config selection - xtask: relax the data-path requirement to accept activation-step-executed OR downstream-activation-loaded Signed-off-by: Zachery Aaron Shores-Chmielewski <zacheryasc@gmail.com>
2026-07-29 08:14:52 +00:00
reason: Option<String>,
},
Snapshot {
commands: Vec<RunCommandWire>,
events: Vec<LifecycleEventWire>,
injected_sequences: Vec<u64>,
},
}
impl NetworkMessage for OrchestratorReport {
fn type_tag() -> &'static str {
"mvp_system::OrchestratorReport"
}
}
pub(crate) struct OrchestratorActor {
core: core::OrchestratorRun,
report_to: Option<ActorAddress>,
command_cursor: usize,
event_cursor: usize,
}
impl OrchestratorActor {
pub(crate) fn new(config: core::RunConfig, report_to: Option<ActorAddress>) -> Self {
Self {
core: core::OrchestratorRun::new(config),
report_to,
command_cursor: 0,
event_cursor: 0,
}
}
fn observe(&mut self, msg: OrchestratorMsg) {
match msg {
OrchestratorMsg::ObservePoolReady { nodes } => {
self.core.observe(core::RunEvent::PoolReady {
nodes: nodes.into_iter().map(core::NodeId).collect(),
});
}
OrchestratorMsg::ObservePlanAvailable { run_id, stages } => {
self.core
.observe(core::RunEvent::PlanAvailable(core::RunPlan {
run_id: core::RunId(run_id),
stages: stages
.into_iter()
.map(|stage| core::StageRef {
stage_index: stage.stage_index,
node_id: core::NodeId(stage.node_id),
})
.collect(),
}));
}
OrchestratorMsg::ObserveStageReady {
run_id,
stage_index,
} => self.core.observe(core::RunEvent::StageReady {
run_id: core::RunId(run_id),
stage_index,
}),
OrchestratorMsg::ObserveNodeRuntimeReady { .. } => {}
OrchestratorMsg::ObserveNodeRuntimeReadyAck { .. } => {}
OrchestratorMsg::ObserveWeightsReady { .. } => {}
OrchestratorMsg::ObserveTokenInEndpointReady => {
self.core.observe(core::RunEvent::TokenInEndpointReady)
}
OrchestratorMsg::ObserveTokenOutEndpointReady => {
self.core.observe(core::RunEvent::TokenOutEndpointReady)
}
OrchestratorMsg::ObserveTokenReceived {
sequence,
token_id,
eos,
} => self.core.observe(core::RunEvent::TokenReceived {
sequence,
token_id,
eos,
}),
OrchestratorMsg::ObserveStageFault {
run_id,
stage_index,
refactor: actorization polish and stability Convert the remaining thread/mpsc-based provider monitor and stage-shard fetch loops into swactor actors, propagate worker-crash reasons through the actor message chain, and validate cached stage shards before reuse. - orchestration/provider_adapters/vastai: replace the thread+AtomicBool VastAiProviderMonitor with VastAiProviderMonitorActor driven by Poll/Stop messages on its own RuntimeHandle (schedule_provider_monitor_poll), preserving the status/terminal-failure observation logic - node/worker_node_runtime: convert the blocking stage-shard-fetch mpsc loop into StageShardFetchActor (Start/PollChild/ProcessLine/ReaderError/ReaderClosed via ExternalSender, on_stop kills and joins the child) reporting Progress/Done/Failed - staging/gguf_shard: add validate_stage_shard_cache (tensor count/alignment/name/dims/type) and mix STAGE_SHARD_CACHE_FORMAT_VERSION into the shard_cache_key; materialize_stage_shard_with_process now validates a cached shard, emitting StageShardCacheInvalid and refetching when stale - node/actor + orchestration/actor: NodeAgentMsg::WorkerCrashed now carries Option<reason>, surfaced as ObserveStageFault{reason}/StageFault{reason} up to the orchestrator; NodeAgentActor records last_worker_crash - orchestration/app: complete_bootstrap now runs after runtime-ready without dropping stop handles (ProvisionedClusterGuard) and folds worker-crash reasons into stage-fault errors; chat/runtime adds cached-model config selection - xtask: relax the data-path requirement to accept activation-step-executed OR downstream-activation-loaded Signed-off-by: Zachery Aaron Shores-Chmielewski <zacheryasc@gmail.com>
2026-07-29 08:14:52 +00:00
reason: _,
} => self.core.observe(core::RunEvent::StageFault {
run_id: core::RunId(run_id),
stage_index,
reason: core::StageFaultReason::WorkerCrashed,
}),
OrchestratorMsg::ObserveEndpointFault { run_id, endpoint } => {
self.core.observe(core::RunEvent::EndpointFault {
run_id: core::RunId(run_id),
endpoint: match endpoint {
EndpointKindWire::TokenIn => core::EndpointKind::TokenIn,
EndpointKindWire::TokenOut => core::EndpointKind::TokenOut,
},
});
}
OrchestratorMsg::ObserveStageStopped {
run_id,
stage_index,
} => self.core.observe(core::RunEvent::StageStopped {
run_id: core::RunId(run_id),
stage_index,
}),
OrchestratorMsg::ObserveTokenEndpointsStopped => {
self.core.observe(core::RunEvent::TokenEndpointsStopped)
}
OrchestratorMsg::AdvanceTimeMs(delta) => self.core.advance_time_ms(delta),
OrchestratorMsg::Snapshot { .. } => {}
}
}
fn drain_outputs(&mut self, ctx: &Ctx) {
let Some(report_to) = self.report_to else {
self.command_cursor = self.core.commands().len();
self.event_cursor = self.core.events().len();
return;
};
for command in &self.core.commands()[self.command_cursor..] {
let _ = ctx.send(report_to, OrchestratorReport::Command(command.into()));
}
self.command_cursor = self.core.commands().len();
for event in &self.core.events()[self.event_cursor..] {
let _ = ctx.send(report_to, OrchestratorReport::Lifecycle(event.into()));
}
self.event_cursor = self.core.events().len();
}
}
impl ActorInterface for OrchestratorActor {
type Incoming = OrchestratorMsg;
type Response = ();
fn handle(&mut self, ctx: &Ctx, msg: Self::Incoming) {
match msg.clone() {
OrchestratorMsg::ObserveNodeRuntimeReady {
run_id,
node_id,
stage_index,
endpoint,
node_actor,
datastream_publisher,
readiness_id,
} => {
if let Some(report_to) = self.report_to {
let _ = ctx.send(
report_to,
OrchestratorReport::NodeRuntimeReady {
run_id,
node_id,
stage_index,
endpoint,
node_actor,
datastream_publisher,
readiness_id,
},
);
}
return;
}
OrchestratorMsg::ObserveNodeRuntimeReadyAck {
run_id,
node_id,
stage_index,
readiness_id,
} => {
if let Some(report_to) = self.report_to {
let _ = ctx.send(
report_to,
OrchestratorReport::NodeRuntimeReadyAck {
run_id,
node_id,
stage_index,
readiness_id,
},
);
}
return;
}
OrchestratorMsg::ObserveWeightsReady {
run_id,
node_id,
stage_index,
} => {
if let Some(report_to) = self.report_to {
let _ = ctx.send(
report_to,
OrchestratorReport::WeightsReady {
run_id,
node_id,
stage_index,
},
);
}
return;
}
OrchestratorMsg::Snapshot { reply_to } => {
let _ = ctx.send(
reply_to,
OrchestratorReport::Snapshot {
commands: self
.core
.commands()
.iter()
.map(RunCommandWire::from)
.collect(),
events: self
.core
.events()
.iter()
.map(LifecycleEventWire::from)
.collect(),
injected_sequences: self.core.injected_sequences(),
},
);
return;
}
_ => {}
}
let direct_report = match msg.clone() {
OrchestratorMsg::ObserveStageReady {
run_id,
stage_index,
} => Some(OrchestratorReport::StageReady {
run_id,
stage_index,
}),
OrchestratorMsg::ObserveStageFault {
run_id,
stage_index,
refactor: actorization polish and stability Convert the remaining thread/mpsc-based provider monitor and stage-shard fetch loops into swactor actors, propagate worker-crash reasons through the actor message chain, and validate cached stage shards before reuse. - orchestration/provider_adapters/vastai: replace the thread+AtomicBool VastAiProviderMonitor with VastAiProviderMonitorActor driven by Poll/Stop messages on its own RuntimeHandle (schedule_provider_monitor_poll), preserving the status/terminal-failure observation logic - node/worker_node_runtime: convert the blocking stage-shard-fetch mpsc loop into StageShardFetchActor (Start/PollChild/ProcessLine/ReaderError/ReaderClosed via ExternalSender, on_stop kills and joins the child) reporting Progress/Done/Failed - staging/gguf_shard: add validate_stage_shard_cache (tensor count/alignment/name/dims/type) and mix STAGE_SHARD_CACHE_FORMAT_VERSION into the shard_cache_key; materialize_stage_shard_with_process now validates a cached shard, emitting StageShardCacheInvalid and refetching when stale - node/actor + orchestration/actor: NodeAgentMsg::WorkerCrashed now carries Option<reason>, surfaced as ObserveStageFault{reason}/StageFault{reason} up to the orchestrator; NodeAgentActor records last_worker_crash - orchestration/app: complete_bootstrap now runs after runtime-ready without dropping stop handles (ProvisionedClusterGuard) and folds worker-crash reasons into stage-fault errors; chat/runtime adds cached-model config selection - xtask: relax the data-path requirement to accept activation-step-executed OR downstream-activation-loaded Signed-off-by: Zachery Aaron Shores-Chmielewski <zacheryasc@gmail.com>
2026-07-29 08:14:52 +00:00
reason,
} => Some(OrchestratorReport::StageFault {
run_id,
stage_index,
refactor: actorization polish and stability Convert the remaining thread/mpsc-based provider monitor and stage-shard fetch loops into swactor actors, propagate worker-crash reasons through the actor message chain, and validate cached stage shards before reuse. - orchestration/provider_adapters/vastai: replace the thread+AtomicBool VastAiProviderMonitor with VastAiProviderMonitorActor driven by Poll/Stop messages on its own RuntimeHandle (schedule_provider_monitor_poll), preserving the status/terminal-failure observation logic - node/worker_node_runtime: convert the blocking stage-shard-fetch mpsc loop into StageShardFetchActor (Start/PollChild/ProcessLine/ReaderError/ReaderClosed via ExternalSender, on_stop kills and joins the child) reporting Progress/Done/Failed - staging/gguf_shard: add validate_stage_shard_cache (tensor count/alignment/name/dims/type) and mix STAGE_SHARD_CACHE_FORMAT_VERSION into the shard_cache_key; materialize_stage_shard_with_process now validates a cached shard, emitting StageShardCacheInvalid and refetching when stale - node/actor + orchestration/actor: NodeAgentMsg::WorkerCrashed now carries Option<reason>, surfaced as ObserveStageFault{reason}/StageFault{reason} up to the orchestrator; NodeAgentActor records last_worker_crash - orchestration/app: complete_bootstrap now runs after runtime-ready without dropping stop handles (ProvisionedClusterGuard) and folds worker-crash reasons into stage-fault errors; chat/runtime adds cached-model config selection - xtask: relax the data-path requirement to accept activation-step-executed OR downstream-activation-loaded Signed-off-by: Zachery Aaron Shores-Chmielewski <zacheryasc@gmail.com>
2026-07-29 08:14:52 +00:00
reason,
}),
_ => None,
};
self.observe(msg);
if let (Some(report_to), Some(report)) = (self.report_to, direct_report) {
let _ = ctx.send(report_to, report);
}
self.drain_outputs(ctx);
}
}
impl From<&core::RunCommand> for RunCommandWire {
fn from(command: &core::RunCommand) -> Self {
match command {
core::RunCommand::ProvisionStage { provision } => Self::ProvisionStage {
run_id: provision.run_id.0,
stage_index: provision.stage_index,
node_id: provision.node_id.0,
},
core::RunCommand::CreateTokenInEndpoint { run_id } => {
Self::CreateTokenInEndpoint { run_id: run_id.0 }
}
core::RunCommand::CreateTokenOutEndpoint { run_id } => {
Self::CreateTokenOutEndpoint { run_id: run_id.0 }
}
core::RunCommand::InjectTokenObject { run_id, object } => Self::InjectTokenObject {
run_id: run_id.0,
sequence: object.sequence,
payload: (&object.payload).into(),
},
core::RunCommand::StopRun {
run_id,
stage_index,
} => Self::StopRun {
run_id: run_id.0,
stage_index: *stage_index,
},
core::RunCommand::TearDownTokenEndpoints { run_id } => {
Self::TearDownTokenEndpoints { run_id: run_id.0 }
}
}
}
}
impl From<&core::LifecycleEvent> for LifecycleEventWire {
fn from(event: &core::LifecycleEvent) -> Self {
match event {
core::LifecycleEvent::RunRejected { run_id, .. } => {
Self::RunRejected { run_id: run_id.0 }
}
core::LifecycleEvent::RunFaulted { run_id, .. } => {
Self::RunFaulted { run_id: run_id.0 }
}
core::LifecycleEvent::RunCompleted { run_id } => {
Self::RunCompleted { run_id: run_id.0 }
}
core::LifecycleEvent::RunOperatorStopped { run_id } => {
Self::RunOperatorStopped { run_id: run_id.0 }
}
core::LifecycleEvent::RunTornDown { run_id } => Self::RunTornDown { run_id: run_id.0 },
}
}
}
pub(crate) fn register_codecs(registry: &mut CodecRegistry) {
registry.register::<OrchestratorMsg, _>(JsonCodec::<OrchestratorMsg>::default());
registry.register::<OrchestratorReport, _>(JsonCodec::<OrchestratorReport>::default());
}
impl From<&core::TokenObjectPayload> for TokenObjectPayloadWire {
fn from(payload: &core::TokenObjectPayload) -> Self {
match payload {
core::TokenObjectPayload::Prompt { tokens } => Self::Prompt {
tokens: tokens.clone(),
},
core::TokenObjectPayload::Decode { token_id, sampling } => Self::Decode {
token_id: *token_id,
sampling: SamplingDataWire {
source_sequence: sampling.source_sequence,
},
},
}
}
}