Skip to content

Commit a748deb

Browse files
authored
Merge pull request #46 from NHSDigital/feat/database-backups
Add script to perform database backups
2 parents 9583346 + a2c0179 commit a748deb

5 files changed

Lines changed: 88 additions & 0 deletions

File tree

Makefile

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,12 @@ _install-uv:
5757
echo "uv already installed"; \
5858
fi
5959

60+
# ---------------------------------------------------------------------------
61+
# Database backup
62+
# ---------------------------------------------------------------------------
63+
backup-db: # Backup sqlite databases @Operations
64+
PYTHONPATH=scripts/python uv run python -m backup_database
65+
6066
# ---------------------------------------------------------------------------
6167
# Testing
6268
# ---------------------------------------------------------------------------

scripts/bat/backup_database.bat

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
:: Batch file to run the backup_database.py script
2+
@echo off
3+
set %rootdir=%1
4+
python "%rootdir%\scripts\python\backup_database.py"

scripts/bat/schtasks.bat

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
:: This batch file creates a scheduled task to run the backup_database.bat script daily at midnight.
2+
@echo off
3+
set thisdir=%~dp0
4+
set rootdir="%thisdir%..\.."
5+
schtasks /create /tn BackupDatabaseTask /tr "%thisdir%backup_database.bat %rootdir%" /sc daily /st 00:00

scripts/python/backup_database.py

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
from datetime import datetime
2+
import dotenv
3+
import sqlite3
4+
import os
5+
import sys
6+
7+
dotenv.load_dotenv()
8+
9+
10+
def backup_database(db_path, backup_path):
11+
"""Backup the database at db_path."""
12+
13+
conn = None
14+
15+
if not os.path.exists(db_path):
16+
print(f"Database not found: {db_path}")
17+
return False
18+
19+
if not os.path.exists(backup_path):
20+
os.makedirs(backup_path)
21+
22+
try:
23+
date_and_time = datetime.now().strftime("%Y%m%d-%H%M%S")
24+
db_filename = os.path.basename(db_path)
25+
backup_path = f"{backup_path}/{date_and_time}.{db_filename}.backup"
26+
27+
conn = sqlite3.connect(db_path)
28+
with sqlite3.connect(backup_path) as backup_conn:
29+
conn.backup(backup_conn)
30+
print(f"Database backed up successfully to: {backup_path}")
31+
return True
32+
except Exception as e:
33+
print(f"Error during backup: {e}")
34+
return False
35+
finally:
36+
if conn:
37+
conn.close()
38+
39+
40+
def main():
41+
"""Main entry point."""
42+
try:
43+
pacs_db_path = os.getenv("PACS_DB_PATH")
44+
mwl_db_path = os.getenv("MWL_DB_PATH")
45+
backup_path = os.getenv("BACKUP_PATH", "./backups")
46+
47+
print("Starting database backup...")
48+
print("PACS_DB_PATH:", pacs_db_path, "MWL_DB_PATH:", mwl_db_path)
49+
success = True
50+
51+
if pacs_db_path:
52+
print(f"Backing up PACS database: {pacs_db_path} to {backup_path}")
53+
success = success and backup_database(pacs_db_path, backup_path)
54+
else:
55+
print("PACS_DB_PATH not set, skipping PACS database backup")
56+
57+
if mwl_db_path:
58+
print(f"Backing up MWL database: {mwl_db_path} to {backup_path}")
59+
success = success and backup_database(mwl_db_path, backup_path)
60+
else:
61+
print("MWL_DB_PATH not set, skipping MWL database backup")
62+
63+
sys.exit(0 if success else 1)
64+
except Exception as e:
65+
print(f"Error: {e}", file=sys.stderr)
66+
import traceback
67+
68+
traceback.print_exc()
69+
sys.exit(1)
70+
71+
72+
if __name__ == "__main__":
73+
main()

0 commit comments

Comments
 (0)