Skip to content

Conversation

@ildyria
Copy link
Member

@ildyria ildyria commented Dec 28, 2025

Implement container mode selection to enable separate queue worker containers, allowing horizontal scaling of background job processing independently from web servers.

Changes:

  • Add LYCHEE_MODE environment variable detection to entrypoint.sh
    • web (default): Runs FrankenPHP/Octane web server
    • worker: Runs Laravel queue:work in auto-restart loop
    • Invalid values: Exit with error message
  • Implement auto-restart loop for worker mode
    • Configurable via QUEUE_NAMES (queue priority)
    • Configurable via WORKER_MAX_TIME (restart interval)
    • Automatic 5-second delay between restarts
  • Add lychee_worker service to docker-compose.yaml (commented out)
    • Security hardening matching web service
    • Resource limits and healthcheck
    • Shared volumes for photo processing
  • Add queue connection validation with warnings
  • Create comprehensive deployment guide (deploy-worker-mode.md)
  • Update knowledge map with worker mode architecture
  • Add Dockerfile comments documenting LYCHEE_MODE behavior
  • Create shell script unit tests for mode detection

Completed tasks:

  • T-002-01: Shell script unit tests (6/6 passing)
  • T-002-02: LYCHEE_MODE detection implementation
  • T-002-06: Queue connection validation
  • T-002-07: QUEUE_CONNECTION=sync warning
  • T-002-08: Docker Compose worker service
  • T-002-23: Knowledge map updates
  • T-002-24: How-to deployment guide
  • T-002-25: Dockerfile documentation
  • T-002-26: Roadmap status update

Pending (requires Docker):

  • Manual integration tests (T-002-03 to T-002-22)
  • Queue priority configuration verification
  • Worker healthcheck script implementation
  • SIGTERM graceful shutdown validation

Spec impact: Feature 002 - Worker Mode Support

  • Spec: docs/specs/4-architecture/features/002-worker-mode/spec.md
  • Plan: docs/specs/4-architecture/features/002-worker-mode/plan.md
  • Tasks: docs/specs/4-architecture/features/002-worker-mode/tasks.md

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Worker Mode for background job processing with auto-restart and configurable queue names/timeouts; supports running workers in separate containers for horizontal scaling.
  • Configuration Changes

    • Updated default cache/queue settings, added a commented example for enabling database-backed queues, and fixed a wording typo in env comments.
  • Documentation

    • Added comprehensive Worker Mode deployment and architecture guides.
  • Tests

    • New entrypoint mode detection tests and adjusted import test expectations.

✏️ Tip: You can customize this high-level summary in your review settings.

Implement container mode selection to enable separate queue worker
containers, allowing horizontal scaling of background job processing
independently from web servers.

Changes:
- Add LYCHEE_MODE environment variable detection to entrypoint.sh
  - web (default): Runs FrankenPHP/Octane web server
  - worker: Runs Laravel queue:work in auto-restart loop
  - Invalid values: Exit with error message
- Implement auto-restart loop for worker mode
  - Configurable via QUEUE_NAMES (queue priority)
  - Configurable via WORKER_MAX_TIME (restart interval)
  - Automatic 5-second delay between restarts
- Add lychee_worker service to docker-compose.yaml (commented out)
  - Security hardening matching web service
  - Resource limits and healthcheck
  - Shared volumes for photo processing
- Add queue connection validation with warnings
- Create comprehensive deployment guide (deploy-worker-mode.md)
- Update knowledge map with worker mode architecture
- Add Dockerfile comments documenting LYCHEE_MODE behavior
- Create shell script unit tests for mode detection

Completed tasks:
- T-002-01: Shell script unit tests (6/6 passing)
- T-002-02: LYCHEE_MODE detection implementation
- T-002-06: Queue connection validation
- T-002-07: QUEUE_CONNECTION=sync warning
- T-002-08: Docker Compose worker service
- T-002-23: Knowledge map updates
- T-002-24: How-to deployment guide
- T-002-25: Dockerfile documentation
- T-002-26: Roadmap status update

Pending (requires Docker):
- Manual integration tests (T-002-03 to T-002-22)
- Queue priority configuration verification
- Worker healthcheck script implementation
- SIGTERM graceful shutdown validation

Spec impact: Feature 002 - Worker Mode Support
- Spec: docs/specs/4-architecture/features/002-worker-mode/spec.md
- Plan: docs/specs/4-architecture/features/002-worker-mode/plan.md
- Tasks: docs/specs/4-architecture/features/002-worker-mode/tasks.md

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
@coderabbitai
Copy link

coderabbitai bot commented Dec 28, 2025

📝 Walkthrough

Walkthrough

Adds a worker mode to container images: mode-aware entrypoint (LYCHEE_MODE=web|worker), a new lychee_worker service and Docker config, updated queue/cache settings, documentation and specs for worker deployment, and tests for entrypoint mode detection and a directory listing expectation.

Changes

