]> git.ipfire.org Git - thirdparty/paperless-ngx.git/commitdiff
Enhancement: speed-up docker container startup (#11134)
authorMichael Martin <flrgh@protonmail.com>
Mon, 17 Nov 2025 21:11:49 +0000 (13:11 -0800)
committerGitHub <noreply@github.com>
Mon, 17 Nov 2025 21:11:49 +0000 (13:11 -0800)
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.

docker/rootfs/etc/s6-overlay/s6-rc.d/init-wait-for-db/run

index ede8a654a6ef7f4c87bbbf7e486de7eae77c7d36..1739edd61454ffcee1ca90f4af142bb6c8d55b37 100755 (executable)
@@ -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
 
-wait_for_postgres() {
-       local attempt_num=1
-       local -r max_attempts=5
+declare -r LOG_PREFIX="[init-db-wait]"
 
-       echo "${log_prefix} Waiting for PostgreSQL to start..."
+declare -ri TIMEOUT=60
+declare -i ATTEMPT=0
+declare -i DELAY=0
+declare -i STARTED_AT=${EPOCHSECONDS:?EPOCHSECONDS var unset}
 
-       local -r host="${PAPERLESS_DBHOST:-localhost}"
-       local -r port="${PAPERLESS_DBPORT:-5432}"
-       local -r user="${PAPERLESS_DBUSER:-paperless}"
+delay_next_attempt() {
+    local -i elapsed=$(( EPOCHSECONDS - STARTED_AT ))
+    local -ri remaining=$(( TIMEOUT - elapsed ))
 
-       # Disable warning, host and port can't have spaces
-       # shellcheck disable=SC2086
-       while [ ! "$(pg_isready -h ${host} -p ${port} --username ${user})" ]; do
+    if (( remaining <= 0 )); then
+        echo "${LOG_PREFIX} Unable to connect after $elapsed seconds."
+        exit 1
+    fi
 
-               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
+    DELAY+=1
 
-               attempt_num=$(("$attempt_num" + 1))
-               sleep 5
-       done
-       # Extra in case this is a first start
-       sleep 5
-       echo "Connected to PostgreSQL"
-}
+    # clamp to remaining time
+    if (( DELAY > remaining )); then
+        DELAY=$remaining
+    fi
 
-wait_for_mariadb() {
-       echo "${log_prefix} Waiting for MariaDB to start..."
+    ATTEMPT+=1
+    echo "${LOG_PREFIX} Attempt $ATTEMPT failed! Trying again in $DELAY seconds..."
+    sleep "$DELAY"
+}
 
-       local -r host="${PAPERLESS_DBHOST:=localhost}"
-       local -r port="${PAPERLESS_DBPORT:=3306}"
+wait_for_postgres() {
+       echo "${LOG_PREFIX} Waiting for PostgreSQL to start..."
 
-       local attempt_num=1
-       local -r max_attempts=5
+       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 ! true > /dev/tcp/$host/$port; do
+       while ! pg_isready -h "${host}" -p "${port}" --username "${user}"; do
+        delay_next_attempt
+       done
+       echo "${LOG_PREFIX} Connected to PostgreSQL"
+}
 
-               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..."
+wait_for_mariadb() {
+       echo "${LOG_PREFIX} Waiting for MariaDB to start..."
 
-               fi
+       local -r host="${PAPERLESS_DBHOST:-localhost}"
+       local -r port="${PAPERLESS_DBPORT:-3306}"
 
-               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"