fix(service): wait for network before startup

Delay systemd startup until network-online and configure Windows delayed
auto-start plus recovery actions.

This reduces early boot failures when config-server resolution depends
on network and DNS becoming ready first.
This commit is contained in:
fanyang89
2026-04-22 13:58:11 +08:00
parent ffddc517e1
commit 6e1018f975
+55 -4
View File
@@ -237,7 +237,8 @@ impl Service {
let mut unit_content = String::new();
writeln!(unit_content, "[Unit]")?;
writeln!(unit_content, "After=network.target syslog.target")?;
writeln!(unit_content, "Wants=network-online.target")?;
writeln!(unit_content, "After=network-online.target syslog.target")?;
if let Some(ref d) = options.description {
writeln!(unit_content, "Description={d}")?;
}
@@ -337,11 +338,12 @@ impl Service {
#[cfg(target_os = "windows")]
mod win_service_manager {
use std::{ffi::OsStr, ffi::OsString, io, path::PathBuf};
use std::{ffi::OsStr, ffi::OsString, io, path::PathBuf, time::Duration};
use windows_service::{
service::{
ServiceAccess, ServiceDependency, ServiceErrorControl, ServiceInfo, ServiceStartType,
ServiceType,
ServiceAccess, ServiceAction, ServiceActionType, ServiceDependency,
ServiceErrorControl, ServiceFailureActions, ServiceFailureResetPeriod, ServiceInfo,
ServiceStartType, ServiceType,
},
service_manager::{ServiceManager, ServiceManagerAccess},
};
@@ -368,6 +370,51 @@ mod win_service_manager {
service_manager: ServiceManager,
}
fn build_failure_actions(disable_restart_on_failure: bool) -> ServiceFailureActions {
let actions = if disable_restart_on_failure {
Vec::new()
} else {
vec![
ServiceAction {
action_type: ServiceActionType::Restart,
delay: Duration::from_secs(1),
},
ServiceAction {
action_type: ServiceActionType::Restart,
delay: Duration::from_secs(1),
},
ServiceAction {
action_type: ServiceActionType::Restart,
delay: Duration::from_secs(1),
},
]
};
ServiceFailureActions {
reset_period: ServiceFailureResetPeriod::After(Duration::from_secs(24 * 60 * 60)),
reboot_msg: None,
command: None,
actions: Some(actions),
}
}
fn configure_service_behavior(
service: &windows_service::service::Service,
ctx: &ServiceInstallCtx,
) -> io::Result<()> {
service
.set_delayed_auto_start(ctx.autostart)
.map_err(io::Error::other)?;
service
.update_failure_actions(build_failure_actions(ctx.disable_restart_on_failure))
.map_err(io::Error::other)?;
service
.set_failure_actions_on_non_crash_failures(!ctx.disable_restart_on_failure)
.map_err(io::Error::other)?;
Ok(())
}
fn generate_service_info(ctx: &ServiceInstallCtx) -> (ServiceInfo, Option<OsString>) {
let start_type = if ctx.autostart {
ServiceStartType::AutoStart
@@ -437,6 +484,8 @@ mod win_service_manager {
.map_err(io::Error::other)?;
}
configure_service_behavior(&service, &ctx)?;
if let Some(work_dir) = ctx.working_directory {
set_service_work_directory(&ctx.label.to_qualified_name(), work_dir)?;
}
@@ -528,6 +577,8 @@ mod win_service_manager {
.map_err(io::Error::other)?;
}
configure_service_behavior(&service, &ctx)?;
if let Some(work_dir) = ctx.working_directory {
set_service_work_directory(&ctx.label.to_qualified_name(), work_dir)?;
}