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
The worklist is inherently ephemeral. Stale worklist items from a previous day are not meaningful to the modality and could cause confusion if they appeared in a C-FIND response.
Therefore we backup and reset the MWL database on a configurable schedule (default: daily at 02:00 UTC).
# ADR-004: Daily backup and reset of the MWL database
2
+
3
+
Date: 2026-04-02
4
+
5
+
Status: Accepted
6
+
7
+
## Context
8
+
9
+
The gateway MWL database holds scheduled appointment data that is consumed by mammography modality via DICOM C-FIND. This data originates from Manage Breast Screening and is written to the gateway by the relay listener.
10
+
11
+
The worklist is inherently ephemeral: appointments are scheduled per clinic, and a clinic session does not span calendar days. Stale worklist items from a previous day are not meaningful to the modality and could cause confusion if they appeared in a C-FIND response.
12
+
13
+
The gateway MWL is not intended to be a canonical or long-term data store. Retaining worklist items indefinitely would cause the database to grow to unwieldy proportions and would give a false impression of data durability.
14
+
15
+
The gateway runs as a Python process on a Windows VM managed by Azure Arc. Scheduling therefore belongs in the infrastructure layer (Windows Task Scheduler, configurable via Arc).
16
+
17
+
## Decision
18
+
19
+
Reset the MWL database on a schedule managed by Windows Task Scheduler by:
20
+
21
+
1. Backing up the database before clearing it, using SQLite's native `conn.backup()` API
22
+
2. Deleting all rows from `worklist_items`
23
+
24
+
`reset_main.py` is performs these two steps and exits. Windows Task Scheduler (registered via `scripts/bat/schtasks.bat`) invokes it on whatever schedule is configured in infrastructure.
25
+
26
+
**Alternatives considered:**
27
+
28
+
-**In-process Python scheduler** (`croniter` sleep loop) — puts scheduling logic in application code; duplicates a facility the OS already provides; requires a long-running process that serves no other purpose
29
+
-**Reset on startup only** — would not handle long-running deployments where the process is not restarted between clinics
30
+
-**No reset** — leads to unbounded growth and stale data visible to the modality
31
+
32
+
## Consequences
33
+
34
+
### Positive Consequences
35
+
36
+
- Worklist is clean at the start of each clinic with no manual intervention
37
+
- Database size remains bounded
38
+
- Backup before clear means data is recoverable if needed
39
+
- Schedule is owned by infrastructure (Arc / Task Scheduler), not application code — no code change needed to adjust timing
40
+
-`reset_main.py` is a simple, testable, one-shot script with no scheduler machinery
41
+
42
+
### Negative Consequences
43
+
44
+
- Schedule configuration lives outside the codebase; requires infrastructure access to change
45
+
- Any worklist items written very close to the reset time could be cleared before the modality queries them. This is mitigated by choosing a reset time well outside clinic hours
46
+
- Backups accumulate on disk and will need periodic pruning; this is not currently automated
1.**Worklist Creation**: Relay listener receives appointments from web app and creates worklist items (NB not yet implemented; worklist items must be created programmatically via `scripts/add_worklist_item.py`)
43
+
1.**Worklist Creation**: Relay listener receives appointments from Manage Breast Screening and creates worklist items
43
44
2.**Worklist Query**: Modality sends C-FIND request to MWL server
44
45
3.**Filtering**: MWL server filters by modality, date, patient ID, status
45
46
4.**Response**: Server returns matching worklist items to modality
46
-
5.**Status Updates**: [MPPS (Modality Performed Procedure Step)](https://dicom.nema.org/medical/dicom/current/output/html/part04.html#chapter_F) updates procedure status (NB not yet implemented)
47
+
5.**Status Updates**: C-STORE receipt transitions items from `SCHEDULED` to `IN PROGRESS`; [MPPS](https://dicom.nema.org/medical/dicom/current/output/html/part04.html#chapter_F) transitions items to `COMPLETED` or `DISCONTINUED`
48
+
6.**Daily Reset**: Windows Task Scheduler invokes `reset_main.py`, which backs up and clears the database
47
49
48
50
## Running the MWL Server
49
51
50
-
The MWL server runs in a separate container:
52
+
The gateway runs as a Python process on a Windows VM:
51
53
52
54
```bash
53
-
# Start both PACS and MWL servers
54
-
docker compose up -d
55
+
# Start the MWL server
56
+
uv run python -m mwl_main
55
57
56
-
# Start only MWL server
57
-
docker compose up -d mwl
58
-
59
-
# View logs
60
-
docker compose logs -f mwl
58
+
# Run a one-shot backup and reset (normally invoked by Task Scheduler)
59
+
uv run python -m reset_main
60
+
```
61
61
62
-
# Stop servers
63
-
docker compose down
62
+
For local development, Docker Compose is available:
|`BACKUP_PATH`|`/var/lib/pacs/backups`| Directory for database backups |
86
+
|`LOG_LEVEL`|`INFO`| Logging level |
87
+
88
+
The reset schedule is configured in Windows Task Scheduler (registered via `scripts/bat/schtasks.bat`), not in the application.
89
+
90
+
## Scheduling the daily reset (Windows)
91
+
92
+
Register the scheduled task (run once, on the gateway VM):
93
+
94
+
```bat
95
+
scripts\bat\schtasks.bat
96
+
```
97
+
98
+
This creates a Task Scheduler task that runs `reset_main.py` daily at midnight. The schedule can be adjusted in Task Scheduler or via Azure Arc without any code change.
@@ -139,31 +159,12 @@ uv run pytest tests/integration/test_c_find_returns_worklist_items.py -v
139
159
uv run pytest tests/integration/test_request_cfind_on_worklist.py -v
140
160
```
141
161
142
-
## Multi-container architecture
143
-
144
-
The PACS and MWL servers run in separate containers. See [ADR-003: Separate containers for PACS and MWL](../adr/ADR-003_Separate_containers_for_PACS_and_MWL.md) for the architectural decision and trade-offs.
SCHEDULED ──(first C-STORE)──▶ IN PROGRESS ──(MPPS N-SET)──▶ COMPLETED
166
+
│
167
+
└────────(MPPS N-SET)──▶ DISCONTINUED
161
168
```
162
169
163
-
Each server:
164
-
165
-
- Runs in its own container
166
-
- Has its own Application Entity (AE)
167
-
- Uses a separate SQLite database
168
-
- Can be scaled and deployed independently
169
-
- Handles different DICOM operations (C-STORE vs C-FIND)
170
+
See [ADR-003: Separate containers for PACS and MWL](../adr/ADR-003_Separate_containers_for_PACS_and_MWL.md) and [ADR-004: Daily backup and reset of the MWL database](../adr/ADR-004_MWL_Daily_Backup_And_Reset.md) for architectural decisions.
0 commit comments