Skip to content

Conversation

@benjamin-stacks
Copy link
Contributor

Not meant to be merged, just testing 3cd2e25 on top of #6762 in CI.

This ability was only used during tests; in actual production, there is
always a DB.

Not having to support the DB-less use is going to make it a lot cleaner
to use the DB as a queue (see stacks-network#6543).

This commit also makes the method names and order of operations a little
less confusing -- we had `send_payload()`, `send_payload_directly()`,
`send_payload_given_db_path()` (ok that one was my fault),
and `send_payload_with_bytes()`.

Now we have this instead:

```
dispatch_to_observer()
-> get_payload_bytes()
-> save_to_db()
-> make_http_request_and_delete_from_db()
   -> make_http_request()
   -> delete_from_db()
```
... instead of using unnamed tuples and long parameter lists.
This will allow us to output warnings if the (non-blocking) delivery
gets too far behind, because we can tell how long it took between
enqueuing the event and actually sending it.

This commit adds another migration to said database, so I slightly
refactored the migration code.
This commit is the main implementation work for stacks-network#6543. It moves event
dispatcher HTTP requests to a separate thread. That way, a slow event
observer doesn't block the node from continuing its work.

Only if your event observers are so slow that the node is continuously
producing events faster than they can be delivered, will it eventually
start blocking again, because the queue size for pending requests is
bounded (at 1,000 right now, but I picked that number out of a hat,
happy to change it if anyone has thoughts).

Each new event payload is stored in the event observer DB, and its
ID is then sent to the subthread, which will make the request and then
delete the DB entry.

That way, if a node is shut down while there are pending requests,
they're in the DB ready to be retried after restart via
`process_pending_payloads()` (which blocks until completion). So that's
exactly as before (except that previously there couldn't have been more
than one or two pending payloads).
This fixes [this integration test failure](https://github.com/stacks-network/stacks-core/actions/runs/20749024845/job/59577684952?pr=6762),
caused by the fact that event delivery wasn't complete by the time the
assertions were made.
Doing this work in the RunLoop implementations' startup code is *almost*
the same thing, but not quite, since the nakamoto run loop might be
started later (after an epoch 3 transition), at which point the event DB
may already have new items from the current run of the application,
which should *not* be touched by `process_pending_payloads`.

This used to not be a problem, but now that that DB is used for the
actual queue of the (concurrently running) EventDispatcherWorker, it has
become one.
This is like 72437b2, but it works for
all the tests instead of only the one.

While only that one test very obviously failed, the issue exists for
pretty much all of the integration tests, because they rely on the
test_observer to capture all relevant data.

Things are fast enough, and therefore we've only seen one blatant
failure, but

1) it's going to be flaky (I can create a whole lot of test failures
   by adding a small artificial delay to event delivery), and
2) it might actually be *hiding* test failures (in some cases, like e.g.
   neon_integrations::deep_contract, we're asserting that certain things
   are *not* in the data, and if the data is incomplete to begin with,
   those assertions are moot).
When switching runloops at the epoch 2/3 transition, this ensures that
the same event dispatcher worker thread is handling delivery, which in
turn ensures that all payloads are delivered in order
This is just to check if CI passes. If it does, we can reasonably assume
that d5fa2fc was all that's necessary.
@benjamin-stacks benjamin-stacks changed the title Feat/non blocking event delivery delay test [CI test only] non-blocking event delivery + artificial delay Jan 9, 2026
@codecov
Copy link

codecov bot commented Jan 9, 2026

Codecov Report

❌ Patch coverage is 85.29862% with 96 lines in your changes missing coverage. Please review.
✅ Project coverage is 73.47%. Comparing base (267c7ef) to head (6acb3ec).
⚠️ Report is 31 commits behind head on develop.

Files with missing lines Patch % Lines
stacks-node/src/event_dispatcher.rs 68.10% 37 Missing ⚠️
stacks-node/src/event_dispatcher/db.rs 89.71% 22 Missing ⚠️
stacks-node/src/event_dispatcher/worker.rs 90.90% 15 Missing ⚠️
stacks-node/src/main.rs 0.00% 8 Missing ⚠️
stacks-node/src/run_loop/nakamoto.rs 25.00% 6 Missing ⚠️
stacks-node/src/tests/neon_integrations.rs 68.75% 5 Missing ⚠️
stacks-node/src/event_dispatcher/tests.rs 98.30% 2 Missing ⚠️
stacks-node/src/run_loop/boot_nakamoto.rs 50.00% 1 Missing ⚠️

❌ Your project check has failed because the head coverage (73.47%) is below the target coverage (80.00%). You can increase the head coverage or adjust the target coverage.

Additional details and impacted files
@@             Coverage Diff             @@
##           develop    #6793      +/-   ##
===========================================
- Coverage    78.40%   73.47%   -4.94%     
===========================================
  Files          585      586       +1     
  Lines       361384   362297     +913     
===========================================
- Hits        283360   266197   -17163     
- Misses       78024    96100   +18076     
Files with missing lines Coverage Δ
stacks-node/src/nakamoto_node/miner.rs 76.71% <100.00%> (-0.67%) ⬇️
stacks-node/src/node.rs 86.40% <100.00%> (-0.02%) ⬇️
stacks-node/src/run_loop/mod.rs 89.65% <100.00%> (ø)
stacks-node/src/run_loop/neon.rs 79.87% <100.00%> (-3.28%) ⬇️
stacks-node/src/tests/signer/mod.rs 67.95% <100.00%> (-1.48%) ⬇️
stacks-node/src/tests/signer/v0.rs 16.61% <ø> (-6.24%) ⬇️
stacks-node/src/run_loop/boot_nakamoto.rs 77.55% <50.00%> (-2.59%) ⬇️
stacks-node/src/event_dispatcher/tests.rs 87.37% <98.30%> (-7.91%) ⬇️
stacks-node/src/tests/neon_integrations.rs 24.89% <68.75%> (+3.04%) ⬆️
stacks-node/src/run_loop/nakamoto.rs 82.51% <25.00%> (-1.24%) ⬇️
... and 4 more

... and 259 files with indirect coverage changes


Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 267c7ef...6acb3ec. Read the comment docs.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Lots of tests failing with state machine update timeouts. It's expected
that the tests take longer now, that's not what we're worried about.
these tests fire a *lot* of events
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant