Description
tests/core/pubsub/test_gossipsub_identify_aware_publish.py::test_publish_after_identify_still_works flakes on CI (e.g. tox (3.13, core) on PR #1203, job 95452018160).
Failure:
AssertionError: Normal publish (after identify) was not delivered.
(from trio.TooSlowError inside wait_for_pubsub_payload, 10s cap)
Same commit passed tox (3.10/3.11/3.12, core); failure is timing-dependent, not health-monitor related.
Root cause
The test waits for pubsub stream and SUBSCRIBE RPC (wait_for_peer, wait_for_subscription) then publishes. That is necessary but not sufficient for GossipSub delivery.
After subscribe() before connect(), GossipSub.join() creates an empty mesh[topic]. Peers are added to the mesh and receive GRAFT on the heartbeat loop, which:
- Starts with
await trio.sleep(heartbeat_initial_delay) (default 0.1s)
- Then runs every
heartbeat_interval (100s in this test file via _HEARTBEAT_DISABLED = 100 to avoid mcache sliding on slow CI)
If connect/identify completes after the first 0.1s heartbeat, the next mesh repair is ~100s later. The test only waits 10s for the payload → flake. If identify finishes before 0.1s, the first heartbeat GRAFTs the peer and the test passes.
Relevant code:
- Test:
tests/core/pubsub/test_gossipsub_identify_aware_publish.py (test_publish_after_identify_still_works)
- Heartbeat delay:
libp2p/pubsub/gossipsub.py (heartbeat() → trio.sleep(heartbeat_initial_delay))
- Mesh fill on heartbeat:
mesh_heartbeat() / emit_graft
What is already event-driven (good)
Pubsub.wait_for_peer / wait_for_subscription — trio.Event + fail_after cap
wait_for_pubsub_payload — blocks on async for subscription, 10s is only a safety cap
What is still time-driven (problem)
- Mesh membership after subscribe-before-connect relies on heartbeat timing, not an event the test waits on.
- Same file still has
await trio.sleep(4) in test_three_nodes_publish_before_full_mesh (explicit time wait).
Proposed fix
- Add a test helper (or use existing patterns) to wait until peer
B is in gossipsub.mesh[topic] on both sides (or until GRAFT has been emitted for that topic), event-based with a reasonable timeout — not a longer sleep.
- Use it in
test_publish_after_identify_still_works after the existing wait_for_peer / wait_for_subscription calls and before publish.
- Optionally replace
trio.sleep(4) in the three-node test with the same mesh-ready wait.
Alternative (narrower): trigger an immediate mesh maintenance pass when a new gossipsub peer subscribes to a topic we are already subscribed to, instead of waiting for the next heartbeat — but that is a production-code change; test-side mesh wait is the minimal fix.
Related
Are you planning to do it yourself in a pull request?
Yes
Description
tests/core/pubsub/test_gossipsub_identify_aware_publish.py::test_publish_after_identify_still_worksflakes on CI (e.g.tox (3.13, core)on PR #1203, job 95452018160).Failure:
(from
trio.TooSlowErrorinsidewait_for_pubsub_payload, 10s cap)Same commit passed
tox (3.10/3.11/3.12, core); failure is timing-dependent, not health-monitor related.Root cause
The test waits for pubsub stream and SUBSCRIBE RPC (
wait_for_peer,wait_for_subscription) then publishes. That is necessary but not sufficient for GossipSub delivery.After
subscribe()beforeconnect(),GossipSub.join()creates an emptymesh[topic]. Peers are added to the mesh and receive GRAFT on the heartbeat loop, which:await trio.sleep(heartbeat_initial_delay)(default 0.1s)heartbeat_interval(100s in this test file via_HEARTBEAT_DISABLED = 100to avoid mcache sliding on slow CI)If connect/identify completes after the first 0.1s heartbeat, the next mesh repair is ~100s later. The test only waits 10s for the payload → flake. If identify finishes before 0.1s, the first heartbeat GRAFTs the peer and the test passes.
Relevant code:
tests/core/pubsub/test_gossipsub_identify_aware_publish.py(test_publish_after_identify_still_works)libp2p/pubsub/gossipsub.py(heartbeat()→trio.sleep(heartbeat_initial_delay))mesh_heartbeat()/emit_graftWhat is already event-driven (good)
Pubsub.wait_for_peer/wait_for_subscription—trio.Event+fail_aftercapwait_for_pubsub_payload— blocks onasync for subscription, 10s is only a safety capWhat is still time-driven (problem)
await trio.sleep(4)intest_three_nodes_publish_before_full_mesh(explicit time wait).Proposed fix
Bis ingossipsub.mesh[topic]on both sides (or until GRAFT has been emitted for that topic), event-based with a reasonable timeout — not a longer sleep.test_publish_after_identify_still_worksafter the existingwait_for_peer/wait_for_subscriptioncalls and beforepublish.trio.sleep(4)in the three-node test with the same mesh-ready wait.Alternative (narrower): trigger an immediate mesh maintenance pass when a new gossipsub peer subscribes to a topic we are already subscribed to, instead of waiting for the next heartbeat — but that is a production-code change; test-side mesh wait is the minimal fix.
Related
Are you planning to do it yourself in a pull request?
Yes