Implement RFC-022 unified graph write protocol (#343)

* Implement unified graph write protocol

* Preserve recovery error wire compatibility
This commit is contained in:
Andrew Altshuler 2026-07-11 14:02:54 +03:00 committed by GitHub
parent 0c8d769501
commit f758ff0d17
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
80 changed files with 13393 additions and 2050 deletions

View file

@ -212,6 +212,16 @@
}
}
}
},
"503": {
"description": "An overlapping durable recovery intent must be resolved before retry",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorOutput"
}
}
}
}
},
"security": [
@ -310,6 +320,16 @@
}
}
}
},
"503": {
"description": "An overlapping durable recovery intent must be resolved before retry",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorOutput"
}
}
}
}
},
"security": [
@ -397,6 +417,16 @@
}
}
}
},
"503": {
"description": "An overlapping durable recovery intent must be resolved before retry",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorOutput"
}
}
}
}
},
"security": [
@ -477,7 +507,7 @@
}
},
"409": {
"description": "Merge conflict",
"description": "Write-authority conflict",
"content": {
"application/json": {
"schema": {
@ -495,6 +525,16 @@
}
}
}
},
"503": {
"description": "An overlapping durable recovery intent must be resolved before retry",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorOutput"
}
}
}
}
},
"deprecated": true,
@ -795,6 +835,16 @@
}
}
},
"409": {
"description": "Prepared load authority changed before effects",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorOutput"
}
}
}
},
"429": {
"description": "Per-actor admission cap exceeded; honor `Retry-After` header",
"content": {
@ -804,6 +854,16 @@
}
}
}
},
"503": {
"description": "An overlapping durable recovery intent must be resolved before retry",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorOutput"
}
}
}
}
},
"deprecated": true,
@ -884,6 +944,16 @@
}
}
},
"409": {
"description": "Prepared load authority changed before effects",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorOutput"
}
}
}
},
"429": {
"description": "Per-actor admission cap exceeded; honor `Retry-After` header",
"content": {
@ -893,6 +963,16 @@
}
}
}
},
"503": {
"description": "An overlapping durable recovery intent must be resolved before retry",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorOutput"
}
}
}
}
},
"security": [
@ -908,7 +988,7 @@
"mutations"
],
"summary": "Apply a GQ mutation to a branch (canonical mutation endpoint).",
"description": "Writes to the named `branch` (defaults to `main`). Mutations are atomic\nper call and produce a new commit. Returns counts of nodes and edges\naffected. **Destructive**: on success the branch is updated; rejected\nmutations may still acquire locks briefly. Returns 409 on merge conflict.\n\nPairs with `POST /query` (read-only). The legacy `POST /change` route\nhas identical semantics and is kept as a deprecated alias.",
"description": "Writes to the named `branch` (defaults to `main`). Mutations are atomic\nper call and produce a new commit. Returns counts of nodes and edges\naffected. **Destructive**: on success the branch is updated; rejected\nmutations may still acquire locks briefly. Returns 409 when the prepared\nwrite authority changes before effects.\n\nPairs with `POST /query` (read-only). The legacy `POST /change` route\nhas identical semantics and is kept as a deprecated alias.",
"operationId": "cluster_mutate",
"parameters": [
{
@ -973,7 +1053,7 @@
}
},
"409": {
"description": "Merge conflict",
"description": "Write-authority conflict",
"content": {
"application/json": {
"schema": {
@ -991,6 +1071,16 @@
}
}
}
},
"503": {
"description": "An overlapping durable recovery intent must be resolved before retry",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorOutput"
}
}
}
}
},
"security": [
@ -1154,7 +1244,7 @@
}
},
"409": {
"description": "Merge conflict",
"description": "Stored mutation write-authority conflict",
"content": {
"application/json": {
"schema": {
@ -1182,6 +1272,16 @@
}
}
}
},
"503": {
"description": "A stored mutation is blocked by a durable recovery intent",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorOutput"
}
}
}
}
},
"security": [
@ -1900,6 +2000,28 @@
"items": {
"$ref": "#/components/schemas/MergeConflictOutput"
}
},
"read_set_conflict": {
"oneOf": [
{
"type": "null"
},
{
"$ref": "#/components/schemas/ReadSetConflictOutput",
"description": "Set when a prepared write's logical authority changed before effects."
}
]
},
"recovery_required": {
"oneOf": [
{
"type": "null"
},
{
"$ref": "#/components/schemas/RecoveryRequiredOutput",
"description": "Set when an overlapping durable recovery intent must be resolved before\nretry. Its table effects may or may not have started."
}
]
}
}
},
@ -2413,6 +2535,30 @@
}
}
},
"ReadSetConflictOutput": {
"type": "object",
"description": "Structured authority mismatch for an RFC-022 prepared write. Values are\nstrings because members include optional graph commit ids and future\nauthority tokens, not only numeric table versions.",
"required": [
"member"
],
"properties": {
"actual": {
"type": [
"string",
"null"
]
},
"expected": {
"type": [
"string",
"null"
]
},
"member": {
"type": "string"
}
}
},
"ReadTargetOutput": {
"type": "object",
"properties": {
@ -2430,6 +2576,17 @@
}
}
},
"RecoveryRequiredOutput": {
"type": "object",
"required": [
"operation_id"
],
"properties": {
"operation_id": {
"type": "string"
}
}
},
"SchemaApplyOutput": {
"type": "object",
"required": [