You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
When the Docker container is stopped while /var/piler/tmp still contains queued messages, piler-smtp and the worker process are stopped together. On the next startup Piler correctly replays that existing backlog, but new messages accepted just after startup can sit behind the old spool. In a large backlog this makes newly received mail look slow to appear even though startup recovery itself is working.
Change
This adds a drained stop path for intentional Docker stops:
docker/start.sh traps SIGTERM and SIGINT instead of ending at sleep infinity.
The trap calls /etc/init.d/rc.piler drain-stop by default.
drain-stop stops piler-smtp first so no new mail is accepted, lets piler workers drain /var/piler/tmp, then stops the workers.
PILER_STOP_DRAIN_TIMEOUT controls the wait timeout, defaulting to 300 seconds.
PILER_STOP_DRAIN=0 and force-stop preserve the old immediate stop path.
Drain logs now expose stable start/end counters (initial_files, remaining_files, and elapsed) so operators can verify how much work was pending and whether the spool reached zero before shutdown.
Crash/forced-kill recovery remains unchanged: if files are still in /var/piler/tmp, the next startup still processes them.
One additional problem addressed by this PR is mail safety during Docker image upgrades that recreate the container.
After docker compose pull, a subsequent docker compose up -d stops and recreates the service when the image changed. The pending workdir backlog is normally under /var/piler/tmp. In the default Compose layout it is part of the container writable layer, because only /etc/piler and /var/piler/store are persistent volumes. Therefore, accepted but not yet processed messages remaining in /var/piler/tmp could be removed together with the old container.
With this change, SIGTERM stops piler-smtp first and lets the Piler workers empty the backlog before the container exits. A normal Compose recreation can therefore start from an empty spool instead of discarding pending files.
If an administrator already mounts /var/piler/tmp (or the complete Piler workdir) on a persistent volume, the backlog already survives container replacement; the drain still avoids replaying it after startup and prevents new messages from waiting behind it.
Two limits remain:
If the drain timeout is reached with files still pending, a subsequent recreation can still discard them unless the workdir is persistent.
The first upgrade from an older, unpatched image cannot use this shutdown path, because the stop is handled by the currently running container. Its backlog should be emptied or persisted before that first recreation.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
When the Docker container is stopped while
/var/piler/tmpstill contains queued messages,piler-smtpand the worker process are stopped together. On the next startup Piler correctly replays that existing backlog, but new messages accepted just after startup can sit behind the old spool. In a large backlog this makes newly received mail look slow to appear even though startup recovery itself is working.Change
This adds a drained stop path for intentional Docker stops:
docker/start.shtrapsSIGTERMandSIGINTinstead of ending atsleep infinity./etc/init.d/rc.piler drain-stopby default.drain-stopstopspiler-smtpfirst so no new mail is accepted, letspilerworkers drain/var/piler/tmp, then stops the workers.PILER_STOP_DRAIN_TIMEOUTcontrols the wait timeout, defaulting to300seconds.PILER_STOP_DRAIN=0andforce-stoppreserve the old immediate stop path.Drain logs now expose stable start/end counters (
initial_files,remaining_files, andelapsed) so operators can verify how much work was pending and whether the spool reached zero before shutdown.Crash/forced-kill recovery remains unchanged: if files are still in
/var/piler/tmp, the next startup still processes them.For context, the GitLab fork/project where this was validated is https://gitlab.com/fredbcode-images/piler.
Before / after measurement
Validation used a test Docker image with this patch, an 8000-message backlog, and a live probe sent immediately after startup.
/var/piler/tmpstill contained mail left by the interrupted run.docker stop -t 600drained 5330 remaining files in221sbefore the container exited.status=storedand the Manticore realtime index in3.264safter restart./var/piler/tmpwas empty.status=storedplus Manticore in89.533sfrom restart,86.275safter the probe send finished.0.843sfrom send start and0.006safter SMTP send completed./var/piler/tmpstill had 5864 files and Manticore had 2157 documents./var/piler/tmpwas empty, Manticore had 8060 documents.Validation
bash -n docker/start.shsh -n init.d/rc.piler.ingit diff --check origin/master...HEADinitial_files=2toremaining_files=0initial_files=1toremaining_files=1Prepared by iafred-bot
GitLab: @fredbcode
GitHub: @fredbcode