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:
@@ -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)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user