Files
L-Ami-Fiduciaire/_bmad-output/implementation-artifacts/0-4-configure-redis-for-cache-queue-and-sessions.md
Saad Ibn-Ezzoubayr fd43a6f429 feat: complete Epic 0 — foundation migration & infrastructure setup
Stories 0.2-0.5: rename folders→declarations (backend+frontend), configure
Redis for cache/queue/sessions, add foundation database migrations
(permissions, archived_at), replace DeclarationStatus enum with architecture
lifecycle values, create DeclarationObserver for status transition validation
and auto-archive, fix controller status transitions to respect observer rules.

93 tests pass (240 assertions).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 18:25:32 +00:00

11 KiB

Story 0.4: Configure Redis for Cache, Queue & Sessions

Status: done

Story

As a platform operator, I want Redis configured as the driver for caching, job queues, and session storage, so that the application has the infrastructure foundation for queued email delivery, dashboard caching, and reliable session management.

Acceptance Criteria

  1. Given the Docker/Sail development environment is running, When Redis is configured, Then a Redis service is added to compose.yaml (or confirmed already present via Sail)
  2. And CACHE_STORE=redis is set in the environment configuration
  3. And QUEUE_CONNECTION=redis is set in the environment configuration
  4. And SESSION_DRIVER=redis is set in the environment configuration
  5. And the queue:work process is running and processes test jobs successfully
  6. And Cache::put() and Cache::get() operations work correctly
  7. And user sessions persist correctly across page navigations
  8. And the composer dev command starts the queue worker alongside the existing services
  9. And a failed_jobs table migration exists for monitoring failed queue jobs