Cohort / File(s) Summary
Environment example
\.env.example
Fixed typo in QUEUE_CONNECTION comment ("defered" → "deferred"); added explanatory comments and a commented example # QUEUE_CONNECTION=database.
Container image
Dockerfile
Added documentation block describing LYCHEE_MODE (default web, worker when set) and ensured CMD runs Octane with FrankenPHP.
Compose & services
docker-compose.yaml
Added lychee_worker service (security hardening, resource limits, env, volumes, healthcheck, logging, networks) for background queue processing; removed commented QUEUE_CONNECTION: sync snippet; updated CACHE_PREFIX to lychee_cache.
Entrypoint script
docker/scripts/entrypoint.sh
Replaced unconditional exec with mode selection: web executes CMD; worker runs a persistent, auto-restarting php artisan queue:work loop honoring QUEUE_NAMES, WORKER_MAX_TIME, and QUEUE_CONNECTION, with validation, logging, restart/backoff, and graceful shutdown handling.
Docs: deploy guide & specs
docs/specs/2-how-to/deploy-worker-mode.md, docs/specs/4-architecture/features/002-worker-mode/..., docs/specs/4-architecture/knowledge-map.md, docs/specs/4-architecture/roadmap.md
Added comprehensive deploy-worker-mode guide; standardized terminology from "docker-compose" → "docker compose"; updated plan/specs/knowledge-map/roadmap to mark Worker Mode complete (2025-12-28) and document behavior/controls (LYCHEE_MODE, QUEUE_NAMES, WORKER_MAX_TIME, auto-restart).
Tasks & checklist
docs/specs/4-architecture/features/002-worker-mode/tasks.md
Marked many checklist items complete, adjusted verification steps, default values (e.g., QUEUE_NAMES, WORKER_MAX_TIME), and simplified notes about healthchecks and scaling.
Tests
tests/docker/test-entrypoint-mode-detection.sh, tests/ImageProcessing/Import/ImportFromServerBrowseTest.php
Added shell test validating entrypoint mode detection (web/worker/default/invalid) with pass/fail reporting; updated image import browse test to expect an additional docker directory entry.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐇 I nudged the mode switch, soft and spry,
Web wakes with dawn, the worker hums nearby,
Queues march on, auto-restarts keep pace,
Logs glow like clover in a comfy place,
A rabbit cheers: deploy with grace!

Pre-merge checks

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov
Copy link

codecov bot commented Dec 28, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 90.36%. Comparing base (8ad85ec) to head (afb2f42).
⚠️ Report is 2 commits behind head on master.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@ildyria ildyria marked this pull request as ready for review December 28, 2025 21:43
@ildyria ildyria requested a review from a team as a code owner December 28, 2025 21:43
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (4)
docs/specs/2-how-to/deploy-worker-mode.md (1)

1-463: Add footer per coding guidelines.

This deployment guide is comprehensive and well-structured. However, per the coding guidelines for Markdown documentation files, add an hr line followed by "Last updated: [date]" at the bottom.

📝 Add footer

Add this at the end of the file (after line 463):

+
+---
+
+*Last updated: 2025-12-28*

Based on coding guidelines: "At the bottom of documentation files, add an hr line followed by 'Last updated: [date of the update]'"

docs/specs/4-architecture/knowledge-map.md (1)

156-156: Update last-updated date to match PR completion.

The knowledge map's last-updated date (December 22, 2025) predates the feature completion date (2025-12-28). Update to reflect the Worker Mode additions.

📝 Update date
-*Last updated: December 22, 2025*
+*Last updated: December 28, 2025*
docs/specs/4-architecture/features/002-worker-mode/tasks.md (1)

175-177: Consider standard notation for deferred task.

The [~] marker is non-standard for task checklists. While the deferral rationale is clear (FR-002-05 crash-loop detection deemed over-engineered for MVP), consider using a standard marker for tool compatibility.

Options:

  1. Use [ ] (pending) with "DEFERRED" in the title (current approach is fine)
  2. Move to "Notes / TODOs" section as a future enhancement
  3. Add a "## Deferred Tasks" section at the end

The current approach is acceptable given the clear explanation, but standardizing markers improves consistency with other task checklists.

docker-compose.yaml (1)

400-400: Consider simplifying healthcheck command.

The || exit 1 is redundant since pgrep already returns non-zero when no process matches. However, the explicit exit code improves readability and intent, so this is acceptable as-is.

Alternative (equivalent) healthcheck
-      test: ["CMD-SHELL", "pgrep -f 'queue:work' || exit 1"]
+      test: ["CMD-SHELL", "pgrep -f 'queue:work'"]
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fd63749 and d701738.

📒 Files selected for processing (12)
  • .env.example
  • Dockerfile
  • docker-compose.yaml
  • docker/scripts/entrypoint.sh
  • docs/specs/2-how-to/deploy-worker-mode.md
  • docs/specs/4-architecture/features/002-worker-mode/plan.md
  • docs/specs/4-architecture/features/002-worker-mode/spec.md
  • docs/specs/4-architecture/features/002-worker-mode/tasks.md
  • docs/specs/4-architecture/knowledge-map.md
  • docs/specs/4-architecture/roadmap.md
  • tests/ImageProcessing/Import/ImportFromServerBrowseTest.php
  • tests/docker/test-entrypoint-mode-detection.sh
🧰 Additional context used
📓 Path-based instructions (8)
**/*.php

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.php: Any new PHP file should contain the license header and have a single blank line after the opening PHP tag
Variable names should be in snake_case in PHP
Apply the PSR-4 coding standard in PHP
Use in_array() with true as the third parameter in PHP
Only use booleans in if statements, not integers or strings
Use strict comparison (===) instead of loose comparison (==)
Avoid code duplication in both if and else statements
Do not use empty() in PHP
Use the moneyphp/money library for handling monetary values in PHP
Never use floats or doubles to represent monetary values; use integers representing the smallest currency unit (e.g., cents for USD)

**/*.php: Write or extend executable specifications (unit, behaviour, or scenario tests) ahead of implementation, confirm they fail, and then drive code to green before refactoring. List the expected success, validation, and failure branches and add thin failing tests for each path.
For PHP code, adhere to conventions: license headers in new files, strict comparison (===), no empty(), in_array() with third parameter true, snake_case variables, PSR-4 standard, test base classes (AbstractTestCase for Unit, BaseApiWithDataTest for Feature_v2).
Always run phpunit tests. If a test remains red, disable it with a TODO, note the reason, and capture the follow-up in the relevant plan.
Spotless now uses Palantir Java Format 2.78.0 with a 120-character wrap; configure IDE formatters to match before pushing code changes.
Keep each increment's control flow flat by delegating validation/normalisation into tiny pure helpers that return simple enums or result records, then compose them instead of introducing inline branching that inflates the branch count per change.
When introducing new helpers/utilities or editing files prone to style violations (records, DTOs, generated adapters), run the narrowest applicable lint target (for example phpstan) before the full pipeline. Note the command in the related plan/task.
For PHP changes, ru...

