marker: concurrent (bounded) definition fan-out

The per-definition fan-out applied markers to links in a serial loop -- one compute round-trip per link. On a 1000-link project that serializes N HTTP round-trips (minutes on remote computes). Fan out with asyncio.gather + Semaphore(32): links are independent (own _markers/_link_data), per-link ControllerError stays isolated, and Project.dump is synchronous + atomic (tmp + rename) so concurrent dumps cannot corrupt the topology file.

Converts the definition-create fan-out, the definition-update sync and re-fan-out loops, and the definition-delete cleanup to the shared _marker_apply_concurrently helper. apply_defs_to_new_link stays serial deliberately: all definitions share one link and each push carries the link's full marker set, so concurrent pushes would race and lose markers.
This commit is contained in:
YueGuobin committed 2026-08-07 23:50:41 +08:00
1 parent 0f86dabfa3
commit 078cf92aef
2 files changed
+83 -38

No files matched your search

+15
View File
@@ -433,6 +433,21 @@ async def test_create_marker_definition_fans_out(project):
assert project.marker_definitions["arp"]["highlight_duration"] == 1200
@pytest.mark.asyncio
async def test_definition_fans_out_over_many_links(project):
# The fan-out is concurrent (bounded) — a large topology must not serialize
# N compute round-trips — but behaviorally every link still receives the
# marker and per-link failures stay isolated.
with _valid_bpf():
links = [await _make_link(project) for _ in range(20)]
await project.create_marker_definition("arp", "arp", highlight_duration=700)
for link in links:
assert link.markers["global-arp"]["highlight_duration"] == 700
assert link.markers["global-arp"]["inherited_from"] == "arp"
assert project.marker_definitions["arp"]["highlight_duration"] == 700
@pytest.mark.asyncio
async def test_update_marker_definition_syncs(project):