Structured OperationFailure, BatchItemResult, and BatchOperationResult envelopes

This commit is contained in:
2026-05-06 10:26:37 +02:00
parent df3b43d311
commit 48dffedc09
9 changed files with 603 additions and 62 deletions

View File

@@ -388,6 +388,11 @@ class SQLiteAssetRegistryRepository:
),
)
except sqlite3.IntegrityError as exc:
if _is_foreign_key_error(exc):
raise ValidationError(
"Version references an unknown asset",
details={"asset_id": version.asset_id, "version_id": version.version_id},
) from exc
raise ValidationError(
"Version sequence already exists for asset",
details={"asset_id": version.asset_id, "sequence": version.sequence},
@@ -404,29 +409,37 @@ class SQLiteAssetRegistryRepository:
return [AssetVersion.from_dict(_loads(row["payload"])) for row in rows]
def save_audit_event(self, event: AuditEvent) -> AuditEvent:
with self._connect() as conn:
conn.execute(
"""
insert into audit_events (id, target, actor_id, correlation_id, outcome, occurred_at, payload)
values (?, ?, ?, ?, ?, ?, ?)
on conflict(id) do update set
target=excluded.target,
actor_id=excluded.actor_id,
correlation_id=excluded.correlation_id,
outcome=excluded.outcome,
occurred_at=excluded.occurred_at,
payload=excluded.payload
""",
(
event.event_id,
event.target,
event.actor_id,
event.correlation_id,
event.outcome.value,
event.occurred_at,
_json(event.to_dict()),
),
)
try:
with self._connect() as conn:
conn.execute(
"""
insert into audit_events (id, target, actor_id, correlation_id, outcome, occurred_at, payload)
values (?, ?, ?, ?, ?, ?, ?)
on conflict(id) do update set
target=excluded.target,
actor_id=excluded.actor_id,
correlation_id=excluded.correlation_id,
outcome=excluded.outcome,
occurred_at=excluded.occurred_at,
payload=excluded.payload
""",
(
event.event_id,
event.target,
event.actor_id,
event.correlation_id,
event.outcome.value,
event.occurred_at,
_json(event.to_dict()),
),
)
except sqlite3.IntegrityError as exc:
if _is_foreign_key_error(exc):
raise ValidationError(
"Audit event references an unknown actor",
details={"actor_id": event.actor_id, "event_id": event.event_id},
) from exc
raise
return event
def get_audit_event(self, event_id: str) -> AuditEvent:
@@ -482,28 +495,36 @@ class SQLiteAssetRegistryRepository:
return IdempotencyRecord.from_dict(_loads(row["payload"]))
def save_ingestion_job(self, job: IngestionJob) -> IngestionJob:
with self._connect() as conn:
conn.execute(
"""
insert into ingestion_jobs (id, status, actor_id, correlation_id, created_at, updated_at, payload)
values (?, ?, ?, ?, ?, ?, ?)
on conflict(id) do update set
status=excluded.status,
actor_id=excluded.actor_id,
correlation_id=excluded.correlation_id,
updated_at=excluded.updated_at,
payload=excluded.payload
""",
(
job.job_id,
job.status.value,
job.actor_id,
job.correlation_id,
job.created_at,
job.updated_at,
_json(job.to_dict()),
),
)
try:
with self._connect() as conn:
conn.execute(
"""
insert into ingestion_jobs (id, status, actor_id, correlation_id, created_at, updated_at, payload)
values (?, ?, ?, ?, ?, ?, ?)
on conflict(id) do update set
status=excluded.status,
actor_id=excluded.actor_id,
correlation_id=excluded.correlation_id,
updated_at=excluded.updated_at,
payload=excluded.payload
""",
(
job.job_id,
job.status.value,
job.actor_id,
job.correlation_id,
job.created_at,
job.updated_at,
_json(job.to_dict()),
),
)
except sqlite3.IntegrityError as exc:
if _is_foreign_key_error(exc):
raise ValidationError(
"Ingestion job references an unknown actor",
details={"actor_id": job.actor_id, "job_id": job.job_id},
) from exc
raise
return job
def get_ingestion_job(self, job_id: str) -> IngestionJob:
@@ -613,7 +634,8 @@ class SQLiteAssetRegistryRepository:
correlation_id text not null,
created_at text not null,
updated_at text not null,
payload text not null
payload text not null,
foreign key(actor_id) references actors(id)
);
create index if not exists idx_assets_lifecycle on assets(lifecycle);
create index if not exists idx_representations_asset on representations(asset_id);
@@ -666,6 +688,10 @@ def _json(value: dict[str, Any]) -> str:
return json.dumps(value, sort_keys=True, separators=(",", ":"))
def _is_foreign_key_error(exc: sqlite3.IntegrityError) -> bool:
return "FOREIGN KEY" in str(exc).upper()
def _loads(value: str) -> dict[str, Any]:
return json.loads(value)