Files:

  • tests/ImageProcessing/Import/ImportFromServerBrowseTest.php
tests/**/*.php

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

No need to mock the database in tests; use the in-memory SQLite database instead

Files:

  • tests/ImageProcessing/Import/ImportFromServerBrowseTest.php
**/*.md

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.md: Use Markdown format for documentation
At the bottom of documentation files, add an hr line followed by "Last updated: [date of the update]"

Files:

  • docs/specs/4-architecture/features/002-worker-mode/tasks.md
  • docs/specs/4-architecture/features/002-worker-mode/plan.md
  • docs/specs/4-architecture/knowledge-map.md
  • docs/specs/2-how-to/deploy-worker-mode.md
  • docs/specs/4-architecture/roadmap.md
  • docs/specs/4-architecture/features/002-worker-mode/spec.md
docs/specs/4-architecture/features/**/*.md

📄 CodeRabbit inference engine (AGENTS.md)

docs/specs/4-architecture/features/**/*.md: Author new specifications, feature plans, and task checklists using docs/specs/templates/feature-spec-template.md, docs/specs/templates/feature-plan-template.md, and docs/specs/templates/feature-tasks-template.md to keep structure, metadata, and verification notes uniform across features.
For any new UI feature or modification, include an ASCII mock-up in the specification (see docs/specs/4-architecture/spec-guidelines/ui-ascii-mockups.md).
When revising a specification, only document fallback or compatibility behaviour if the user explicitly asked for it; if instructions are unclear, pause and request confirmation instead of assuming a fallback.
For every task, refresh the relevant feature plan and note open questions; only move forward once the plan reflects the desired change. Update specs before code.
Update feature specs, feature plans, and tasks documents as progress is made and sync context to disk.
Capture prompt summaries, command sequences, and rationale in the active feature plan or an appendix referenced from it so downstream reviewers know how the change was produced (intent logging).
Track upcoming additions for contract tests, mutation analysis, and security/red-team prompt suites in the plans until automated jobs exist (quality gates).
Publish prompt and tool usage notes alongside the feature plan update so future agents understand how the iteration unfolded.

Files:

  • docs/specs/4-architecture/features/002-worker-mode/tasks.md
  • docs/specs/4-architecture/features/002-worker-mode/plan.md
  • docs/specs/4-architecture/features/002-worker-mode/spec.md
docs/specs/4-architecture/features/**/{spec,plan,tasks}.md

📄 CodeRabbit inference engine (AGENTS.md)

docs/specs/4-architecture/features/**/{spec,plan,tasks}.md: Start every feature by updating or creating its specification at docs/specs/4-architecture/features/-/spec.md, followed by plan and tasks documents after clarifications are resolved.
Generate or refresh the feature plan only after the specification is current and high-/medium-impact clarifications are resolved and recorded in the spec (plus ADRs where required).

Files:

  • docs/specs/4-architecture/features/002-worker-mode/tasks.md
  • docs/specs/4-architecture/features/002-worker-mode/plan.md
  • docs/specs/4-architecture/features/002-worker-mode/spec.md
docs/specs/4-architecture/features/**/tasks.md

📄 CodeRabbit inference engine (AGENTS.md)

docs/specs/4-architecture/features/**/tasks.md: Maintain a per-feature tasks checklist that mirrors the plan, orders tests before code, and keeps planned increments ≤90 minutes by preferring finer-grained entries and documenting sub-steps when something nears the limit.
Mark each task [x] in the feature's tasks.md as soon as it passes verification. Do not batch task completions—update the checklist after every individual task so progress is always visible.
Before committing, confirm every completed task in tasks.md is marked [x] and the roadmap status reflects current progress (validate task checklist).

Files:

  • docs/specs/4-architecture/features/002-worker-mode/tasks.md
docs/specs/4-architecture/knowledge-map.md

📄 CodeRabbit inference engine (AGENTS.md)

docs/specs/4-architecture/knowledge-map.md: Skim docs/specs/4-architecture/knowledge-map.md and the up-to-date module snapshot in docs/specs/architecture-graph.json before planning so new work reinforces the architectural relationships already captured there.
Maintain the knowledge map by adding, adjusting, or pruning entries whenever new modules, dependencies, or contracts appear.

Files:

  • docs/specs/4-architecture/knowledge-map.md
docs/specs/4-architecture/roadmap.md

📄 CodeRabbit inference engine (AGENTS.md)

docs/specs/4-architecture/roadmap.md: Update the roadmap regularly to reflect feature status and progress as work is made.
Keep high-level plans in docs/specs/4-architecture/roadmap.md, store each feature's spec/plan/tasks inside docs/specs/4-architecture/features/-/, and remove plans once work is complete.

Files:

  • docs/specs/4-architecture/roadmap.md
🧠 Learnings (21)
📚 Learning: 2025-12-28T18:12:55.752Z
Learnt from: ildyria
Repo: LycheeOrg/Lychee PR: 3901
File: app/Providers/AppServiceProvider.php:0-0
Timestamp: 2025-12-28T18:12:55.752Z
Learning: When using Laravel Octane's tick API, Octane::tick(...) returns an InvokeTickCallable that only has ->seconds(int) and ->immediate() methods. There is no ->every(N) method. Use the correct usage: Octane::tick('name', fn() => ...)->seconds(N) or Octane::tick('name', fn() => ..., N). Apply this guideline to PHP files across the project (not just AppServiceProvider.php).

Applied to files:

  • tests/ImageProcessing/Import/ImportFromServerBrowseTest.php
