Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a parallel async event handler to OnionMessenger and pass it directly to BackgroundProcessor #3060

Merged

Conversation

TheBlueMatt
Copy link
Collaborator

This adds an OnionMessenger::process_pending_events_async
mirroring the same in ChannelManager. However, unlike the one in
ChannelManager, this processes the events in parallel by spawning
all futures and using the new MultiFuturePoller.

Because OnionMessenger just generates a stream of messages to
store/fetch, we first process all the events to store new messages,
await them, then process all the events to fetch stored messages,
ensuring reordering shouldn't result in lost messages (unless we
race with a peer disconnection, which could happen anyway).

This allows us to have a bound on any `OnionMessenger` without
having to create bounds for every bound in `OnionMessenger`.
If we have a handful of futures we want to make progress on
simultaneously we need some way to poll all of them in series,
which we add here in the form of `MultiFuturePoller`. Its probably
not as effecient as some of the options in the `futures` crate, but
it is very trivial and not that bad.
@TheBlueMatt TheBlueMatt force-pushed the 2024-05-parallel-async-om-events branch 2 times, most recently from e5106f9 to a915c6f Compare May 10, 2024 22:54
@codecov-commenter
Copy link

codecov-commenter commented May 10, 2024

Codecov Report

Attention: Patch coverage is 78.07018% with 25 lines in your changes missing coverage. Please review.

Project coverage is 92.08%. Comparing base (0ffa4b3) to head (fadb268).
Report is 76 commits behind head on main.

Files Patch % Lines
lightning/src/util/async_poll.rs 29.41% 11 Missing and 1 partial ⚠️
lightning/src/onion_message/messenger.rs 83.82% 7 Missing and 4 partials ⚠️
lightning-background-processor/src/lib.rs 93.10% 0 Missing and 2 partials ⚠️

❗ Your organization needs to install the Codecov GitHub app to enable full functionality.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3060      +/-   ##
==========================================
+ Coverage   89.83%   92.08%   +2.25%     
==========================================
  Files         116      118       +2     
  Lines       96472   113057   +16585     
  Branches    96472   113057   +16585     
==========================================
+ Hits        86663   104113   +17450     
+ Misses       7244     6726     -518     
+ Partials     2565     2218     -347     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@TheBlueMatt TheBlueMatt force-pushed the 2024-05-parallel-async-om-events branch 2 times, most recently from 62317c8 to 15d1135 Compare May 13, 2024 19:00
@valentinewallace
Copy link
Contributor

Looks like 1.63 builds are sad

Comment on lines +55 to +81
/// A type implementing [`EntropySource`]
type EntropySource: EntropySource + ?Sized;
/// A type that may be dereferenced to [`Self::EntropySource`]
type ES: Deref<Target = Self::EntropySource>;
/// A type implementing [`NodeSigner`]
type NodeSigner: NodeSigner + ?Sized;
/// A type that may be dereferenced to [`Self::NodeSigner`]
type NS: Deref<Target = Self::NodeSigner>;
/// A type implementing [`Logger`]
type Logger: Logger + ?Sized;
/// A type that may be dereferenced to [`Self::Logger`]
type L: Deref<Target = Self::Logger>;
/// A type implementing [`NodeIdLookUp`]
type NodeIdLookUp: NodeIdLookUp + ?Sized;
/// A type that may be dereferenced to [`Self::NodeIdLookUp`]
type NL: Deref<Target = Self::NodeIdLookUp>;
/// A type implementing [`MessageRouter`]
type MessageRouter: MessageRouter + ?Sized;
/// A type that may be dereferenced to [`Self::MessageRouter`]
type MR: Deref<Target = Self::MessageRouter>;
/// A type implementing [`OffersMessageHandler`]
type OffersMessageHandler: OffersMessageHandler + ?Sized;
/// A type that may be dereferenced to [`Self::OffersMessageHandler`]
type OMH: Deref<Target = Self::OffersMessageHandler>;
/// A type implementing [`CustomOnionMessageHandler`]
type CustomOnionMessageHandler: CustomOnionMessageHandler + ?Sized;
/// A type that may be dereferenced to [`Self::CustomOnionMessageHandler`]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: end sentences in periods

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think they're full sentences?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AChannelManager's docs have the same sentence structure and use periods. Feel free to ignore, though.

lightning/src/util/async_poll.rs Outdated Show resolved Hide resolved
lightning/src/util/async_poll.rs Outdated Show resolved Hide resolved
Comment on lines 1177 to 1179
Some(Event::OnionMessageIntercepted { .. }) => {
futures.push(Some(handler(next_event.unwrap())));
},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could this parallelism affect how users structure their database storage for intercepted OMs? Just wondering if some extra docs could be helpful.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, not sure why it would matter? DBs should generally have no issue with parallel insertions, no matter the structure really.

@TheBlueMatt TheBlueMatt force-pushed the 2024-05-parallel-async-om-events branch from 15d1135 to 8e6dcaa Compare May 28, 2024 15:26
Copy link
Contributor

@valentinewallace valentinewallace left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM pending a second reviewer.

Comment on lines 1172 to 1173
// We process events in parallel, but we want to complete `OnionMessageIntercepted` events
// prior to `OnionMessagePeerConnected` ones.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not have OnionMessenger store the events in two separate Vecs? Seems like the code would be a lot simpler.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Uhhh, right, duh, that would be simpler.

