Skip to content

Commit 3eba065

Browse files
authored
Merge branch 'master' into cam/fix-audit
2 parents e622729 + e248951 commit 3eba065

26 files changed

Lines changed: 1061 additions & 527 deletions

api/.env.example

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,10 @@ PRISM_OIDC_CLIENT_SECRET=
1010
PRISM_SESSION_SECRET=
1111
# Default one week session time
1212
PRISM_SESSION_TTL_SECONDS=604800
13+
14+
# Local map export storage (optional — docker-compose.develop.yml sets RustFS defaults).
15+
# EXPORT_MAP_S3_BUCKET=prism-dev
16+
# AWS_ACCESS_KEY_ID=rustfsadmin
17+
# AWS_SECRET_ACCESS_KEY=rustfsadmin
18+
# AWS_ENDPOINT_URL=http://rustfs:9000 # server-side S3 (Docker network)
19+
# AWS_PRESIGN_ENDPOINT_URL=http://localhost:9000 # presigned download URLs (browser)

api/README.md

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,33 @@ export KOBO_USERNAME=kobo_user KOBO_PASSWORD=test
4242
make api
4343
```
4444

45-
This starts two containers via `docker-compose.develop.yml`:
45+
This starts four containers via `docker-compose.develop.yml`:
4646
- **`db`** — PostGIS (Postgres) on host port **54321**
47+
- **`rustfs`** — local S3-compatible storage for map export artifacts (API port **9000**, console **9001**)
4748
- **`api`** — FastAPI (uvicorn with hot reload) on host port **80**
49+
- **`export_map_worker`** — polls `map_export_jobs`, runs Playwright export, writes artifacts to RustFS
50+
51+
### Local map export storage (RustFS)
52+
53+
Production stores batch and scheduled map exports in **AWS S3** (`EXPORT_MAP_S3_BUCKET`, e.g. `s3://prism-wfp/batch-maps`). Local dev uses **RustFS** so the same code paths run without real AWS credentials for artifacts.
54+
55+
`docker-compose.develop.yml` sets this automatically for **`api`** and **`export_map_worker`**:
56+
57+
| Variable | Local value | Role |
58+
|---|---|---|
59+
| `EXPORT_MAP_S3_BUCKET` | `prism-dev` | Bucket created by `rustfs-init` |
60+
| `AWS_ENDPOINT_URL` | `http://rustfs:9000` | Server-side S3 calls (worker, API inside Docker) |
61+
| `AWS_PRESIGN_ENDPOINT_URL` | `http://localhost:9000` | Presigned download URLs the browser can reach |
62+
63+
RustFS console: **http://localhost:9001** (login `rustfsadmin` / `rustfsadmin`).
64+
65+
These flows stay aligned with production when `EXPORT_MAP_S3_BUCKET` is set and `EXPORT_MAP_LOCAL_OUTPUT_DIR` is empty (the compose default):
66+
67+
1. **Write**`export_map_worker`
68+
2. **Dedupe**`POST /export-map/jobs` and `scheduled_public_maps` cron
69+
3. **Download**`GET /export-map/jobs/{id}` and admin schedule download
70+
71+
The alternative dev mode, `EXPORT_MAP_LOCAL_OUTPUT_DIR`, writes `file://…` URIs to disk instead of S3 and skips the RustFS/prod-aligned path.
4872

4973
### 3. Run migrations and seed data
5074

