fix: lazy-connect + retry for ioredis to avoid blocked startup
This commit is contained in:
parent
c9a86790de
commit
f4af81ef02
|
|
@ -1,4 +1,5 @@
|
|||
import env from '#start/env'
|
||||
import logger from '@adonisjs/core/services/logger'
|
||||
import { Redis } from 'ioredis'
|
||||
|
||||
// BullMQ treats a plain `{host, port}` connection object as a recipe: every
|
||||
|
|
@ -14,6 +15,24 @@ const sharedConnection = new Redis({
|
|||
port: env.get('REDIS_PORT') ?? 6379,
|
||||
db: env.get('REDIS_DB') ?? 0,
|
||||
maxRetriesPerRequest: null,
|
||||
// Don't open the socket at module import time. Importing this file (during
|
||||
// `node ace migration:run`, `db:seed`, `queue:work`, or HTTP boot) otherwise
|
||||
// races Docker's network/DNS lifecycle: on a fresh `up` the `redis` name is
|
||||
// not yet resolvable (EAI_AGAIN), and on a recreate the embedded DNS briefly
|
||||
// serves the previous container's IP (ECONNREFUSED to the stale address).
|
||||
// Lazy-connecting defers the first dial until BullMQ actually needs Redis —
|
||||
// after the entrypoint has confirmed it is reachable — so each (re)connect
|
||||
// re-resolves the current IP instead of hammering a stale one.
|
||||
lazyConnect: true,
|
||||
// Bounded, backing-off retry so a transient outage doesn't busy-loop.
|
||||
retryStrategy: (times) => Math.min(times * 200, 2000),
|
||||
})
|
||||
|
||||
// Without an `error` listener ioredis logs the raw "[ioredis] Unhandled error
|
||||
// event" lines and, on some Node versions, an EventEmitter `error` with no
|
||||
// listener can crash the process. Route them through the app logger instead.
|
||||
sharedConnection.on('error', (err) => {
|
||||
logger.error({ err }, 'Shared Redis connection error')
|
||||
})
|
||||
|
||||
const queueConfig = {
|
||||
|
|
|
|||
|
|
@ -7,6 +7,29 @@ echo "Starting entrypoint script..."
|
|||
# Ensure required storage directories exist (volume may be freshly mounted)
|
||||
mkdir -p /app/storage/logs /app/storage/kb_uploads
|
||||
|
||||
# Wait for Redis to be reachable before booting anything that opens a BullMQ
|
||||
# connection. `depends_on: condition: service_healthy` only gates a clean
|
||||
# `up --recreate`; it is NOT re-checked on `docker compose restart` or a
|
||||
# `restart: unless-stopped` bounce, so without this the app can race Docker's
|
||||
# DNS (EAI_AGAIN) or dial a restarted Redis container's stale IP (ECONNREFUSED).
|
||||
# This isn't load-bearing since legacy installs used a mounted entrypoint script
|
||||
# that may override this script, but it's a cost-nothing check for newer installs.
|
||||
# The real check is done by the application itself, but this provides a safety net.
|
||||
REDIS_HOST="${REDIS_HOST:-redis}"
|
||||
REDIS_PORT="${REDIS_PORT:-6379}"
|
||||
echo "Waiting for Redis at ${REDIS_HOST}:${REDIS_PORT}..."
|
||||
for i in $(seq 1 60); do
|
||||
if node -e "const net=require('net');const s=net.connect(Number(process.env.REDIS_PORT||6379),process.env.REDIS_HOST||'redis');s.on('connect',()=>{s.end();process.exit(0)});s.on('error',()=>process.exit(1));" 2>/dev/null; then
|
||||
echo "Redis is up and running!"
|
||||
break
|
||||
fi
|
||||
if [ "$i" -eq 60 ]; then
|
||||
echo "Timed out waiting for Redis at ${REDIS_HOST}:${REDIS_PORT}" >&2
|
||||
exit 1
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
|
||||
# Run AdonisJS migrations
|
||||
echo "Running AdonisJS migrations..."
|
||||
node ace migration:run --force
|
||||
|
|
|
|||
Loading…
Reference in New Issue