Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 13 additions & 6 deletions core/crates/ployzd/src/corrosion/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ impl CorrosionConfig {
let admin = AdminClient::new(self.paths.admin_socket());
let docker = Docker::connect_with_socket_defaults()?;
let service = DockerService {
service: ManagedService::host(docker, self.container_name.clone(), IMAGE),
service: managed(docker, self.container_name.clone()),
data_dir: self.paths.data_dir.clone(),
run_dir: self.paths.run_dir.clone(),
};
Expand Down Expand Up @@ -223,11 +223,18 @@ struct InstalledFiles {
/// handle, for a reset the daemon did not finish before it stopped.
pub async fn remove_retained(run_dir: &Path) -> Result<(), Error> {
let docker = Docker::connect_with_socket_defaults()?;
remove(
&ManagedService::host(docker, DEFAULT_CONTAINER_NAME, IMAGE),
run_dir,
)
.await
remove(&managed(docker, DEFAULT_CONTAINER_NAME), run_dir).await
}

/// Seconds a replaced or removed Corrosion gets after SIGTERM. Its graceful exit waits up
/// to 5 s for gossip connections that peers keep open to go idle, and the daemon waits
/// on that stop (#3680). Nothing durable rides on it: a killed Corrosion keeps every
/// committed write, its graceful exit already drops queued changes, and peers resend
/// those through sync, as after a crash.
const STOP_GRACE_SECONDS: i32 = 1;

fn managed(docker: Docker, name: impl Into<String>) -> ManagedService {
ManagedService::host(docker, name, IMAGE).with_stop_grace(STOP_GRACE_SECONDS)
}

async fn remove(service: &ManagedService, run_dir: &Path) -> Result<(), Error> {
Expand Down
26 changes: 24 additions & 2 deletions core/crates/ployzd/src/docker/managed_service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ use bollard::{
Docker,
errors::Error as DockerError,
models::{ContainerCreateBody, ContainerInspectResponse},
query_parameters::{CreateContainerOptionsBuilder, RemoveContainerOptionsBuilder},
query_parameters::{
CreateContainerOptionsBuilder, RemoveContainerOptionsBuilder, StopContainerOptions,
StopContainerOptionsBuilder,
},
};
use ployz_core::PullPolicy;
use sha2::{Digest as _, Sha256};
Expand Down Expand Up @@ -106,6 +109,7 @@ pub(crate) struct ManagedService {
engine: Engine,
name: String,
image: &'static str,
stop_grace_seconds: Option<i32>,
}

#[derive(Clone)]
Expand All @@ -120,6 +124,7 @@ impl ManagedService {
engine: Engine::Host(docker),
name: name.into(),
image,
stop_grace_seconds: None,
}
}

Expand All @@ -132,9 +137,17 @@ impl ManagedService {
engine: Engine::Endpoint(docker),
name: name.into(),
image,
stop_grace_seconds: None,
}
}

/// Seconds Docker waits after SIGTERM before it kills the container, instead of
/// its 10 s default.
pub(crate) fn with_stop_grace(mut self, seconds: i32) -> Self {
self.stop_grace_seconds = Some(seconds);
self
}

pub(crate) async fn ensure_host(
&self,
desired: DesiredContainer,
Expand Down Expand Up @@ -228,13 +241,22 @@ impl ManagedService {
}

async fn stop(&self) -> Result<(), DockerError> {
match self.docker().stop_container(&self.name, None).await {
match self
.docker()
.stop_container(&self.name, self.stop_options())
.await
{
Ok(()) => Ok(()),
Err(error) if is_already_stopped(&error) || is_not_found(&error) => Ok(()),
Err(error) => Err(error),
}
}

fn stop_options(&self) -> Option<StopContainerOptions> {
self.stop_grace_seconds
.map(|seconds| StopContainerOptionsBuilder::default().t(seconds).build())
}

pub(crate) async fn remove(&self) -> Result<(), DockerError> {
self.stop().await?;
match self
Expand Down
Loading