Phase 2 of Migration
This commit is contained in:
56
backend/migration/migrate_public_features.py
Normal file
56
backend/migration/migrate_public_features.py
Normal file
@@ -0,0 +1,56 @@
|
||||
"""
|
||||
Phase 2 — Step 2.2: public_features (Firestore → Postgres)
|
||||
|
||||
Reads the single 'admin_settings/public_features' doc from Firestore and
|
||||
flattens each field into a key/value row in public_features.
|
||||
|
||||
Run on VPS:
|
||||
docker compose exec backend python -m migration.migrate_public_features
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import sys
|
||||
|
||||
from sqlalchemy.dialects.postgresql import insert as pg_insert
|
||||
|
||||
from settings.orm import PublicFeature
|
||||
from shared.firebase import init_firebase, get_db as get_firestore
|
||||
from migration.utils import AsyncPgSession, log_run, pg_count
|
||||
|
||||
SCRIPT = "migrate_public_features"
|
||||
COLLECTION = "admin_settings"
|
||||
DOC_ID = "public_features"
|
||||
|
||||
|
||||
async def run() -> None:
|
||||
init_firebase()
|
||||
fs = get_firestore()
|
||||
if fs is None:
|
||||
print("ERROR: Firebase not initialised — check service account path.", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
doc = fs.collection(COLLECTION).document(DOC_ID).get()
|
||||
if not doc.exists:
|
||||
print("No public_features document found in Firestore — skipping.")
|
||||
await log_run(SCRIPT, 0, 0, notes="source doc not found")
|
||||
return
|
||||
|
||||
data = doc.to_dict()
|
||||
source_count = len(data)
|
||||
print(f"Source (Firestore): {source_count} fields in {COLLECTION}/{DOC_ID}")
|
||||
|
||||
records = [{"key": k, "value": v} for k, v in data.items()]
|
||||
|
||||
async with AsyncPgSession() as session:
|
||||
async with session.begin():
|
||||
stmt = pg_insert(PublicFeature).values(records)
|
||||
stmt = stmt.on_conflict_do_nothing(index_elements=["key"])
|
||||
await session.execute(stmt)
|
||||
dest_count = await pg_count(session, "public_features")
|
||||
|
||||
print(f"Postgres public_features: {dest_count} rows ✓")
|
||||
await log_run(SCRIPT, source_count, dest_count)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(run())
|
||||
Reference in New Issue
Block a user