Auto-start monica_site dj-queue worker on adama (#18)
Sync runner checkout / sync (push) Successful in 7s

## Summary
- Closes [#17](#17).
- Django deploy passes optional `host_apps.compose_profiles` as `COMPOSE_PROFILES` so compose profiles survive `up -d --remove-orphans`.
- Adama `monica_site` beta+prod set `compose_profiles: [worker]` (dj-queue singleton). Roslin / ai-server-4080 stay web-only.

## Why
Real campaign sends enqueue dj-queue tasks; without the worker they stay **Queued**. Test email worked because it is synchronous SMTP.

## Test plan
- [ ] Merge + deploy `monica_site` beta (and/or prod) via `deploy.sh`
- [ ] On **adama**, confirm worker container up for `monica_site_beta` / `monica_site_prod`
- [ ] On roslin / ai-server-4080, confirm **no** worker
- [ ] Portal: send campaign → recipient leaves Queued → SentReviewed-on: #18
This commit was merged in pull request #18.
This commit is contained in:
2026-08-08 12:01:18 -07:00
parent cc503988c0
commit b07e8cb4c3
6 changed files with 20 additions and 15 deletions
+8 -6
View File
@@ -208,6 +208,8 @@ a DB.
- `app_catalog` (`group_vars/all.yml`) — how each app is built (repo, type, compose file, migrate cmd). - `app_catalog` (`group_vars/all.yml`) — how each app is built (repo, type, compose file, migrate cmd).
- `host_apps` (`host_vars/<host>.yml`) — which app+env+port runs on that host. - `host_apps` (`host_vars/<host>.yml`) — which app+env+port runs on that host.
Optional `compose_profiles: [worker]` activates docker compose profiles on that
host only (used for `monica_site` dj-queue singleton on adama).
- Django app = one compose project per env: project name `<app>_<env>`, host port from `host_apps`. - Django app = one compose project per env: project name `<app>_<env>`, host port from `host_apps`.
Ports match across adama/roslin so NPM can balance `adama:PORT` + `roslin:PORT`. Ports match across adama/roslin so NPM can balance `adama:PORT` + `roslin:PORT`.
@@ -256,11 +258,10 @@ chat_backend secrets must use `SEARXNG_BASE_URL=http://10.0.0.128:8088`.
- **django**: push per-app secret from control node `{{ secrets_dir }}/<app>/<app>_<env>.env` - **django**: push per-app secret from control node `{{ secrets_dir }}/<app>/<app>_<env>.env`
to host `{{ apps_env_dir }}` → git checkout at ref → copy `.env` into checkout → to host `{{ apps_env_dir }}` → git checkout at ref → copy `.env` into checkout →
`docker compose build` → `up -d` → migrate (run once, shared DB). `docker compose build` → `up -d` (with `COMPOSE_PROFILES` from optional
**`monica_site` worker:** compose profile `worker` (dj-queue) is **not** started by `host_apps.compose_profiles`) → migrate (run once, shared DB).
catalog deploy. After first/prod deploy, start once on **adama only**: **`monica_site` worker:** adama `host_apps` sets `compose_profiles: [worker]` so
`docker compose -f docker-compose.prod.yml --profile worker up -d` deploy starts dj-queue with web. Other hosts omit profiles (web only).
(do not run on roslin / ai-server-4080).
- **node-static**: git checkout at ref → `npm ci` → `npm run build:<env>` - **node-static**: git checkout at ref → `npm ci` → `npm run build:<env>`
(writes to the app's `webroot_pattern`, e.g. `/var/www/{env}.realpath.app/html` (writes to the app's `webroot_pattern`, e.g. `/var/www/{env}.realpath.app/html`
or `/var/www/{env}.chat.aimloperations/html`). or `/var/www/{env}.chat.aimloperations/html`).
@@ -399,7 +400,8 @@ Store vault password for CI in a file readable only by the Act runner (e.g. `~/.
| 10a | Register + deploy `scha` (all webservers, port 8002) | In progress ([scha#19](https://git.aimloperations.com/ai_ml_operations/scha/issues/19)) | | 10a | Register + deploy `scha` (all webservers, port 8002) | In progress ([scha#19](https://git.aimloperations.com/ai_ml_operations/scha/issues/19)) |
| 10b | Register + deploy `chat_web_app` (node-static, ports 8082/8083) | Done (prod); beta ([#7](https://git.aimloperations.com/ai_ml_operations/server-infra/issues/7), [chat_web_app#35](https://git.aimloperations.com/ai_ml_operations/chat_web_app/issues/35)) | | 10b | Register + deploy `chat_web_app` (node-static, ports 8082/8083) | Done (prod); beta ([#7](https://git.aimloperations.com/ai_ml_operations/server-infra/issues/7), [chat_web_app#35](https://git.aimloperations.com/ai_ml_operations/chat_web_app/issues/35)) |
| 10c | Register + deploy `chat_backend` (django, ports 8003/8013) | Done (prod); beta ([#7](https://git.aimloperations.com/ai_ml_operations/server-infra/issues/7), [chat_backend#26](https://git.aimloperations.com/ai_ml_operations/chat_backend/issues/26)) | | 10c | Register + deploy `chat_backend` (django, ports 8003/8013) | Done (prod); beta ([#7](https://git.aimloperations.com/ai_ml_operations/server-infra/issues/7), [chat_backend#26](https://git.aimloperations.com/ai_ml_operations/chat_backend/issues/26)) |
| 10d | Register + deploy `monica_site` (django, ports 8004/8014; worker on adama) | In progress ([#14](https://git.aimloperations.com/ai_ml_operations/server-infra/issues/14)) | | 10d | Register + deploy `monica_site` (django, ports 8004/8014) | Done ([#14](https://git.aimloperations.com/ai_ml_operations/server-infra/issues/14)) |
| 10e | Auto-start `monica_site` dj-queue worker on adama (`compose_profiles`) | In progress ([#17](https://git.aimloperations.com/ai_ml_operations/server-infra/issues/17)) |
| 11 | Gitea container registry (optional) | Future | | 11 | Gitea container registry (optional) | Future |
## Open Decisions ## Open Decisions
+2 -3
View File
@@ -110,9 +110,8 @@ app_catalog:
compose_file: docker-compose.prod.yml compose_file: docker-compose.prod.yml
web_service: web web_service: web
migrate_cmd: "uv run python manage.py migrate --noinput" migrate_cmd: "uv run python manage.py migrate --noinput"
# dj-queue worker (compose profile `worker`) is a singleton — start only on # dj-queue worker = compose profile `worker` (singleton). Deploy starts it
# adama after deploy: docker compose -f docker-compose.prod.yml --profile worker up -d # via host_apps.compose_profiles on adama only (see host_vars/adama.yml).
# Catalog deploys web + migrate only; worker is manual / ops step.
# Deploy filter vars. CI passes these; manual runs may leave them undefined # Deploy filter vars. CI passes these; manual runs may leave them undefined
# to (re)deploy every app listed in the host's host_apps. # to (re)deploy every app listed in the host's host_apps.
+3 -3
View File
@@ -16,6 +16,6 @@ host_apps:
- { name: chat_web_app, env: beta, port: 8083 } - { name: chat_web_app, env: beta, port: 8083 }
- { name: chat_backend, env: prod, port: 8003 } - { name: chat_backend, env: prod, port: 8003 }
- { name: chat_backend, env: beta, port: 8013 } - { name: chat_backend, env: beta, port: 8013 }
- { name: monica_site, env: prod, port: 8004 } # compose_profiles: worker → dj-queue singleton (not on roslin / ai-server-4080).
- { name: monica_site, env: beta, port: 8014 } - { name: monica_site, env: prod, port: 8004, compose_profiles: [worker] }
# monica_site dj-queue worker (compose --profile worker) runs ONLY on adama. - { name: monica_site, env: beta, port: 8014, compose_profiles: [worker] }
+1 -1
View File
@@ -34,6 +34,6 @@ host_apps:
- { name: chat_web_app, env: beta, port: 8083 } - { name: chat_web_app, env: beta, port: 8083 }
- { name: chat_backend, env: prod, port: 8003 } - { name: chat_backend, env: prod, port: 8003 }
- { name: chat_backend, env: beta, port: 8013 } - { name: chat_backend, env: beta, port: 8013 }
# monica_site worker NOT here — adama host_apps sets compose_profiles: [worker].
- { name: monica_site, env: prod, port: 8004 } - { name: monica_site, env: prod, port: 8004 }
- { name: monica_site, env: beta, port: 8014 } - { name: monica_site, env: beta, port: 8014 }
# monica_site worker is NOT on ai-server-4080 — singleton on adama only.
+1 -1
View File
@@ -13,6 +13,6 @@ host_apps:
- { name: chat_web_app, env: beta, port: 8083 } - { name: chat_web_app, env: beta, port: 8083 }
- { name: chat_backend, env: prod, port: 8003 } - { name: chat_backend, env: prod, port: 8003 }
- { name: chat_backend, env: beta, port: 8013 } - { name: chat_backend, env: beta, port: 8013 }
# monica_site worker NOT here — adama host_apps sets compose_profiles: [worker].
- { name: monica_site, env: prod, port: 8004 } - { name: monica_site, env: prod, port: 8004 }
- { name: monica_site, env: beta, port: 8014 } - { name: monica_site, env: beta, port: 8014 }
# monica_site worker is NOT on roslin — singleton on adama only.
+4
View File
@@ -100,6 +100,9 @@
- _legacy_systemd | default('') | length > 0 - _legacy_systemd | default('') | length > 0
- _legacy_systemd_probe.stdout | default('') | length > 0 - _legacy_systemd_probe.stdout | default('') | length > 0
# Optional host_apps.compose_profiles (e.g. [worker]) activates compose profiles
# on this host only. Used for monica_site dj-queue singleton on adama — without
# it, plain up --remove-orphans can drop a manually started worker.
- name: "django[{{ _project }}] start containers" - name: "django[{{ _project }}] start containers"
ansible.builtin.command: ansible.builtin.command:
cmd: "docker compose -f {{ _spec.compose_file }} --env-file .env up -d --remove-orphans" cmd: "docker compose -f {{ _spec.compose_file }} --env-file .env up -d --remove-orphans"
@@ -107,6 +110,7 @@
environment: environment:
COMPOSE_PROJECT_NAME: "{{ _project }}" COMPOSE_PROJECT_NAME: "{{ _project }}"
WEB_PORT: "{{ app_item.port }}" WEB_PORT: "{{ app_item.port }}"
COMPOSE_PROFILES: "{{ (app_item.compose_profiles | default([])) | join(',') }}"
become: true become: true
become_user: "{{ admin_user }}" become_user: "{{ admin_user }}"
changed_when: true changed_when: true