@@ -55,7 +79,7 @@ make db-migrate
5579
make db-seed
5680
```
5781

58-
`db-migrate` applies Alembic migrations (`upgrade head`). `db-seed` runs migrations first, then inserts sample dev data (Mozambique AA metadata, a `local_dev_user`, and example alert rows).
82+
`db-migrate` applies Alembic migrations (`upgrade head`). `db-seed` runs migrations first, then inserts sample dev data (Mozambique AA metadata, a `local_dev_user`, example alert rows, and five `[Seed]` map export schedules for cron/download QA).
5983

6084
### 4. Verify
6185

api/docker-compose.develop.yml

Lines changed: 61 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,56 @@ services:
1616
retries: 12
1717
start_period: 30s
1818

19+
# Local S3-compatible storage for map export artifacts (dev only).
20+
rustfs:
21+
image: rustfs/rustfs:latest
22+
ports:
23+
- "9000:9000"
24+
- "9001:9001"
25+
environment:
26+
RUSTFS_ACCESS_KEY: rustfsadmin
27+
RUSTFS_SECRET_KEY: rustfsadmin
28+
RUSTFS_CONSOLE_ENABLE: "true"
29+
RUSTFS_ADDRESS: 0.0.0.0:9000
30+
RUSTFS_CONSOLE_ADDRESS: 0.0.0.0:9001
31+
volumes:
32+
- rustfs_data:/data
33+
command: ["/data"]
34+
healthcheck:
35+
test: ["CMD-SHELL", "curl -sf http://127.0.0.1:9000/health || exit 1"]
36+
interval: 5s
37+
timeout: 5s
38+
retries: 12
39+
start_period: 40s
40+
41+
rustfs-init:
42+
image: amazon/aws-cli:2.27.50
43+
depends_on:
44+
rustfs:
45+
condition: service_healthy
46+
environment:
47+
AWS_ACCESS_KEY_ID: rustfsadmin
48+
AWS_SECRET_ACCESS_KEY: rustfsadmin
49+
AWS_DEFAULT_REGION: us-east-1
50+
entrypoint: /bin/sh
51+
command:
52+
- -c
53+
- |
54+
until aws --endpoint-url http://rustfs:9000 s3 ls >/dev/null 2>&1; do
55+
echo "waiting for rustfs..."
56+
sleep 2
57+
done
58+
aws --endpoint-url http://rustfs:9000 s3 mb s3://prism-dev 2>/dev/null || true
59+
1960
api:
2061
env_file:
2162
- path: .env
2263
required: false
2364
depends_on:
2465
db:
2566
condition: service_healthy
67+
rustfs-init:
68+
condition: service_completed_successfully
2669
volumes:
2770
- ./prism_app:/prism_app
2871
- ./pyproject.toml:/pyproject.toml
@@ -52,18 +95,27 @@ services:
5295
- VECTOR_STORE_ACCESS_KEY_ID=${VECTOR_STORE_ACCESS_KEY_ID}
5396
- VECTOR_STORE_SECRET_ACCESS_KEY=${VECTOR_STORE_SECRET_ACCESS_KEY}
5497
- VECTOR_STORE_DEFAULT_REGION=${VECTOR_STORE_DEFAULT_REGION}
98+
# Map export artifacts → local RustFS
99+
- EXPORT_MAP_S3_BUCKET=prism-dev
100+
- EXPORT_MAP_LOCAL_OUTPUT_DIR=
101+
- AWS_ACCESS_KEY_ID=rustfsadmin
102+
- AWS_SECRET_ACCESS_KEY=rustfsadmin
103+
- AWS_DEFAULT_REGION=us-east-1
104+
- AWS_ENDPOINT_URL=http://rustfs:9000
105+
- AWS_PRESIGN_ENDPOINT_URL=http://localhost:9000
55106
command: uvicorn prism_app.main:app --host 0.0.0.0 --port 80 --reload
56107
# Infinite loop, to keep it alive, for debugging
57108
# command: bash -c "while true; do echo 'sleeping...' && sleep 10; done"
58-
109+
59110
export_map_worker:
60111
shm_size: "2gb"
61112
depends_on:
62113
db:
63114
condition: service_healthy
115+
rustfs-init:
116+
condition: service_completed_successfully
64117
volumes:
65118
- ./prism_app:/prism_app
66-
- ./cache:/cache:rw
67119
build:
68120
context: ./
69121
dockerfile: ./Dockerfile.export-map-worker
@@ -74,14 +126,16 @@ services:
74126
- POSTGRES_DB=postgres
75127
- POSTGRES_PORT=5432
76128
- POSTGRES_PASSWORD=!ChangeMe!
77-
- EXPORT_MAP_S3_BUCKET=${EXPORT_MAP_S3_BUCKET:-}
78-
- EXPORT_MAP_LOCAL_OUTPUT_DIR=${EXPORT_MAP_LOCAL_OUTPUT_DIR:-/cache/map_exports}
79-
- AWS_DEFAULT_REGION=${AWS_DEFAULT_REGION:-}
80-
- AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID:-}
81-
- AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY:-}
129+
- EXPORT_MAP_S3_BUCKET=prism-dev
130+
- EXPORT_MAP_LOCAL_OUTPUT_DIR=
131+
- AWS_ACCESS_KEY_ID=rustfsadmin
132+
- AWS_SECRET_ACCESS_KEY=rustfsadmin
133+
- AWS_DEFAULT_REGION=us-east-1
134+
- AWS_ENDPOINT_URL=http://rustfs:9000
82135
- BROWSER_POOL_SIZE=1
83136
working_dir: /prism_app
84137
command: [ "python", "-m", "prism_app.workers.export_map_worker" ]
85138

86139
volumes:
87140
db_data:
141+
rustfs_data:

0 commit comments

Comments
 (0)