From c3ac102eba3641f8a43753068dc17a82966f8511 Mon Sep 17 00:00:00 2001 From: Michael Martin Date: Mon, 17 Nov 2025 13:11:49 -0800 Subject: [PATCH] Enhancement: speed-up docker container startup (#11134) This alters the retry/backoff logic in the init-wait-for-db script to be more optimistic about database availability. During regular deployment and operations of paperless-ngx, it's common to restart the application server with the database instance already running, so we should optimize for this case. Instead of unconditionally delaying 5 seconds between each connection attempt, start with a minimum delay of 1 second and increase the delay linearly with each attempt, maxing out at 10 seconds. This makes the retry count-based failure mode less practical, so instead we just use a timeout-based approach.* *NOTE: the original implementation would have an effective timeout of 25s. This alters the behavior to 60s. Additionally, this removes an unnecessary 5s delay that was injected in the postgres case. The script uses a more comprehensive connection check for postgres than it does mariadb, so if anything this 5s delay after getting an "ok" response from the DB was extra unnecessary in the postgres case. --- .../s6-overlay/s6-rc.d/init-wait-for-db/run | 90 +++++++++---------- 1 file changed, 43 insertions(+), 47 deletions(-) diff --git a/docker/rootfs/etc/s6-overlay/s6-rc.d/init-wait-for-db/run b/docker/rootfs/etc/s6-overlay/s6-rc.d/init-wait-for-db/run index ede8a654a..1739edd61 100755 --- a/docker/rootfs/etc/s6-overlay/s6-rc.d/init-wait-for-db/run +++ b/docker/rootfs/etc/s6-overlay/s6-rc.d/init-wait-for-db/run @@ -1,70 +1,66 @@ #!/command/with-contenv /usr/bin/bash # shellcheck shell=bash +# vim: set ft=bash ts=4 sw=4 sts=4 et : -declare -r log_prefix="[init-db-wait]" +set -euo pipefail + +declare -r LOG_PREFIX="[init-db-wait]" + +declare -ri TIMEOUT=60 +declare -i ATTEMPT=0 +declare -i DELAY=0 +declare -i STARTED_AT=${EPOCHSECONDS:?EPOCHSECONDS var unset} + +delay_next_attempt() { + local -i elapsed=$(( EPOCHSECONDS - STARTED_AT )) + local -ri remaining=$(( TIMEOUT - elapsed )) + + if (( remaining <= 0 )); then + echo "${LOG_PREFIX} Unable to connect after $elapsed seconds." + exit 1 + fi + + DELAY+=1 + + # clamp to remaining time + if (( DELAY > remaining )); then + DELAY=$remaining + fi + + ATTEMPT+=1 + echo "${LOG_PREFIX} Attempt $ATTEMPT failed! Trying again in $DELAY seconds..." + sleep "$DELAY" +} wait_for_postgres() { - local attempt_num=1 - local -r max_attempts=5 - - echo "${log_prefix} Waiting for PostgreSQL to start..." + echo "${LOG_PREFIX} Waiting for PostgreSQL to start..." local -r host="${PAPERLESS_DBHOST:-localhost}" local -r port="${PAPERLESS_DBPORT:-5432}" local -r user="${PAPERLESS_DBUSER:-paperless}" - # Disable warning, host and port can't have spaces - # shellcheck disable=SC2086 - while [ ! "$(pg_isready -h ${host} -p ${port} --username ${user})" ]; do - - if [ $attempt_num -eq $max_attempts ]; then - echo "${log_prefix} Unable to connect to database." - exit 1 - else - echo "${log_prefix} Attempt $attempt_num failed! Trying again in 5 seconds..." - fi - - attempt_num=$(("$attempt_num" + 1)) - sleep 5 + while ! pg_isready -h "${host}" -p "${port}" --username "${user}"; do + delay_next_attempt done - # Extra in case this is a first start - sleep 5 - echo "Connected to PostgreSQL" + echo "${LOG_PREFIX} Connected to PostgreSQL" } wait_for_mariadb() { - echo "${log_prefix} Waiting for MariaDB to start..." + echo "${LOG_PREFIX} Waiting for MariaDB to start..." - local -r host="${PAPERLESS_DBHOST:=localhost}" - local -r port="${PAPERLESS_DBPORT:=3306}" + local -r host="${PAPERLESS_DBHOST:-localhost}" + local -r port="${PAPERLESS_DBPORT:-3306}" - local attempt_num=1 - local -r max_attempts=5 - - # Disable warning, host and port can't have spaces - # shellcheck disable=SC2086 - while ! true > /dev/tcp/$host/$port; do - - if [ $attempt_num -eq $max_attempts ]; then - echo "${log_prefix} Unable to connect to database." - exit 1 - else - echo "${log_prefix} Attempt $attempt_num failed! Trying again in 5 seconds..." - - fi - - attempt_num=$(("$attempt_num" + 1)) - sleep 5 + while ! true > "/dev/tcp/$host/$port"; do + delay_next_attempt done - echo "Connected to MariaDB" + echo "${LOG_PREFIX} Connected to MariaDB" } -if [[ "${PAPERLESS_DBENGINE}" == "mariadb" ]]; then - echo "${log_prefix} Waiting for MariaDB to report ready" +if [[ "${PAPERLESS_DBENGINE:-}" == "mariadb" ]]; then wait_for_mariadb -elif [[ -n "${PAPERLESS_DBHOST}" ]]; then - echo "${log_prefix} Waiting for postgresql to report ready" +elif [[ -n "${PAPERLESS_DBHOST:-}" ]]; then wait_for_postgres fi - echo "${log_prefix} Database is ready" +echo "${LOG_PREFIX} Database is ready"