In the next commit, `OnionMessenger` events are handled in parallel
using rust async. When we do that, we'll want to handle
`OnionMessageIntercepted` events prior to
`OnionMessagePeerConnected` ones.

While we'd generally prefer to handle all events in the order they
were generated, if we want to handle them in parallel, we don't
want a `OnionMessageIntercepted` event to start being processed,
then handle an `OnionMessagePeerConnected` prior to the first
completing. This could cause us to store a freshly-intercepted
message for a peer in a DB that was just wiped because the peer
is now connected.

This does run the risk of processing a `OnionMessagePeerConnected`
event prior to an `OnionMessageIntercepted` event (because a peer
connected, then disconnected, then we received a message for that
peer all before any events were handled), that is somewhat less
likely and discarding a message in a rare race is better than
leaving a message lying around undelivered.

Thus, here, we store `OnionMessenger` events in separate `Vec`s
which we can pull from in message-type-order.
This adds an `OnionMessenger::process_pending_events_async`
mirroring the same in `ChannelManager`. However, unlike the one in
`ChannelManager`, this processes the events in parallel by spawning
all futures and using the new `MultiFuturePoller`.

Because `OnionMessenger` just generates a stream of messages to
store/fetch, we first process all the events to store new messages,
`await` them, then process all the events to fetch stored messages,
ensuring reordering shouldn't result in lost messages (unless we
race with a peer disconnection, which could happen anyway).
When `OnionMessenger` first developed a timer and events interface,
we accessed the `OnionMessenger` indirectly via the `PeerManager`.
While this is a fairly awkward interface, it avoided a large pile
of generics on the background processor interfaces. However, since
we now have an `AOnionMessenger` trait, this concern is no longer
significant. Further, because we now want to use the built-in
`OnionMessenger` async event processing method, we really need a
direct referene to the `OnionMessenger` in the background
processor, which we add here optionally.
This never really made a lot of sense from an API perspective, but
was required to avoid handing the background processor an explicit
`OnionMessegner`, which we are now doing. Thus, we can simply drop
these bounds as unnecessary.
@TheBlueMatt TheBlueMatt force-pushed the 2024-05-parallel-async-om-events branch from 8e6dcaa to fadb268 Compare June 3, 2024 18:51
jkczyz
jkczyz previously approved these changes Jun 3, 2024
Copy link
Contributor

@jkczyz jkczyz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

lightning-background-processor/src/lib.rs Show resolved Hide resolved
@TheBlueMatt
Copy link
Collaborator Author

Addressed @jkczyz's point and squashed:

$ git diff-tree -U1 fadb26875 21aebd2d7
diff --git a/lightning-background-processor/src/lib.rs b/lightning-background-processor/src/lib.rs
index 6b7cd5b05..a17f514a5 100644
--- a/lightning-background-processor/src/lib.rs
+++ b/lightning-background-processor/src/lib.rs
@@ -57,5 +57,2 @@ use std::time::Instant;

-#[cfg(not(feature = "std"))]
-use alloc::boxed::Box;
-
 /// `BackgroundProcessor` takes care of tasks that (1) need to happen periodically to keep
@@ -696,3 +693,3 @@ where
 		let fetch_time = &fetch_time;
-		Box::pin(async move { // We should be able to drop the Box once our MSRV is 1.68
+		async move { // We should be able to drop the Box once our MSRV is 1.68
 			if let Some(network_graph) = network_graph {
@@ -711,3 +708,3 @@ where
 			event_handler(event).await;
-		})
+		}
 	};

@valentinewallace
Copy link
Contributor

LGTM after the comment about Box is removed.

@TheBlueMatt TheBlueMatt force-pushed the 2024-05-parallel-async-om-events branch from 21aebd2 to eedceeb Compare June 3, 2024 21:25
@TheBlueMatt
Copy link
Collaborator Author

🤦

$ git diff-tree -U1 21aebd2d eedceeb3
diff --git a/lightning-background-processor/src/lib.rs b/lightning-background-processor/src/lib.rs
index a17f514a5..a5d56c459 100644
--- a/lightning-background-processor/src/lib.rs
+++ b/lightning-background-processor/src/lib.rs
@@ -693,3 +693,3 @@ where
 		let fetch_time = &fetch_time;
-		async move { // We should be able to drop the Box once our MSRV is 1.68
+		async move {
 			if let Some(network_graph) = network_graph {

jkczyz
jkczyz previously approved these changes Jun 3, 2024
@tnull
Copy link
Contributor

tnull commented Jun 4, 2024

Unfortunately tests are still failing due to !Unpin issues.

@TheBlueMatt
Copy link
Collaborator Author

Doh! That's why the Box was there...

@TheBlueMatt TheBlueMatt dismissed stale reviews from jkczyz and valentinewallace via fadb268 June 4, 2024 13:06
@TheBlueMatt TheBlueMatt force-pushed the 2024-05-parallel-async-om-events branch from eedceeb to fadb268 Compare June 4, 2024 13:06
@TheBlueMatt
Copy link
Collaborator Author

Reverted to include the Box again.

@TheBlueMatt TheBlueMatt merged commit 3cd1cb5 into lightningdevkit:main Jun 4, 2024
25 of 32 checks passed
@TheBlueMatt
Copy link
Collaborator Author

lol ffs merged without noticing there were still fixup commits...oh well, they were just doc fixes so not really a big deal.

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.

5 participants