📚 Learning: 2025-12-22T14:12:18.082Z
Learnt from: CR
Repo: LycheeOrg/Lychee PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-22T14:12:18.082Z
Learning: Applies to docs/specs/4-architecture/features/**/tasks.md : Maintain a per-feature tasks checklist that mirrors the plan, orders tests before code, and keeps planned increments ≤90 minutes by preferring finer-grained entries and documenting sub-steps when something nears the limit.

Applied to files:

  • docs/specs/4-architecture/features/002-worker-mode/tasks.md
  • docs/specs/4-architecture/features/002-worker-mode/plan.md
📚 Learning: 2025-12-22T14:12:18.082Z
Learnt from: CR
Repo: LycheeOrg/Lychee PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-22T14:12:18.082Z
Learning: Applies to docs/specs/4-architecture/features/**/tasks.md : Mark each task [x] in the feature's tasks.md as soon as it passes verification. Do not batch task completions—update the checklist after every individual task so progress is always visible.

Applied to files:

  • docs/specs/4-architecture/features/002-worker-mode/tasks.md
📚 Learning: 2025-12-22T14:12:18.082Z
Learnt from: CR
Repo: LycheeOrg/Lychee PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-22T14:12:18.082Z
Learning: Applies to docs/specs/4-architecture/features/**/tasks.md : Before committing, confirm every completed task in tasks.md is marked [x] and the roadmap status reflects current progress (validate task checklist).

Applied to files:

  • docs/specs/4-architecture/features/002-worker-mode/tasks.md
📚 Learning: 2025-12-22T14:12:18.082Z
Learnt from: CR
Repo: LycheeOrg/Lychee PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-22T14:12:18.082Z
Learning: Applies to docs/specs/4-architecture/features/**/*.md : Update feature specs, feature plans, and tasks documents as progress is made and sync context to disk.

Applied to files:

  • docs/specs/4-architecture/features/002-worker-mode/tasks.md
  • docs/specs/4-architecture/features/002-worker-mode/plan.md
📚 Learning: 2025-12-22T14:12:18.082Z
Learnt from: CR
Repo: LycheeOrg/Lychee PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-22T14:12:18.082Z
Learning: Applies to docs/specs/4-architecture/features/**/*.md : For every task, refresh the relevant feature plan and note open questions; only move forward once the plan reflects the desired change. Update specs before code.

Applied to files:

  • docs/specs/4-architecture/features/002-worker-mode/tasks.md
  • docs/specs/4-architecture/features/002-worker-mode/plan.md
📚 Learning: 2025-12-22T14:12:18.082Z
Learnt from: CR
Repo: LycheeOrg/Lychee PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-22T14:12:18.082Z
Learning: Applies to docs/specs/4-architecture/features/**/*.md : Track upcoming additions for contract tests, mutation analysis, and security/red-team prompt suites in the plans until automated jobs exist (quality gates).

Applied to files:

  • docs/specs/4-architecture/features/002-worker-mode/tasks.md
  • docs/specs/4-architecture/features/002-worker-mode/plan.md
  • docs/specs/4-architecture/roadmap.md
  • docs/specs/4-architecture/features/002-worker-mode/spec.md
📚 Learning: 2025-12-22T14:12:18.082Z
Learnt from: CR
Repo: LycheeOrg/Lychee PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-22T14:12:18.082Z
Learning: Applies to docs/specs/4-architecture/features/**/*.md : Publish prompt and tool usage notes alongside the feature plan update so future agents understand how the iteration unfolded.

Applied to files:

  • docs/specs/4-architecture/features/002-worker-mode/tasks.md
  • docs/specs/4-architecture/features/002-worker-mode/plan.md
  • docs/specs/4-architecture/roadmap.md
📚 Learning: 2025-12-22T14:12:18.082Z
Learnt from: CR
Repo: LycheeOrg/Lychee PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-22T14:12:18.082Z
Learning: Applies to docs/specs/4-architecture/features/**/*.md : Author new specifications, feature plans, and task checklists using docs/specs/templates/feature-spec-template.md, docs/specs/templates/feature-plan-template.md, and docs/specs/templates/feature-tasks-template.md to keep structure, metadata, and verification notes uniform across features.

Applied to files:

  • docs/specs/4-architecture/features/002-worker-mode/tasks.md
  • docs/specs/4-architecture/features/002-worker-mode/plan.md
📚 Learning: 2025-12-22T14:12:18.082Z
Learnt from: CR
Repo: LycheeOrg/Lychee PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-22T14:12:18.082Z
Learning: Applies to docs/specs/4-architecture/open-questions.md : Update or close entries in docs/specs/4-architecture/open-questions.md after completing work.

Applied to files:

  • docs/specs/4-architecture/features/002-worker-mode/tasks.md
  • docs/specs/4-architecture/roadmap.md
📚 Learning: 2025-12-22T14:12:18.082Z
Learnt from: CR
Repo: LycheeOrg/Lychee PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-22T14:12:18.082Z
Learning: Applies to docs/specs/4-architecture/features/**/{spec,plan,tasks}.md : Generate or refresh the feature plan only after the specification is current and high-/medium-impact clarifications are resolved and recorded in the spec (plus ADRs where required).

Applied to files:

  • docs/specs/4-architecture/features/002-worker-mode/tasks.md
  • docs/specs/4-architecture/features/002-worker-mode/plan.md
📚 Learning: 2025-12-22T14:12:18.082Z
Learnt from: CR
Repo: LycheeOrg/Lychee PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-22T14:12:18.082Z
Learning: Applies to docs/specs/4-architecture/features/**/*.md : Capture prompt summaries, command sequences, and rationale in the active feature plan or an appendix referenced from it so downstream reviewers know how the change was produced (intent logging).

Applied to files:

  • docs/specs/4-architecture/features/002-worker-mode/plan.md
