feat(csv-import): Implement SAVEPOINT handling for vitals baseline import
- Updated the CSV import logic to include SAVEPOINT management, allowing for better error handling during the vitals baseline import process. - Enhanced the SQL migration script to drop existing CHECK constraints related to the 'source' field, ensuring compatibility with the new universal CSV import. - Incremented DB_SCHEMA_VERSION to "20260409c" to reflect these changes and improve the import process reliability.
This commit is contained in:
parent
e60976e1cc
commit
5a0c71dd90
|
|
@ -588,6 +588,9 @@ def _import_vitals_baseline(
|
||||||
continue
|
continue
|
||||||
iso = d.isoformat()
|
iso = d.isoformat()
|
||||||
try:
|
try:
|
||||||
|
# Ohne SAVEPOINT: erster fehlgeschlagener INSERT setzt die Xact auf „aborted“,
|
||||||
|
# alle folgenden Queries + commit() schlagen fehl → generischer 500.
|
||||||
|
cur.execute("SAVEPOINT vitals_csv_row")
|
||||||
cur.execute(
|
cur.execute(
|
||||||
"""
|
"""
|
||||||
INSERT INTO vitals_baseline (
|
INSERT INTO vitals_baseline (
|
||||||
|
|
@ -619,8 +622,15 @@ def _import_vitals_baseline(
|
||||||
updated += 1
|
updated += 1
|
||||||
if result.get("id"):
|
if result.get("id"):
|
||||||
affected_ids["vitals_baseline"].append(str(result["id"]))
|
affected_ids["vitals_baseline"].append(str(result["id"]))
|
||||||
|
cur.execute("RELEASE SAVEPOINT vitals_csv_row")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
error_details.append({"row": rows_total, "error": str(e)})
|
try:
|
||||||
|
cur.execute("ROLLBACK TO SAVEPOINT vitals_csv_row")
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
error_details.append(
|
||||||
|
{"row": rows_total, "error": str(e), "context": "vitals_baseline upsert"},
|
||||||
|
)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"rows_total": rows_total,
|
"rows_total": rows_total,
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,22 @@
|
||||||
-- Universal-CSV-Import schreibt source = 'csv'; bisherige CHECK erlaubte das nicht → 500 beim Import.
|
-- Universal-CSV-Import setzt source = 'csv'. Alte CHECK-Constraints kennen das nicht.
|
||||||
ALTER TABLE vitals_baseline DROP CONSTRAINT IF EXISTS vitals_baseline_source_check;
|
-- Namen können je nach PG-Version abweichen → alle passenden CHECK Constraints zu source droppen.
|
||||||
|
DO $$
|
||||||
|
DECLARE
|
||||||
|
r RECORD;
|
||||||
|
BEGIN
|
||||||
|
FOR r IN
|
||||||
|
SELECT c.conname
|
||||||
|
FROM pg_constraint c
|
||||||
|
JOIN pg_class t ON c.conrelid = t.oid
|
||||||
|
WHERE t.relname = 'vitals_baseline'
|
||||||
|
AND c.contype = 'c'
|
||||||
|
AND pg_get_constraintdef(c.oid) ILIKE '%source%'
|
||||||
|
AND pg_get_constraintdef(c.oid) ILIKE '%IN %'
|
||||||
|
LOOP
|
||||||
|
EXECUTE format('ALTER TABLE vitals_baseline DROP CONSTRAINT %I', r.conname);
|
||||||
|
END LOOP;
|
||||||
|
END $$;
|
||||||
|
|
||||||
ALTER TABLE vitals_baseline ADD CONSTRAINT vitals_baseline_source_check
|
ALTER TABLE vitals_baseline ADD CONSTRAINT vitals_baseline_source_check
|
||||||
CHECK (source IN ('manual', 'apple_health', 'garmin', 'withings', 'csv'));
|
CHECK (source IN ('manual', 'apple_health', 'garmin', 'withings', 'csv'));
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
-- Idempotent: erneute Bereinigung der source-CHECK, falls 048 zuvor nicht griff oder nur teilweise lief.
|
||||||
|
DO $$
|
||||||
|
DECLARE
|
||||||
|
r RECORD;
|
||||||
|
BEGIN
|
||||||
|
FOR r IN
|
||||||
|
SELECT c.conname
|
||||||
|
FROM pg_constraint c
|
||||||
|
JOIN pg_class t ON c.conrelid = t.oid
|
||||||
|
WHERE t.relname = 'vitals_baseline'
|
||||||
|
AND c.contype = 'c'
|
||||||
|
AND pg_get_constraintdef(c.oid) ILIKE '%source%'
|
||||||
|
AND pg_get_constraintdef(c.oid) ILIKE '%IN %'
|
||||||
|
LOOP
|
||||||
|
EXECUTE format('ALTER TABLE vitals_baseline DROP CONSTRAINT %I', r.conname);
|
||||||
|
END LOOP;
|
||||||
|
END $$;
|
||||||
|
|
||||||
|
ALTER TABLE vitals_baseline ADD CONSTRAINT vitals_baseline_source_check
|
||||||
|
CHECK (source IN ('manual', 'apple_health', 'garmin', 'withings', 'csv'));
|
||||||
|
|
@ -477,6 +477,7 @@ async def csv_import_execute(
|
||||||
m,
|
m,
|
||||||
)
|
)
|
||||||
except Exception as exec_err:
|
except Exception as exec_err:
|
||||||
|
logger.exception("Universal-CSV-Import fehlgeschlagen: %s", exec_err)
|
||||||
cur.execute("ROLLBACK TO SAVEPOINT csv_import_exec")
|
cur.execute("ROLLBACK TO SAVEPOINT csv_import_exec")
|
||||||
cur.execute(
|
cur.execute(
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ Semantic Versioning: MAJOR.MINOR.PATCH
|
||||||
|
|
||||||
APP_VERSION = "0.9p"
|
APP_VERSION = "0.9p"
|
||||||
BUILD_DATE = "2026-04-09"
|
BUILD_DATE = "2026-04-09"
|
||||||
DB_SCHEMA_VERSION = "20260409b" # u. a. 048 vitals_baseline.source csv
|
DB_SCHEMA_VERSION = "20260409c" # 048/049 vitals_baseline.source csv + SAVEPOINT Import
|
||||||
|
|
||||||
MODULE_VERSIONS = {
|
MODULE_VERSIONS = {
|
||||||
"auth": "1.2.0",
|
"auth": "1.2.0",
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user