fix(serve): start scheduler at startup instead of first ACP connection (#10766)
This commit is contained in:
@@ -1480,6 +1480,9 @@ async fn handle_serve_command(args: ServeCommandArgs) -> Result<()> {
|
||||
})
|
||||
.collect::<Result<Vec<_>>>()?;
|
||||
let secret_key = env_secret.unwrap_or_else(generate_serve_secret_key);
|
||||
if let Err(error) = server.start_scheduler().await {
|
||||
warn!("Scheduler failed to start; scheduled jobs will not run until a client connects: {error}");
|
||||
}
|
||||
let router = create_router(
|
||||
server,
|
||||
secret_key,
|
||||
|
||||
@@ -32,6 +32,13 @@ impl AcpServer {
|
||||
}
|
||||
}
|
||||
|
||||
/// Start the scheduler now instead of on first client connect, so a
|
||||
/// headless `goose serve` runs scheduled jobs; on failure `create_agent`
|
||||
/// retries. No-op when the scheduler is disabled.
|
||||
pub async fn start_scheduler(&self) -> Result<()> {
|
||||
self.scheduler().await.map(|_| ())
|
||||
}
|
||||
|
||||
async fn scheduler(&self) -> Result<Option<Arc<dyn SchedulerTrait>>> {
|
||||
if !self.config.enable_scheduler {
|
||||
return Ok(None);
|
||||
@@ -57,6 +64,10 @@ impl AcpServer {
|
||||
let config = crate::config::Config::global();
|
||||
let disable_session_naming = config.get_goose_disable_session_naming().unwrap_or(false);
|
||||
let scheduler = self.scheduler().await?;
|
||||
if let Some(scheduler) = &scheduler {
|
||||
// Listing syncs from storage, registering jobs persisted by other processes.
|
||||
scheduler.list_scheduled_jobs().await;
|
||||
}
|
||||
|
||||
let provider_factory: AcpProviderFactory =
|
||||
Arc::new(move |provider_name, extensions, working_dir| {
|
||||
@@ -123,4 +134,32 @@ mod tests {
|
||||
|
||||
assert!(server.scheduler().await.unwrap().is_some());
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn start_scheduler_initializes_before_any_client_connects() {
|
||||
let root = tempfile::tempdir().unwrap();
|
||||
let server = server(root.path().to_path_buf(), true);
|
||||
|
||||
assert!(!server.scheduler.initialized());
|
||||
server.start_scheduler().await.unwrap();
|
||||
assert!(server.scheduler.initialized());
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn start_scheduler_is_idempotent() {
|
||||
let root = tempfile::tempdir().unwrap();
|
||||
let server = server(root.path().to_path_buf(), true);
|
||||
|
||||
server.start_scheduler().await.unwrap();
|
||||
server.start_scheduler().await.unwrap();
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn start_scheduler_does_not_construct_one_when_disabled() {
|
||||
let root = tempfile::tempdir().unwrap();
|
||||
let server = server(root.path().to_path_buf(), false);
|
||||
|
||||
server.start_scheduler().await.unwrap();
|
||||
assert!(!server.scheduler.initialized());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user