📚 Learning: 2025-12-22T14:12:18.082Z
Learnt from: CR
Repo: LycheeOrg/Lychee PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-22T14:12:18.082Z
Learning: Applies to docs/specs/4-architecture/roadmap.md : Keep high-level plans in docs/specs/4-architecture/roadmap.md, store each feature's spec/plan/tasks inside docs/specs/4-architecture/features/<NNN>-<feature-name>/, and remove plans once work is complete.

Applied to files:

  • docs/specs/4-architecture/features/002-worker-mode/plan.md
  • docs/specs/4-architecture/roadmap.md
📚 Learning: 2025-12-22T14:12:18.082Z
Learnt from: CR
Repo: LycheeOrg/Lychee PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-22T14:12:18.082Z
Learning: Applies to docs/specs/4-architecture/features/**/{spec,plan,tasks}.md : Start every feature by updating or creating its specification at docs/specs/4-architecture/features/<NNN>-<feature-name>/spec.md, followed by plan and tasks documents after clarifications are resolved.

Applied to files:

  • docs/specs/4-architecture/features/002-worker-mode/plan.md
📚 Learning: 2025-12-22T14:12:18.082Z
Learnt from: CR
Repo: LycheeOrg/Lychee PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-22T14:12:18.082Z
Learning: Applies to docs/specs/5-operations/analysis-gate-checklist.md : Run the analysis gate in docs/specs/5-operations/analysis-gate-checklist.md once spec, plan, and tasks agree; address findings before implementation.

Applied to files:

  • docs/specs/4-architecture/features/002-worker-mode/plan.md
📚 Learning: 2025-12-22T14:12:18.082Z
Learnt from: CR
Repo: LycheeOrg/Lychee PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-22T14:12:18.082Z
Learning: Before hand-off, review your own changes, rerun checks, and ensure documentation/test coverage matches the behaviour (RCI self-review).

Applied to files:

  • docs/specs/4-architecture/features/002-worker-mode/plan.md
📚 Learning: 2025-12-22T14:12:18.082Z
Learnt from: CR
Repo: LycheeOrg/Lychee PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-22T14:12:18.082Z
Learning: Once an increment passes static analysis (phpstan), tests (phpunit) and formatting (php-cs-fixer), prepare the commit for the operator instead of executing it yourself. Stage the requested files, run ./scripts/codex-commit-review.sh to obtain a Conventional Commit message with a Spec impact: line whenever docs and code change together.

Applied to files:

  • docs/specs/4-architecture/features/002-worker-mode/plan.md
📚 Learning: 2025-12-26T11:45:18.032Z
Learnt from: ildyria
Repo: LycheeOrg/Lychee PR: 3889
File: Dockerfile:8-23
Timestamp: 2025-12-26T11:45:18.032Z
Learning: In multi-stage Dockerfiles for the Lychee project, using `--ignore-platform-reqs` in the composer build stage is acceptable because it's only used to generate vendor files that are copied to the production stage. The platform requirements that matter are in the final production image, not the intermediate build stage.

Applied to files:

  • docs/specs/4-architecture/features/002-worker-mode/plan.md
  • docker-compose.yaml
📚 Learning: 2025-09-03T14:22:58.633Z
Learnt from: ildyria
Repo: LycheeOrg/Lychee PR: 3673
File: docs/add-oauth-provider.md:36-49
Timestamp: 2025-09-03T14:22:58.633Z
Learning: Lychee uses Laravel 12 but deliberately maintains the old infrastructure model without migrating to newer Laravel 11+ patterns. They continue using EventServiceProvider for event registration rather than the newer Event::listen approach in AppServiceProvider, so documentation should reflect the traditional EventServiceProvider pattern.

Applied to files:

  • docs/specs/4-architecture/knowledge-map.md
📚 Learning: 2025-12-26T11:45:18.032Z
Learnt from: ildyria
Repo: LycheeOrg/Lychee PR: 3889
File: Dockerfile:8-23
Timestamp: 2025-12-26T11:45:18.032Z
Learning: In multi-stage Dockerfiles (as used in Lychee), you may use --ignore-platform-reqs in the composer build stage when generating vendor files, because this stage only affects vendor generation and the final production image is what enforces platform requirements. Ensure: (1) this flag is confined to the build stage and does not affect the production runtime image, (2) the final stage uses the correct platform constraints and installed extensions, and (3) the produced vendor files are compatible with the production image’s PHP/runtime platform. This pattern should be applied to all Dockerfiles that contain a build stage with composer, not just a single file.

Applied to files:

  • Dockerfile
📚 Learning: 2025-12-22T14:12:18.082Z
Learnt from: CR
Repo: LycheeOrg/Lychee PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-22T14:12:18.082Z
Learning: Applies to docs/specs/4-architecture/roadmap.md : Update the roadmap regularly to reflect feature status and progress as work is made.

Applied to files:

  • docs/specs/4-architecture/roadmap.md
🪛 LanguageTool
docs/specs/4-architecture/features/002-worker-mode/tasks.md

[grammar] ~75-~75: Use a hyphen to join words.
Context: ...xtension - [x] T-002-08 – Extend docker compose.yaml with lychee_worker service ...

(QB_NEW_EN_HYPHEN)


[grammar] ~76-~76: Use a hyphen to join words.
Context: ...service configuration to existing docker compose.yaml with shared volumes and env...

(QB_NEW_EN_HYPHEN)


[grammar] ~122-~122: Use a hyphen to join words.
Context: ...nvironment variable documented in docker compose (lines 343-346) Notes: TestW...

(QB_NEW_EN_HYPHEN)


[grammar] ~125-~125: Use a hyphen to join words.
Context: ...ment QUEUE_NAMES configuration in docker compose.yaml comments. Intent: Opera...

(QB_NEW_EN_HYPHEN)