Tasks / Subtasks

  • Task 1: Add Redis service to compose.yaml (AC: #1)

    • 1.1: Add redis service using redis:alpine image with port mapping ${FORWARD_REDIS_PORT:-6379}:6379, health check (redis-cli ping), volume for data persistence, and sail network
    • 1.2: Add redis to the depends_on list of the laravel.test service (alongside mailpit)
    • 1.3: Add named volume sail-redis under top-level volumes section
  • Task 2: Update environment configuration (AC: #2, #3, #4)

    • 2.1: In .env, change CACHE_STORE=database to CACHE_STORE=redis
    • 2.2: In .env, change QUEUE_CONNECTION=database to QUEUE_CONNECTION=redis
    • 2.3: In .env, change SESSION_DRIVER=database to SESSION_DRIVER=redis
    • 2.4: In .env, change REDIS_HOST=127.0.0.1 to REDIS_HOST=redis (Docker service name)
    • 2.5: In .env.example, apply the same 4 changes (CACHE_STORE, QUEUE_CONNECTION, SESSION_DRIVER, REDIS_HOST)
    • 2.6: Fix pre-existing typo in .env.example: CACHE_STORE=databasew corrected to CACHE_STORE=redis
  • Task 3: Update composer dev queue command (AC: #5, #8)

    • 3.1: In composer.json, change queue:listen --tries=1 --timeout=0 to queue:work --tries=3 --timeout=30 in the dev script (queue:work is more efficient with Redis driver)
    • 3.2: Apply same change to dev:ssr script
  • Task 4: Confirm failed_jobs table migration exists (AC: #9)

    • 4.1: Verify database/migrations/0001_01_01_000002_create_jobs_table.php already creates failed_jobs table — no new migration needed
  • Task 5: Verification and Testing (AC: #5, #6, #7)

    • 5.1: Rebuild and start Docker environment: docker compose up -d --build
    • 5.2: Verify Redis is accessible: docker compose exec redis redis-cli ping (expect PONG)
    • 5.3: Verify cache works: docker compose exec laravel.test php artisan tinker --execute="Cache::put('test', 'redis-works', 60); echo Cache::get('test');" (expect redis-works)
    • 5.4: Verify queue processes jobs: docker compose exec laravel.test php artisan queue:work --once with a dispatched test job
    • 5.5: Verify session works: log in via browser, navigate between pages, confirm session persists
    • 5.6: Run composer test — all existing tests must pass (78 tests, 222 assertions)
    • 5.7: Run npm run build — zero TypeScript errors (no frontend changes expected)

Dev Notes

Critical Architecture Constraints

  • Docker Compose ONLY: Everything runs under Docker Compose — no local installations allowed. All commands via docker compose exec laravel.test prefix.
  • Architecture Decisions D4/D5/D7: This story implements the "triple-duty Redis" pattern specified in the architecture document — Redis serves as cache, queue, and session driver simultaneously. This is the standard Laravel production pattern.
  • Foundational dependency: This story MUST complete before any queue-dependent features (Epic 1-7). Specifically: bulk email notifications (Story 3.4), dashboard caching (Story 2.1), nudge system (Story 3.2), and all ShouldQueue mail classes.
  • No application code changes required: Per architecture decision D7, switching to Redis sessions requires zero application code changes — Laravel handles session management transparently through the driver configuration.
  • phpredis extension: Already included in Sail's PHP 8.4 Docker image — no need to install or configure the extension.
  • queue:work vs queue:listen: Use queue:work instead of queue:listen. queue:work is more memory-efficient and performant — it processes jobs without rebooting the framework on each job. The --tries=3 flag aligns with NFR26 (retry up to 3 times).

Current State Analysis

Component Before (current) After (this story)
compose.yaml services laravel.test, mailpit laravel.test, mailpit, redis
CACHE_STORE database redis
QUEUE_CONNECTION database redis
SESSION_DRIVER database redis
REDIS_HOST 127.0.0.1 redis (Docker service name)
composer dev queue queue:listen --tries=1 --timeout=0 queue:work --tries=3 --timeout=30
failed_jobs table Already exists (migration 0001_01_01_000002) No change needed

Redis Service Configuration Reference

The Redis service in compose.yaml should follow Sail conventions:

redis:
    image: 'redis:alpine'
    ports:
        - '${FORWARD_REDIS_PORT:-6379}:6379'
    volumes:
        - 'sail-redis:/data'
    networks:
        - sail
    healthcheck:
        test: ["CMD", "redis-cli", "ping"]
        retries: 3
        timeout: 5s

Laravel Config Files (No Changes Needed)

The following config files already have Redis driver configurations ready — they read from .env variables:

  • config/cache.phpredis store defined at line 75
  • config/queue.phpredis connection defined at line 67
  • config/session.php — supports redis driver
  • config/database.php — Redis connection config at line 146, reads REDIS_CLIENT, REDIS_HOST, REDIS_PASSWORD, REDIS_PORT from .env

Previous Story Intelligence (Story 0.3)

Key learnings from Story 0.3 that apply:

  • Docker commands: All artisan/npm commands via docker compose exec laravel.test
  • Scope discipline: Story 0.2 review flagged cosmetic changes (EOF newlines, import reordering) as undisciplined scope — avoid changes outside story scope
  • Testing: Use composer test which clears config, runs Pint lint check, then php artisan test
  • No frontend changes: This is a pure infrastructure story — no Vue/TypeScript files should be modified

Git Intelligence

Recent commits:

  • d380df4 chore: add BMAD workflow commands for Claude and Cursor
  • 35545c2 feat: L'Ami Fiduciaire V1.0.0 — full codebase with Story 0.1 complete

Only 2 commits exist — the codebase is freshly established. Stories 0.2 and 0.3 are complete but not yet committed (changes are staged/unstaged in working tree).

Testing Standards

  • Use Pest syntax (test() closures), never PHPUnit class-based tests
  • RefreshDatabase is auto-applied via Pest.php — don't add manually
  • Run tests: composer test (clears config, runs Pint, runs tests)
  • Feature tests grouped by domain subdirectory
  • This story primarily requires manual verification (Redis connectivity, cache operations, session persistence) plus confirmation that all existing 78 tests still pass
  • Consider adding a smoke test in tests/Feature/ to verify Redis cache/queue connectivity if time permits

Project Structure Notes

  • Files modified: compose.yaml, .env, .env.example, composer.json (4 files total)
  • No new PHP classes, controllers, models, or Vue components
  • No new migrations (failed_jobs already exists)
  • Alignment with Docker Compose-first development approach

References

  • [Source: _bmad-output/planning-artifacts/epics.md#Story 0.4]
  • [Source: _bmad-output/planning-artifacts/architecture.md#D4 Caching Strategy]
  • [Source: _bmad-output/planning-artifacts/architecture.md#D5 Queue Driver]
  • [Source: _bmad-output/planning-artifacts/architecture.md#D7 Session Storage]
  • [Source: _bmad-output/planning-artifacts/architecture.md#Decision Impact Analysis]
  • [Source: _bmad-output/project-context.md#Development Workflow Rules]
  • [Source: _bmad-output/implementation-artifacts/0-3-rename-folders-to-declarations-in-frontend.md#Dev Notes]
  • [Source: compose.yaml (current — 2 services, no Redis)]
  • [Source: .env (lines 30, 38, 40, 45-48)]
  • [Source: config/cache.php, config/queue.php, config/session.php, config/database.php]
  • [Source: database/migrations/0001_01_01_000002_create_jobs_table.php (failed_jobs already exists)]
  • [Source: composer.json (lines 54-62, dev scripts)]

Change Log

  • 2026-03-12: Configured Redis as cache, queue, and session driver — added Redis service to Docker Compose, updated environment variables, switched queue:listen to queue:work
  • 2026-03-12: Code review — fixed 3 issues: (1) HIGH: added condition: service_healthy to redis depends_on in compose.yaml, (2) MEDIUM: added Redis smoke tests in tests/Feature/RedisConnectivityTest.php, (3) MEDIUM: documented pre-existing .env.example typo fix as subtask 2.6

Dev Agent Record

Agent Model Used

Claude Opus 4.6

Debug Log References

  • Closure-based job dispatch from tinker fails serialization (expected limitation) — verified queue connectivity via queue:work --once and config inspection instead

Completion Notes List

  • Task 1: Added redis service (redis:alpine) to compose.yaml with health check, data volume, and sail network. Added redis to laravel.test depends_on. Added sail-redis named volume.
  • Task 2: Updated .env and .env.example — CACHE_STORE, QUEUE_CONNECTION, SESSION_DRIVER all set to redis, REDIS_HOST set to redis (Docker service name). Also fixed typo databasewredis in .env.example.
  • Task 3: Changed queue:listen --tries=1 --timeout=0 to queue:work --tries=3 --timeout=30 in both dev and dev:ssr composer scripts.
  • Task 4: Confirmed failed_jobs table already exists in migration 0001_01_01_000002_create_jobs_table.php.
  • Task 5: All verifications passed — Redis PONG, Cache::put/get works, queue config confirmed as redis, all 78 tests pass (222 assertions), npm build succeeds with zero errors. Session verification (AC#7) requires manual browser testing by user.

File List

  • compose.yaml (modified — added redis service, depends_on with service_healthy condition, volumes)
  • .env (modified — CACHE_STORE, QUEUE_CONNECTION, SESSION_DRIVER, REDIS_HOST)
  • .env.example (modified — same 4 env vars, fixed pre-existing typo)
  • composer.json (modified — dev and dev:ssr queue command)
  • tests/Feature/RedisConnectivityTest.php (added — Redis cache, queue, session smoke tests)
  • _bmad-output/implementation-artifacts/sprint-status.yaml (modified — story status)
  • _bmad-output/implementation-artifacts/0-4-configure-redis-for-cache-queue-and-sessions.md (modified — task checkboxes, dev agent record, status)