Clients take a flow's id or key: one resolver in the SDK, id first, explicit id:/key:, a warning for reads and a refusal for changes when a name means two flows, deleted flows found by their last key; sync creates by POST, retries a create race through the drift checks and reports the id; MCP gets create_flow and resolves every flow argument with the caller's token; displays show flow_name; an engine from before ids is named as such

This commit is contained in:
2026-11-02 19:39:14 +01:00
parent fd637e0f1e
commit 53916d869b
20 changed files with 816 additions and 147 deletions
+64
View File
@@ -213,6 +213,70 @@ def test_sync_refuses_a_flow_it_did_not_create(api, flows):
theirs.name = "train"
def test_two_first_syncs_of_one_key_end_with_one_flow(api, flows):
"""The second looked before the first had created the flow.
Its create is refused for the key, so it looks again and updates the
first one's flow, checked first as any stored flow is: a canvas edit made
in between is refused rather than overwritten.
"""
class Late(Client):
looked = False
def find_flow(self, key):
if self.looked:
return super().find_flow(key)
# What it saw before the other sync created the flow.
self.looked = True
return None
target = flows["train"]
target.name = "raced"
try:
first = sync([target], api, origin=ORIGIN)[0]
second = sync([target], Late(http=api.http, token=api.token), origin=ORIGIN)[0]
assert first.created and not second.created
assert second.id == first.id
assert [f["id"] for f in api.flows() if f["name"] == "raced"] == [first.id]
api.put_source(first.id, "fit", "def process(dataset, lr):\n return {}\n")
with pytest.raises(SyncError, match="edited on the canvas"):
sync([target], Late(http=api.http, token=api.token), origin=ORIGIN)
finally:
target.name = "train"
found = api.find_flow("raced")
if found:
api.http.delete(f"{PREFIX}/flows/{found['id']}")
def test_a_synced_flow_is_addressed_by_its_key_under_an_issued_id(api, flows):
"""The id is the engine's own, opaque; the client takes the key and
sends the id, and the history answers with both."""
report = sync([flows["train"]], api, origin=ORIGIN)[0]
train = flow_id(api, "train")
assert report.id == train
assert train != "train" and train.startswith("f_")
[made] = api.import_runs(
[
{
"flow": "train",
"external_id": "elsewhere:1",
"params": {"lr": 0.05},
"created_at": "2026-03-01T10:00:00Z",
"result": {"score": 0.9},
}
]
)
rows = api.runs(flow="train")
assert made["id"] in {row["id"] for row in rows}
assert {(row["flow"], row["flow_name"]) for row in rows} == {(train, "train")}
exported = api.export_runs(flow="train")
assert {(row["flow"], row["flow_name"]) for row in exported} == {(train, "train")}
def test_use_stores_the_rewiring_it_was_given(api, flows):
sync([flows["finetune"]], api, origin=ORIGIN)