marker: rework pause/resume from project-wide to per-definition

The project-wide mute (POST /markers/pause|resume + _markers_paused) paused
every marker with one button. The actual need is per-rule control: pause one
definition and toggle only its inherited global-{name} copies across all links.

- Drop project-level: _markers_paused (init/asdict/load/start_all), the
  pause_all/resume_all_markers methods, and the /markers/pause|resume routes.
- Add per-definition: a persisted `paused` flag on each definition;
  pause/resume_marker_definition fan out update_marker(enabled) to every
  global-{name} copy — instant, via the existing enable_packet_filter toggle
  (no NIO rebuild, pcap/emitted preserved). New links inherit a paused
  definition already off (inherit_marker passes enabled=not paused).
- start_marker takes an enabled kwarg; update_marker's enabled-only short-circuit
  now also covers inherited copies so def pause/resume is instant.
- Routes: POST /marker-definitions/{name}/pause|resume.
- Docs + tests updated.
This commit is contained in:
YueGuobin committed 2026-08-02 22:46:33 +08:00
1 parent e97df86d96
commit 1eeee024bd
7 files changed
+113 -114

No files matched your search

+28 -17
View File
@@ -512,29 +512,40 @@ async def test_update_marker_with_bpf_still_rebuilds_nio(project):
# ---------------------------------------------------------------------------
# Part C: project-level pause/resume fan-out
# Per-definition pause/resume (toggle every inherited global-{name} copy)
# ---------------------------------------------------------------------------
@pytest.mark.asyncio
async def test_pause_all_markers_fans_out_to_capture_nodes(project):
# Part C: project-level pause hits each marker-hosting node once.
async def test_pause_marker_definition_toggles_copies_off(project):
with _valid_bpf():
link = await _make_link(project)
await link.start_marker("m", "icmp")
node = link._nodes[0]["node"]
node.post = AsyncioMagicMock()
project.get_node = MagicMock(return_value=node)
await project.pause_all_markers()
node.post.assert_any_call("/markers/pause")
link1 = await _make_link(project)
link2 = await _make_link(project)
await project.create_marker_definition("arp", "arp")
assert link1.markers["global-arp"]["enabled"] is True
assert link2.markers["global-arp"]["enabled"] is True
await project.pause_marker_definition("arp")
assert project.marker_definitions["arp"]["paused"] is True
assert link1.markers["global-arp"]["enabled"] is False
assert link2.markers["global-arp"]["enabled"] is False
@pytest.mark.asyncio
async def test_resume_all_markers_fans_out(project):
async def test_resume_marker_definition_toggles_copies_on(project):
with _valid_bpf():
link = await _make_link(project)
await link.start_marker("m", "icmp")
node = link._nodes[0]["node"]
node.post = AsyncioMagicMock()
project.get_node = MagicMock(return_value=node)
await project.resume_all_markers()
node.post.assert_any_call("/markers/resume")
await project.create_marker_definition("arp", "arp")
await project.pause_marker_definition("arp")
assert link.markers["global-arp"]["enabled"] is False
await project.resume_marker_definition("arp")
assert project.marker_definitions["arp"]["paused"] is False
assert link.markers["global-arp"]["enabled"] is True
@pytest.mark.asyncio
async def test_paused_definition_inherited_as_disabled(project):
# A link created after the definition was paused inherits it already off.
with _valid_bpf():
await project.create_marker_definition("arp", "arp")
await project.pause_marker_definition("arp")
new_link = await _make_link(project)
assert new_link.markers["global-arp"]["enabled"] is False
-1
View File
@@ -83,7 +83,6 @@ async def test_json():
"supplier": None,
"variables": None,
"marker_definitions": {},
"markers_paused": False,
"created_by": None
}