Skip to content

Commit c7e88d9

Browse files
committed
feat: implemented status heartbeat
1 parent ba11fa4 commit c7e88d9

2 files changed

Lines changed: 61 additions & 7 deletions

File tree

crates/taurus/src/app/mod.rs

Lines changed: 53 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
mod worker;
22

3+
use std::sync::Arc;
34
use std::time::Duration;
45

56
use code0_flow::flow_config::load_env_file;
@@ -27,7 +28,7 @@ pub async fn run() {
2728
let client = connect_nats(&config).await;
2829

2930
let mut health_task = spawn_health_task(&config);
30-
let (runtime_status_service, runtime_usage_service) =
31+
let (runtime_status_service, runtime_usage_service, mut runtime_status_heartbeat_task) =
3132
setup_dynamic_services_if_needed(&config).await;
3233

3334
let nats_remote = NATSRemoteRuntime::new(client.clone());
@@ -41,6 +42,14 @@ pub async fn run() {
4142
);
4243

4344
wait_for_shutdown(&mut worker_task, &mut health_task).await;
45+
if let Some(handle) = runtime_status_heartbeat_task.take() {
46+
handle.abort();
47+
if let Err(err) = handle.await {
48+
if !err.is_cancelled() {
49+
log::warn!("Runtime status heartbeat task ended unexpectedly: {}", err);
50+
}
51+
}
52+
}
4453
update_stopped_status(runtime_status_service.as_ref()).await;
4554

4655
log::info!("Taurus shutdown complete");
@@ -95,11 +104,12 @@ fn spawn_health_task(config: &Config) -> Option<JoinHandle<()>> {
95104
async fn setup_dynamic_services_if_needed(
96105
config: &Config,
97106
) -> (
98-
Option<TaurusRuntimeStatusService>,
107+
Option<Arc<TaurusRuntimeStatusService>>,
99108
Option<TaurusRuntimeUsageService>,
109+
Option<JoinHandle<()>>,
100110
) {
101111
if config.mode != DYNAMIC {
102-
return (None, None);
112+
return (None, None, None);
103113
}
104114

105115
push_definitions_until_success(config).await;
@@ -109,23 +119,59 @@ async fn setup_dynamic_services_if_needed(
109119
.await,
110120
);
111121

112-
let runtime_status_service = Some(
122+
let runtime_status_service = Some(Arc::new(
113123
TaurusRuntimeStatusService::from_url(
114124
config.aquila_url.clone(),
115125
config.aquila_token.clone(),
116126
"taurus".into(),
117127
runtime_features(),
118128
)
119129
.await,
120-
);
130+
));
121131

122132
if let Some(status_service) = runtime_status_service.as_ref() {
123133
status_service
124134
.update_runtime_status(tucana::shared::execution_runtime_status::Status::Running)
125135
.await;
126136
}
127137

128-
(runtime_status_service, runtime_usage_service)
138+
let runtime_status_heartbeat_task = if config.adapter_status_update_interval_seconds > 0 {
139+
let status_service = runtime_status_service
140+
.as_ref()
141+
.expect("runtime status service should exist in dynamic mode")
142+
.clone();
143+
let update_interval_seconds = config.adapter_status_update_interval_seconds;
144+
145+
let handle = tokio::spawn(async move {
146+
let mut interval = tokio::time::interval(Duration::from_secs(update_interval_seconds));
147+
interval.set_missed_tick_behavior(tokio::time::MissedTickBehavior::Skip);
148+
149+
// First tick is immediate; consume it so heartbeats start after the interval.
150+
interval.tick().await;
151+
152+
loop {
153+
interval.tick().await;
154+
status_service
155+
.update_runtime_status(tucana::shared::execution_runtime_status::Status::Running)
156+
.await;
157+
}
158+
});
159+
160+
log::info!(
161+
"Runtime status heartbeat started (interval={}s)",
162+
update_interval_seconds
163+
);
164+
Some(handle)
165+
} else {
166+
log::info!("Runtime status heartbeat is disabled");
167+
None
168+
};
169+
170+
(
171+
runtime_status_service,
172+
runtime_usage_service,
173+
runtime_status_heartbeat_task,
174+
)
129175
}
130176

131177
async fn push_definitions_until_success(config: &Config) {
@@ -165,7 +211,7 @@ fn runtime_features() -> Vec<RuntimeFeature> {
165211
}]
166212
}
167213

168-
async fn update_stopped_status(runtime_status_service: Option<&TaurusRuntimeStatusService>) {
214+
async fn update_stopped_status(runtime_status_service: Option<&Arc<TaurusRuntimeStatusService>>) {
169215
if let Some(status_service) = runtime_status_service {
170216
status_service
171217
.update_runtime_status(tucana::shared::execution_runtime_status::Status::Stopped)

crates/taurus/src/config/mod.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ pub struct Config {
2323
pub grpc_port: u16,
2424

2525
pub definitions: String,
26+
27+
/// Runtime status heartbeat interval in seconds while Taurus is running.
28+
/// Set to 0 to disable periodic heartbeat updates.
29+
pub adapter_status_update_interval_seconds: u64,
2630
}
2731

2832
/// Implementation for all relevant `Aquila` startup configurations
@@ -40,6 +44,10 @@ impl Config {
4044
grpc_host: env_with_default("GRPC_HOST", "127.0.0.1".to_string()),
4145
grpc_port: env_with_default("GRPC_PORT", 50051),
4246
definitions: env_with_default("DEFINITIONS", String::from("./definitions")),
47+
adapter_status_update_interval_seconds: env_with_default(
48+
"ADAPTER_STATUS_UPDATE_INTERVAL_SECONDS",
49+
30_u64,
50+
),
4351
}
4452
}
4553
}

0 commit comments

Comments
 (0)