feat(calendar): document outbox retention policy
This commit is contained in:
@@ -153,16 +153,24 @@ on throwaway databases.
|
||||
| --- | --- | --- |
|
||||
| `REDIS_URL` | `redis://redis:6379/0` | Celery broker/result backend when async workers are enabled. |
|
||||
| `CELERY_ENABLED` | `false` | Local/dev can send synchronously. Production campaign delivery should run workers and set this to `true`. |
|
||||
| `CELERY_QUEUES` | `send_email,append_sent,default` | Queue list expected by worker/process manager definitions. |
|
||||
| `CELERY_QUEUES` | `send_email,append_sent,notifications,calendar,default` | Queue list expected by worker/process manager definitions. The Calendar queue drains durable external-calendar operations. |
|
||||
|
||||
Worker command:
|
||||
|
||||
```bash
|
||||
python -m celery -A govoplan_core.celery_app:celery worker \
|
||||
--queues send_email,append_sent,default \
|
||||
--queues send_email,append_sent,notifications,calendar,default \
|
||||
--loglevel INFO
|
||||
```
|
||||
|
||||
Run Celery beat as a separately supervised process. Its built-in one-minute
|
||||
schedule recovers Calendar outbox rows left behind by broker failures, process
|
||||
crashes, and expired worker leases:
|
||||
|
||||
```bash
|
||||
python -m celery -A govoplan_core.celery_app:celery beat --loglevel INFO
|
||||
```
|
||||
|
||||
### Storage
|
||||
|
||||
| Setting | Default | Notes |
|
||||
@@ -275,7 +283,7 @@ the checked in `.env.example`. It runs:
|
||||
- explicit `ENABLED_MODULES`
|
||||
- explicit migrations and `--with-dev-data` bootstrap
|
||||
- API via the module-aware devserver
|
||||
- a Celery worker for `send_email,append_sent,default`
|
||||
- a Celery worker for `send_email,append_sent,notifications,calendar,default`
|
||||
- WebUI through the Vite dev server
|
||||
- durable local files under `runtime/production-like/files`
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import json
|
||||
import os
|
||||
from collections.abc import Mapping
|
||||
from dataclasses import dataclass
|
||||
from typing import Any, Literal
|
||||
from typing import Literal
|
||||
|
||||
from cryptography.fernet import Fernet
|
||||
from sqlalchemy.engine import make_url
|
||||
@@ -274,7 +274,8 @@ ENABLED_MODULES=tenancy,organizations,identity,access,admin,dashboard,policy,aud
|
||||
|
||||
CELERY_ENABLED=true
|
||||
REDIS_URL=redis://127.0.0.1:6379/0
|
||||
CELERY_QUEUES=send_email,append_sent,default
|
||||
CELERY_QUEUES=send_email,append_sent,notifications,calendar,default
|
||||
CALENDAR_OUTBOX_TERMINAL_RETENTION_DAYS=90
|
||||
|
||||
CORS_ORIGINS=https://govoplan.example.org
|
||||
AUTH_COOKIE_SECURE=true
|
||||
@@ -317,7 +318,8 @@ DATABASE_URL=postgresql+psycopg://govoplan:govoplan-dev@127.0.0.1:55433/govoplan
|
||||
GOVOPLAN_DATABASE_URL_PGTOOLS=postgresql://govoplan:govoplan-dev@127.0.0.1:55433/govoplan
|
||||
REDIS_URL=redis://127.0.0.1:56379/0
|
||||
CELERY_ENABLED=true
|
||||
CELERY_QUEUES=send_email,append_sent,default
|
||||
CELERY_QUEUES=send_email,append_sent,notifications,calendar,default
|
||||
CALENDAR_OUTBOX_TERMINAL_RETENTION_DAYS=90
|
||||
|
||||
ENABLED_MODULES=tenancy,organizations,identity,access,admin,dashboard,policy,audit,campaigns,files,mail,calendar,docs,ops
|
||||
CORS_ORIGINS=http://127.0.0.1:5173,http://localhost:5173
|
||||
|
||||
@@ -3,11 +3,24 @@ from __future__ import annotations
|
||||
import unittest
|
||||
|
||||
from cryptography.fernet import Fernet
|
||||
from pydantic import ValidationError
|
||||
|
||||
from govoplan_core.core.install_config import env_template, validate_runtime_configuration
|
||||
from govoplan_core.settings import Settings
|
||||
|
||||
|
||||
class InstallConfigTests(unittest.TestCase):
|
||||
def test_calendar_outbox_retention_setting_is_validated(self) -> None:
|
||||
self.assertEqual(Settings().calendar_outbox_terminal_retention_days, 90)
|
||||
self.assertEqual(
|
||||
Settings(
|
||||
CALENDAR_OUTBOX_TERMINAL_RETENTION_DAYS="0"
|
||||
).calendar_outbox_terminal_retention_days,
|
||||
0,
|
||||
)
|
||||
with self.assertRaises(ValidationError):
|
||||
Settings(CALENDAR_OUTBOX_TERMINAL_RETENTION_DAYS="-1")
|
||||
|
||||
def test_self_hosted_validation_reports_actionable_missing_settings(self) -> None:
|
||||
result = validate_runtime_configuration({}, profile="self-hosted")
|
||||
|
||||
@@ -68,8 +81,10 @@ class InstallConfigTests(unittest.TestCase):
|
||||
|
||||
self.assertIn("GOVOPLAN_INSTALL_PROFILE=self-hosted", self_hosted)
|
||||
self.assertIn("MASTER_KEY_B64=<generate", self_hosted)
|
||||
self.assertIn("CALENDAR_OUTBOX_TERMINAL_RETENTION_DAYS=90", self_hosted)
|
||||
self.assertIn("GOVOPLAN_INSTALL_PROFILE=production-like", production_like)
|
||||
self.assertNotIn("MASTER_KEY_B64=<generate", production_like)
|
||||
self.assertIn("CALENDAR_OUTBOX_TERMINAL_RETENTION_DAYS=90", production_like)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
Reference in New Issue
Block a user