[grammar] ~128-~128: Use a hyphen to join words.
Context: ...erification commands:_ - Review docker compose.yaml worker service environment ...

(QB_NEW_EN_HYPHEN)


[style] ~129-~129: The words ‘explains’ and ‘explanation’ are quite similar. Consider replacing ‘explains’ with a different word.
Context: ...service environment section - Comment explains QUEUE_NAMES usage with example: "high,d...

(VERB_NOUN_SENT_LEVEL_REP)


[grammar] ~149-~149: Use a hyphen to join words.
Context: ... WORKER_MAX_TIME configuration in docker compose.yaml comments. Intent: Opera...

(QB_NEW_EN_HYPHEN)


[grammar] ~152-~152: Use a hyphen to join words.
Context: ...erification commands:_ - Review docker compose.yaml worker service environment ...

(QB_NEW_EN_HYPHEN)


[style] ~153-~153: The words ‘explains’ and ‘explanation’ are quite similar. Consider replacing ‘explains’ with a different word.
Context: ...service environment section - Comment explains WORKER_MAX_TIME purpose (memory leak mi...

(VERB_NOUN_SENT_LEVEL_REP)


[grammar] ~168-~168: Use a hyphen to join words.
Context: ...02-19 – Healthcheck documented in docker compose.yaml. Intent: Operator guida...

(QB_NEW_EN_HYPHEN)


[grammar] ~171-~171: Use a hyphen to join words.
Context: ...erification commands:_ - Review docker compose.yaml lines 397-404 - Comment e...

(QB_NEW_EN_HYPHEN)


[locale-violation] ~177-~177: The phrase ‘in future’ is British English. Did you mean: “in the future”?
Context: ... (pgrep) is adequate for MVP. If needed in future, can implement crash-loop detection as ...

(IN_FUTURE)


[grammar] ~190-~190: Use a hyphen to join words.
Context: ...ent graceful shutdown behavior in docker compose.yaml comments. Intent: Opera...

(QB_NEW_EN_HYPHEN)


[grammar] ~193-~193: Use a hyphen to join words.
Context: ...erification commands:_ - Review docker compose.yaml worker service environment ...

(QB_NEW_EN_HYPHEN)

docs/specs/4-architecture/features/002-worker-mode/plan.md

[grammar] ~262-~262: Use a hyphen to join words.
Context: ...nsion** Goal: Extend existing docker compose.yaml with optional worker servic...

(QB_NEW_EN_HYPHEN)


[grammar] ~269-~269: Use a hyphen to join words.
Context: ... 1. Research: Review existing docker compose.yaml structure (lychee_api, lych...

(QB_NEW_EN_HYPHEN)


[grammar] ~270-~270: Use a hyphen to join words.
Context: ...ement:** Add worker service to existing docker compose.yaml: ```yaml # Add this ...

(QB_NEW_EN_HYPHEN)


[grammar] ~631-~631: Use a hyphen to join words.
Context: ...rators can deploy worker mode via docker compose.yaml (lychee_worker service).

(QB_NEW_EN_HYPHEN)

⏰ Context from checks skipped due to timeout of 180000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (19)
  • GitHub Check: 3️⃣ Dockerfile Lint
  • GitHub Check: 2️⃣ PHP dist / 8.5 - postgresql
  • GitHub Check: 2️⃣ PHP dist / 8.5 - sqlite
  • GitHub Check: 2️⃣ PHP dist / 8.4 - sqlite
  • GitHub Check: 2️⃣ PHP dist / 8.5 - mariadb
  • GitHub Check: 2️⃣ PHP dist / 8.4 - mariadb
  • GitHub Check: 2️⃣ PHP dist / 8.4 - postgresql
  • GitHub Check: 1️⃣ PHP tests / 8.5 - sqlite -- Feature_v2
  • GitHub Check: 1️⃣ PHP tests / 8.5 - sqlite -- Unit
  • GitHub Check: 1️⃣ PHP tests / 8.5 - mariadb -- Webshop
  • GitHub Check: 1️⃣ PHP tests / 8.5 - postgresql -- Unit
  • GitHub Check: 1️⃣ PHP tests / 8.5 - postgresql -- Feature_v2
  • GitHub Check: 1️⃣ PHP tests / 8.5 - postgresql -- Webshop
  • GitHub Check: 1️⃣ PHP tests / 8.5 - postgresql -- ImageProcessing
  • GitHub Check: 1️⃣ PHP tests / 8.5 - mariadb -- Unit
  • GitHub Check: 1️⃣ PHP tests / 8.5 - sqlite -- Webshop
  • GitHub Check: 1️⃣ PHP tests / 8.5 - sqlite -- ImageProcessing
  • GitHub Check: 1️⃣ PHP tests / 8.5 - mariadb -- Feature_v2
  • GitHub Check: 1️⃣ PHP tests / 8.5 - mariadb -- ImageProcessing
🔇 Additional comments (10)
docs/specs/4-architecture/roadmap.md (1)

15-15: LGTM! Feature completion documented correctly.

The Worker Mode Support feature is appropriately marked as completed with a clear completion date and concise summary of deliverables.

docs/specs/4-architecture/features/002-worker-mode/spec.md (1)

36-36: LGTM! Terminology standardized to Docker Compose v2.

The updates correctly use docker compose (the v2 CLI command) instead of docker-compose. This aligns with current Docker Compose best practices and matches the terminology used throughout the PR.

Also applies to: 46-46, 63-63, 100-100, 126-126, 182-182

docs/specs/4-architecture/features/002-worker-mode/plan.md (1)

629-631: LGTM! Plan status correctly updated to Complete.

The plan appropriately reflects the feature's production-ready status with completion date and clear next steps for deployment.

docs/specs/4-architecture/knowledge-map.md (1)

28-34: LGTM! Worker Mode architecture documented clearly.

The Infrastructure Layer section now includes comprehensive Worker Mode documentation covering mode selection, auto-restart behavior, configuration, and deployment guidance.

docs/specs/4-architecture/features/002-worker-mode/tasks.md (1)

15-196: LGTM! Tasks comprehensively documented with verification steps.

The task checklist is thorough with clear intent statements, verification commands, and implementation notes for each task. The progression from tests-first to implementation reflects good practices.

Dockerfile (1)

143-147: LGTM! Clear documentation of container mode behavior.

The added comments effectively document the LYCHEE_MODE environment variable's impact on container behavior and reference the deployment guide for operator guidance.

tests/ImageProcessing/Import/ImportFromServerBrowseTest.php (1)

41-41: LGTM: Test updated to include new 'docker' directory.

The addition of 'docker' to the expected directory list is correct and properly positioned in the alphabetically sorted array.

docker-compose.yaml (1)

289-413: Well-structured worker service configuration.

The lychee_worker service is comprehensively configured with:

  • Appropriate security hardening matching the API service
  • Resource limits suitable for background job processing
  • Shared volumes for photo processing access
  • Environment variables aligned with worker mode requirements

One observation: Line 336 hardcodes LYCHEE_MODE: worker rather than using ${LYCHEE_MODE:-worker}. This prevents override from .env, which may be intentional for operational clarity (ensuring worker containers always run in worker mode), but consider whether environment-level override would be useful for testing scenarios.

tests/docker/test-entrypoint-mode-detection.sh (1)

1-137: Excellent test coverage for mode detection logic.

This shell script test suite demonstrates good testing practices:

  • Proper use of portable sh syntax (not bash-specific features)
  • Comprehensive coverage of success and failure paths (web, worker, unset, invalid modes)
  • Clean helper function design with pattern matching and exit code verification
  • Proper cleanup of temporary test artifacts
  • Clear color-coded output for test results

The test structure aligns well with the entrypoint.sh behavior it validates.

docker/scripts/entrypoint.sh (1)

80-143: Well-designed worker mode implementation.

The mode detection and worker loop structure is solid:

  • Clean case-based mode switching with appropriate defaults
  • Auto-restart loop properly handles both clean exits and failures (after fixing EXIT_CODE bug)
  • Environment-driven configuration (QUEUE_NAMES, WORKER_MAX_TIME, QUEUE_CONNECTION)
  • Helpful warning for QUEUE_CONNECTION=sync
  • Reasonable 5-second restart delay prevents thrashing
  • Error handling for invalid LYCHEE_MODE values

The infinite loop design is appropriate for a long-running worker process with memory leak mitigation (--max-time) and crash recovery.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
docker/scripts/entrypoint.sh (1)

117-127: Consider making --timeout configurable.

The job timeout is hardcoded to 3600 seconds (1 hour). If users have legitimate long-running jobs (e.g., large video processing), they cannot override this without modifying the script.

🔧 Optional: Add WORKER_TIMEOUT environment variable
         QUEUE_NAMES=${QUEUE_NAMES:-default}
         WORKER_MAX_TIME=${WORKER_MAX_TIME:-3600}
+        WORKER_TIMEOUT=${WORKER_TIMEOUT:-3600}
         QUEUE_CONNECTION=${QUEUE_CONNECTION:-sync}

         echo "📋 Queue names: $QUEUE_NAMES"
         echo "⏱️  Max time: ${WORKER_MAX_TIME}s"
+        echo "⏱️  Job timeout: ${WORKER_TIMEOUT}s"
         echo "📡 Queue connection: $QUEUE_CONNECTION"
             php artisan queue:work \
                 --queue="$QUEUE_NAMES" \
                 --tries=3 \
-                --timeout=3600 \
+                --timeout="$WORKER_TIMEOUT" \
                 --sleep=3 \
                 --max-time="$WORKER_MAX_TIME" || EXIT_CODE=$?
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d701738 and a750598.

📒 Files selected for processing (2)
  • .env.example
  • docker/scripts/entrypoint.sh
🚧 Files skipped from review as they are similar to previous changes (1)
  • .env.example
⏰ Context from checks skipped due to timeout of 180000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (20)
  • GitHub Check: 2️⃣ PHP dist / 8.5 - mariadb
  • GitHub Check: 2️⃣ PHP dist / 8.4 - postgresql
  • GitHub Check: 2️⃣ PHP dist / 8.4 - sqlite
  • GitHub Check: 2️⃣ PHP dist / 8.4 - mariadb
  • GitHub Check: 1️⃣ PHP tests / 8.5 - sqlite -- ImageProcessing
  • GitHub Check: 1️⃣ PHP tests / 8.5 - sqlite -- Webshop
  • GitHub Check: 1️⃣ PHP tests / 8.5 - postgresql -- Install
  • GitHub Check: 1️⃣ PHP tests / 8.4 - postgresql -- Install
  • GitHub Check: 1️⃣ PHP tests / 8.5 - sqlite -- Unit
  • GitHub Check: 1️⃣ PHP tests / 8.5 - postgresql -- ImageProcessing
  • GitHub Check: 1️⃣ PHP tests / 8.5 - postgresql -- Unit
  • GitHub Check: 1️⃣ PHP tests / 8.5 - sqlite -- Feature_v2
  • GitHub Check: 1️⃣ PHP tests / 8.5 - mariadb -- ImageProcessing
  • GitHub Check: 1️⃣ PHP tests / 8.5 - postgresql -- Webshop
  • GitHub Check: 1️⃣ PHP tests / 8.5 - mariadb -- Webshop
  • GitHub Check: 1️⃣ PHP tests / 8.5 - postgresql -- Feature_v2
  • GitHub Check: 1️⃣ PHP tests / 8.5 - mariadb -- Feature_v2
  • GitHub Check: 1️⃣ PHP tests / 8.5 - mariadb -- Unit
  • GitHub Check: 1️⃣ PHP tests / 8.5 - mariadb -- Install
  • GitHub Check: 1️⃣ PHP tests / 8.4 - mariadb -- Install
🔇 Additional comments (3)
docker/scripts/entrypoint.sh (3)

80-88: LGTM on web mode implementation.

Clean and straightforward mode detection with sensible default. The exec "$@" properly replaces the shell with the CMD from Dockerfile, preserving signal handling for the web server.


114-115: Good fix for the EXIT_CODE reset issue.

Initializing EXIT_CODE=0 before each command execution correctly addresses the previous review concern. Now each iteration properly reflects its own exit status rather than carrying over from previous failures.


139-142: Good error handling for invalid mode.

Clear error message with guidance on valid values, and proper exit code 1 for failure.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
docker/scripts/entrypoint.sh (2)

93-107: Consider documenting the intentional "sync" default.

The code defaults QUEUE_CONNECTION to "sync" (line 96) but warns this is not recommended (lines 103-107). While this is a safe fallback strategy (works synchronously without configuration), the intent may not be immediately clear to maintainers.

Consider adding a brief comment explaining this is an intentional safe-default-with-warning pattern.

💡 Optional: Add clarifying comment
     # Get queue configuration from environment
     QUEUE_NAMES=${QUEUE_NAMES:-default}
     WORKER_MAX_TIME=${WORKER_MAX_TIME:-3600}
+    # Default to 'sync' as a safe fallback, but warn user to configure async queue
     QUEUE_CONNECTION=${QUEUE_CONNECTION:-sync}

109-113: Minor: Misplaced comment on line 113.

The trailing comment on line 113 ("Auto-restart loop...") describes the while loop that starts on line 116, not the trap statement. Consider moving it to line 115 for clarity.

💡 Optional: Improve comment placement
     # Track if we should keep running
     KEEP_RUNNING=true
 
     # Handle graceful shutdown
-    trap 'echo "🛑 Received shutdown signal, stopping..."; KEEP_RUNNING=false' TERM INT        # Auto-restart loop: if queue:work exits, restart it
-
-    # This handles memory leak mitigation (max-time) and crash recovery
+    trap 'echo "🛑 Received shutdown signal, stopping..."; KEEP_RUNNING=false' TERM INT
+
+    # Auto-restart loop: if queue:work exits, restart it
+    # This handles memory leak mitigation (max-time) and crash recovery
     while $KEEP_RUNNING; do
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a750598 and afb2f42.

📒 Files selected for processing (1)
  • docker/scripts/entrypoint.sh
⏰ Context from checks skipped due to timeout of 180000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (20)
  • GitHub Check: 2️⃣ PHP dist / 8.5 - mariadb
  • GitHub Check: 2️⃣ PHP dist / 8.4 - postgresql
  • GitHub Check: 2️⃣ PHP dist / 8.5 - postgresql
  • GitHub Check: 2️⃣ PHP dist / 8.4 - sqlite
  • GitHub Check: 2️⃣ PHP dist / 8.4 - mariadb
  • GitHub Check: 2️⃣ PHP dist / 8.5 - sqlite
  • GitHub Check: 1️⃣ PHP tests / 8.5 - sqlite -- Webshop
  • GitHub Check: 1️⃣ PHP tests / 8.5 - mariadb -- Webshop
  • GitHub Check: 1️⃣ PHP tests / 8.5 - postgresql -- Webshop
  • GitHub Check: 1️⃣ PHP tests / 8.5 - mariadb -- Feature_v2
  • GitHub Check: 1️⃣ PHP tests / 8.5 - sqlite -- Feature_v2
  • GitHub Check: 1️⃣ PHP tests / 8.5 - sqlite -- ImageProcessing
  • GitHub Check: 1️⃣ PHP tests / 8.5 - mariadb -- ImageProcessing
  • GitHub Check: 1️⃣ PHP tests / 8.5 - postgresql -- Unit
  • GitHub Check: 1️⃣ PHP tests / 8.4 - mariadb -- Install
  • GitHub Check: 1️⃣ PHP tests / 8.5 - postgresql -- Install
  • GitHub Check: 1️⃣ PHP tests / 8.5 - postgresql -- ImageProcessing
  • GitHub Check: 1️⃣ PHP tests / 8.5 - sqlite -- Unit
  • GitHub Check: 1️⃣ PHP tests / 8.5 - postgresql -- Feature_v2
  • GitHub Check: 1️⃣ PHP tests / 8.5 - mariadb -- Unit
🔇 Additional comments (3)
docker/scripts/entrypoint.sh (3)

80-88: LGTM! Clean mode detection and web mode implementation.

The default to "web" mode ensures backward compatibility, and using exec "$@" properly replaces the shell process with the Dockerfile CMD, ensuring signal propagation works correctly.


150-153: LGTM! Proper error handling for invalid mode.

The default case provides a clear error message and exits with an appropriate non-zero code, preventing silent failures from misconfiguration.


115-148: Worker loop implementation looks solid.

The auto-restart logic correctly:

  • Resets EXIT_CODE to 0 before each iteration (line 120) ✓
  • Captures exit codes from failed commands (line 132) ✓
  • Checks the shutdown flag before restarting (lines 140-144) ✓
  • Uses appropriate delays to prevent rapid restart loops (line 147) ✓

Laravel's queue:work command handles SIGTERM/SIGINT gracefully — it finishes the current job before exiting, ensuring jobs aren't killed mid-run. The signal-handling flow in this script correctly relies on that behavior: SIGTERM triggers the worker to exit cleanly, the loop condition prevents restart, and the script exits with the appropriate exit code.

@ildyria ildyria merged commit 3ef6912 into master Dec 28, 2025
38 checks passed
@ildyria ildyria deleted the add-worker-mode branch December 28, 2025 22:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants