You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: alerting/README.md
+30-4Lines changed: 30 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -9,7 +9,7 @@ There is a unique service running for all country specific frontends.
9
9
10
10
## Database schema and migrations
11
11
12
-
The alerting stack uses the same PostgreSQL database as the PRISM API for `alert`, `user_info`, and `anticipatory_action_alerts`. **Python/Alembic under `api/alembic/` is the sole owner of new schema migrations** for this database. The TypeORM migration history in `migration/` remains useful as a record of how production was built, but **do not add new TypeORM migrations** for these tables or enums. Change SQLModel in `api/prism_app/database/`, add an Alembic revision under `api/alembic/versions/`, and run `alembic upgrade head` with `PRISM_ALERTS_DATABASE_URL` (see `api/README.md`).
12
+
The alerting stack uses the same PostgreSQL database as the PRISM API for `alert`, `user_info`, and `anticipatory_action_alerts`. **Python/Alembic under `api/alembic/` is the sole owner of schema migrations** for this database. Change SQLModel in `api/prism_app/database/`, add an Alembic revision under `api/alembic/versions/`, and run `alembic upgrade head` with `PRISM_ALERTS_DATABASE_URL` (see `api/README.md`).
13
13
14
14
## Functionalities
15
15
@@ -23,18 +23,20 @@ The alerting stack uses the same PostgreSQL database as the PRISM API for `alert
23
23
- Alerts are triggered by a cron job running within the `alerting-node` process.
24
24
- Run `docker compose up` to launch the `alerting-node` and `alerting-db` processes.
25
25
- The system checks database entries to determine **which country** needs to be triggered.
26
-
- Currently, **Mozambique is supported**. After the DB schema exists (Alembic baseline / TypeORM history in prod), seed local data from the **API** (same repo area that owns migrations)—see **Local dev seed data** in [`api/README.md`](../api/README.md): `poetry run python scripts/seed_alerts_db.py` from `api/`. Connection vars are `PRISM_ALERTS_DATABASE_URL` or `POSTGRES_*` in `api/.env`; for host access to `alerting-db`, use port `54321` as in [`.env.example`](./.env.example).
26
+
- Currently, **Mozambique is supported**. After the DB schema exists, seed local data from the **API** (same repo area that owns migrations)—see **Local dev seed data** in [`api/README.md`](../api/README.md): `poetry run python scripts/seed_alerts_db.py` from `api/`. Connection vars are `PRISM_ALERTS_DATABASE_URL` or `POSTGRES_*` in `api/.env`; for host access to `alerting-db`, use port `54321` as in [`.env.example`](./.env.example).
27
27
28
28
-**country**: The target country for the alert.
29
29
-**emails**: A list of email addresses that will receive the alert notification.
30
30
-**prism_url**: The base URL of the PRISM platform for redirection link and screenshot capture.
31
31
-**type**: Hazard type enum: `storm` | `flood` | `drought`.
32
32
33
-
The `type` column is a PostgreSQL ENUM (`anticipatory_action_alerts_type_enum`). It was originally created by TypeORM migration `1738850000000-add-type-to-anticipatory-action-alerts.ts`; the authoritative definition for new environments is the Alembic baseline under `api/alembic/versions/`.
33
+
The `type` column is a PostgreSQL ENUM (`anticipatory_action_alerts_type_enum`) defined by the Alembic baseline under `api/alembic/versions/`.
The same API seed step loads a [Starlette Admin](https://github.com/jowilf/starlette-admin)–friendly `user_info` row and two sample `alert` rows (SQL under [`api/scripts/seed_local_alerts_dev.sql`](../api/scripts/seed_local_alerts_dev.sql)). **User password:** with `salt = 'false'`, the PRISM API validates this row using a **plain-text** password match ([`prism_app/auth.py`](../api/prism_app/auth.py))—use HTTP Basic `local_dev_user` / `localdev` when auth is enabled. Re-running the seed replaces the fixed `seed-alert-*@example.com` rows and leaves `user_info` unchanged if the username already exists.
37
+
For [Starlette Admin](https://github.com/jowilf/starlette-admin) or API smoke tests, use the same seed step as above: from `api/`, run `poetry run python scripts/seed_alerts_db.py`. That executes [`api/scripts/seed_local_alerts_dev.sql`](../api/scripts/seed_local_alerts_dev.sql), which loads sample `alert` and `user_info` rows (and the Mozambique AA rows) in one shot. Re-running is safe: see comments at the top of that SQL file.
38
+
39
+
-**User password:** with `salt = 'false'`, the PRISM API validates this row using a **plain-text** password match ([`prism_app/auth.py`](../api/prism_app/auth.py))—use HTTP Basic `local_dev_user` / `localdev` when auth is enabled.
- The provided emails replace the DB-configured recipients for test runs.
67
69
70
+
### Ethereal (fake SMTP, no credentials)
71
+
72
+
If **`PRISM_ALERTS_EMAIL_USER`** and **`PRISM_ALERTS_EMAIL_PASSWORD`** are both unset or empty, [`src/utils/email.ts`](./src/utils/email.ts) uses Nodemailer’s [Ethereal](https://ethereal.email) test inbox: it creates a disposable SMTP account, sends through `smtp.ethereal.email`, and logs a **preview URL** (`Preview URL: …`) you can open in a browser to read the message and attachments.
73
+
74
+
This is independent of **`--testEmail`**: you can keep using test addresses in the command; Ethereal still delivers to its fake SMTP and you inspect the result via the preview URL (those addresses are not a real inbox).
75
+
76
+
1. Ensure real SMTP env vars are not set (or remove them from `.env` / compose for local runs).
77
+
2. Run a worker that sends mail (commands above, or threshold `alert-worker` if your DB triggers a send).
78
+
3. Copy the logged preview link from the container or terminal output.
79
+
80
+
Each run may use a new Ethereal account. To reuse one inbox, configure Ethereal’s SMTP user/password yourself via `PRISM_ALERTS_EMAIL_USER`, `PRISM_ALERTS_EMAIL_PASSWORD`, and `PRISM_ALERTS_EMAIL_HOST` (e.g. `smtp.ethereal.email`).
81
+
68
82
### Flood data source
69
83
- The flood worker reads `dates.json`: `https://data.earthobservation.vam.wfp.org/public-share/aa/flood/moz/dates.json`.
70
84
- Email triggers when `trigger_status` is one of: `bankfull`, `moderate`, `severe`.
71
85
- Email content follows the AA Flood design and includes a map screenshot and CTA link.
72
86
87
+
## CI and release checks (shared alerts database)
88
+
89
+
GitHub Actions job **`alerts_db_alembic_and_alerting`** (in [`.github/workflows/api.yml`](../.github/workflows/api.yml)) starts an ephemeral Postgres, runs `alembic upgrade head` from `api/`, then:
90
+
91
+
1.**`yarn check-alerts-db-contract`** — Validates tables/columns/types the Node workers query still match the migrated schema (`src/ci/check-alerts-db-contract.ts`). Requires `PRISM_ALERTS_DATABASE_URL`.
92
+
2.**`yarn smoke-alerts-db-pool`** — Runs real `pg` queries used by threshold and AA workers (empty tables OK; `src/ci/smoke-alerts-db-pool.ts`).
93
+
3.**`yarn smoke-alerting-workers`** — Runs `runAlertWorker()` plus AA storm/flood `SELECT`s on the same pool (`src/ci/smoke-alerting-workers.ts`; safe when there are no active alerts).
94
+
95
+
The same job then runs **`pytest`** on `test_api.py`, `test_alerting.py`, and **`test_alerts_db_integration.py`** so the API, `/stats` alerting fixture, admin list routes, and Alembic metadata align with that database. See [api/README.md](../api/README.md) (**Alerts database (CI integration + local)**).
96
+
97
+
**Before or right after the first production `alembic upgrade` on the shared alerts DB**, also smoke manually: full `alert-worker`, one AA worker **without**`--testEmail` (so the pool hits Postgres), and read-only Starlette Admin on `alert` / `user_info` / `anticipatory_action_alerts`.
98
+
73
99
## Server crons
74
100
Alert workers are running as crons on the server. Edit with: `crontab -e`
Copy file name to clipboardExpand all lines: alerting/crons/cron_aa_flood_alert_run.sh
+1-1Lines changed: 1 addition & 1 deletion
Original file line number
Diff line number
Diff line change
@@ -4,7 +4,7 @@ cd ~/prism-app/alerting
4
4
# source secrets from AWS
5
5
source ../api/set_envs.sh
6
6
7
-
docker compose run --rm --entrypoint 'yarn aa-flood-alert-worker' alerting-node 2>&1| tee -a ~/prism-app/alerting/aa_flood_alert_worker.log
7
+
docker compose run --rm -e POSTGRES_SSL=true --entrypoint 'yarn aa-flood-alert-worker' alerting-node 2>&1| tee -a ~/prism-app/alerting/aa_flood_alert_worker.log
8
8
9
9
## To set up the cron job, run the following command on the server:
Copy file name to clipboardExpand all lines: alerting/crons/cron_aa_storm_alert_run.sh
+1-3Lines changed: 1 addition & 3 deletions
Original file line number
Diff line number
Diff line change
@@ -4,12 +4,10 @@ cd ~/prism-app/alerting
4
4
# source secrets from AWS
5
5
source ../api/set_envs.sh
6
6
7
-
docker compose run --rm --entrypoint 'yarn aa-storm-alert-worker' alerting-node 2>&1| tee -a ~/prism-app/alerting/aa_storm_alert_worker.log
7
+
docker compose run --rm -e POSTGRES_SSL=true --entrypoint 'yarn aa-storm-alert-worker' alerting-node 2>&1| tee -a ~/prism-app/alerting/aa_storm_alert_worker.log
8
8
9
9
## To set up the cron job, run the following command on the server:
10
10
# crontab -e
11
11
## and then add the following line to the crontab file:
12
12
## This will run the storm AA alerting script every hour at minute 0.
0 commit comments