feat: add journaled transfer materialization
This commit is contained in:
@@ -22,6 +22,10 @@ class JobConflict(RuntimeError):
|
||||
pass
|
||||
|
||||
|
||||
class FileOperationConflict(RuntimeError):
|
||||
pass
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class CommandAcceptance:
|
||||
duplicate: bool
|
||||
@@ -183,6 +187,87 @@ class ClientStore:
|
||||
),
|
||||
)
|
||||
|
||||
def begin_file_operation(
|
||||
self,
|
||||
operation_id: str,
|
||||
job_id: str,
|
||||
intent_json: str,
|
||||
) -> dict[str, object]:
|
||||
intent = _canonical(json.loads(intent_json))
|
||||
with self._connect() as connection:
|
||||
connection.execute("BEGIN IMMEDIATE")
|
||||
existing = connection.execute(
|
||||
"SELECT * FROM file_journal WHERE operation_id = ?",
|
||||
(operation_id,),
|
||||
).fetchone()
|
||||
if existing:
|
||||
if (
|
||||
existing["job_id"] != job_id
|
||||
or existing["intent_json"] != intent
|
||||
):
|
||||
raise FileOperationConflict(
|
||||
"file operation ID was reused with different intent"
|
||||
)
|
||||
return dict(existing)
|
||||
connection.execute(
|
||||
"""
|
||||
INSERT INTO file_journal (
|
||||
operation_id, job_id, intent_json, state
|
||||
) VALUES (?, ?, ?, 'intent')
|
||||
""",
|
||||
(operation_id, job_id, intent),
|
||||
)
|
||||
row = connection.execute(
|
||||
"SELECT * FROM file_journal WHERE operation_id = ?",
|
||||
(operation_id,),
|
||||
).fetchone()
|
||||
return dict(row)
|
||||
|
||||
def complete_file_operation(
|
||||
self,
|
||||
operation_id: str,
|
||||
result_json: str,
|
||||
) -> dict[str, object]:
|
||||
result = _canonical(json.loads(result_json))
|
||||
with self._connect() as connection:
|
||||
connection.execute("BEGIN IMMEDIATE")
|
||||
existing = connection.execute(
|
||||
"SELECT * FROM file_journal WHERE operation_id = ?",
|
||||
(operation_id,),
|
||||
).fetchone()
|
||||
if existing is None:
|
||||
raise FileOperationConflict("file operation intent does not exist")
|
||||
if existing["state"] == "completed":
|
||||
if existing["result_json"] != result:
|
||||
raise FileOperationConflict(
|
||||
"completed file operation has a different result"
|
||||
)
|
||||
return dict(existing)
|
||||
connection.execute(
|
||||
"""
|
||||
UPDATE file_journal
|
||||
SET result_json = ?, state = 'completed'
|
||||
WHERE operation_id = ?
|
||||
""",
|
||||
(result, operation_id),
|
||||
)
|
||||
row = connection.execute(
|
||||
"SELECT * FROM file_journal WHERE operation_id = ?",
|
||||
(operation_id,),
|
||||
).fetchone()
|
||||
return dict(row)
|
||||
|
||||
def file_operation_rows(self, job_id: str) -> list[dict[str, object]]:
|
||||
with self._connect() as connection:
|
||||
rows = connection.execute(
|
||||
"""
|
||||
SELECT operation_id, job_id, intent_json, result_json, state
|
||||
FROM file_journal WHERE job_id = ? ORDER BY operation_id
|
||||
""",
|
||||
(job_id,),
|
||||
).fetchall()
|
||||
return [dict(row) for row in rows]
|
||||
|
||||
def begin_route_attempt(
|
||||
self,
|
||||
command_id: str,
|
||||
|
||||
Reference in New Issue
Block a user