Skip to content

Refactor handler#1806

Merged
GitGab19 merged 8 commits into
stratum-mining:mainfrom
Shourya742:2025-07-08-handlers-refactor
Jul 31, 2025
Merged

Refactor handler#1806
GitGab19 merged 8 commits into
stratum-mining:mainfrom
Shourya742:2025-07-08-handlers-refactor

Conversation

@Shourya742

Copy link
Copy Markdown
Member

This PR aims to relax the strict constraints around handler implementations in the protocol crate, particularly concerning synchronicity and return types.

Handlers are no longer required to take Arc<Mutex<Self>>; instead, they now operate with a mutable reference (&mut self) for state mutation. This change simplifies the design and improves ergonomics.

We are also moving away from the SendTo_ abstraction in favor of returning Option<Vec<Message>>. The goal is to delegate message routing decisions to the upstream implementor rather than enforcing it within the library.

Despite these refactors, users still need to implement the relevant traits and invoke the appropriate handle_*_message methods.

We explored exposing a single handle_message method to unify the interface, but this approach would have forced implementors to implement all handler traits, which is not practical. You can find the associated code changes here: (Shourya742#20)

@Shourya742 Shourya742 force-pushed the 2025-07-08-handlers-refactor branch 2 times, most recently from c3631de to 2dc73fc Compare July 15, 2025 14:28
@plebhash

Copy link
Copy Markdown
Member

an alternative approach (more aligned with the original feedback) would be to allow async methods with the following syntax for the trait definition:

fn handle_x(
   &mut self,
   ...,
) -> impl std::future::Future<Output = Result<(), Error>> + Send;

an implementation would look like this:

async fn handle_x(
  &mut self,
  ...,
) -> Result<(), Error> { ... }

this would allow self to carry async channels and avoid the need to rely on return types for message routing

alternatively, MSRV v1.75.0 would also allow using the async fn syntax on trait definition, as long as we also mark the traits with trait_variant::make proc macro

@Shourya742

Copy link
Copy Markdown
Member Author

an alternative approach (more aligned with the original feedback) would be to allow async methods with the following syntax for the trait definition:

fn handle_x(
   &mut self,
   ...,
) -> impl std::future::Future<Output = Result<(), Error>> + Send;

an implementation would look like this:

async fn handle_x(
  &mut self,
  ...,
) -> Result<(), Error> { ... }

this would allow self to carry async channels and avoid the need to rely on return types for message routing

alternatively, MSRV v1.75.0 would also allow using the async fn syntax on trait definition, as long as we also mark the traits with trait_variant::make proc macro

The key consideration in both this and our current implementation is whether we want the trait implementor to send messages directly from within the handlers, or whether we expect handlers to return a list of client-specific messages to be sent. In the latter case, handle_message implementor would be responsible for sending those messages based on the handler's response.

@GitGab19

Copy link
Copy Markdown
Member

@Shourya742 I think we should try to explore the possibility of sending messages inside the handlers, since it was the original request.

Maybe we could also consider to provide a double option, with one async trait which can be used to send messages directly there, and one trait which returns Option<SameMessageReceived> as we were discussing during yesterday's call.

@Shourya742

Shourya742 commented Jul 16, 2025

Copy link
Copy Markdown
Member Author

@Shourya742 I think we should try to explore the possibility of sending messages inside the handlers, since it was the original request.

Maybe we could also consider to provide a double option, with one async trait which can be used to send messages directly there, and one trait which returns Option<SameMessageReceived> as we were discussing during yesterday's call.

I was thinking the same both approaches make sense, and we could let the implementors decide what works best for them. However, this would leave us with four possible combinations for the trait implementations:

  1. Async + returns Vec
  2. Sync + returns Vec
  3. Async + returns ()
  4. Sync + returns ()

OR

  1. Async + returns Option<>
  2. Sync + returns Option<>

@plebhash

Copy link
Copy Markdown
Member

one trait which returns Option<SameMessageReceived> as we were discussing during yesterday's call.

maybe I'm missing something, but wouldn't the caller context already have SameMessageReceived?

if that's the case, what would be the value of returning the same message again, instead of a simple Ok that signals successful execution?

@Shourya742

Copy link
Copy Markdown
Member Author

one trait which returns Option<SameMessageReceived> as we were discussing during yesterday's call.

maybe I'm missing something, but wouldn't the caller context already have SameMessageReceived?

if that's the case, what would be the value of returning the same message again, instead of a simple Ok that signals successful execution?

Yes, It should process the message and return list of new message to be shared or not shared with client.

@plebhash

Copy link
Copy Markdown
Member

deleted previous message

sorry I'm on mobile... I'll try to follow up later when time allows

@GitGab19

Copy link
Copy Markdown
Member

@Shourya742 I think we should have:

  • async --> sends messages internally and returns Result<(), Error>
  • sync --> returns Result<Vec<MessageToBeSent>, Error>

As pointed out by @plebhash , the caller already has the message in its context (in our current status the caller has the frame), so it makes no sense to return the same message in the sync case.

I don't know if returning the Vec would work well for every case we have, especially in NewTemplate or SetNewPrevHash ones. We need to think a bit more about these cases I guess.

@Shourya742 Shourya742 force-pushed the 2025-07-08-handlers-refactor branch 4 times, most recently from fa07104 to 3b26df9 Compare July 17, 2025 13:29
@Shourya742

Copy link
Copy Markdown
Member Author

We have now moved the handlers into their own crate within the protocol workspace. The handlers now return a unit Result and expect the implementor to manage the message lifecycle deciding how to process and dispatch messages within the handler itself. We now support both sync and async variants of handlers, and we're maintaining MSRV compatibility (thanks @plebhash!). The next step will be to migrate the new tproxy to use the new handlers module as an example implementation demonstrating how the handlers are intended to be used. I'm still exploring ways to improve the trait structure, if nothing significantly better emerges, the current design will be finalized.

Comment thread protocols/v2/handlers-sv2/src/job_declaration.rs Outdated
Comment thread protocols/v2/handlers-sv2/src/template_distribution.rs Outdated
Comment thread protocols/v2/handlers-sv2/src/template_distribution.rs Outdated
@Shourya742 Shourya742 force-pushed the 2025-07-08-handlers-refactor branch 3 times, most recently from 933eb97 to 00c4019 Compare July 20, 2025 13:02
Comment thread protocols/v2/handlers-sv2/src/error.rs Outdated
@GitGab19 GitGab19 linked an issue Jul 29, 2025 that may be closed by this pull request
@coleFD

coleFD commented Jul 29, 2025

Copy link
Copy Markdown
Collaborator

looks great!

@Shourya742 Shourya742 force-pushed the 2025-07-08-handlers-refactor branch from 18202de to df689e2 Compare July 29, 2025 15:03
Comment thread protocols/v2/handlers-sv2/src/mining.rs Outdated
Comment thread protocols/v2/handlers-sv2/src/mining.rs
Comment thread protocols/v2/handlers-sv2/src/mining.rs Outdated
Comment thread protocols/v2/handlers-sv2/src/mining.rs Outdated
Comment thread protocols/v2/handlers-sv2/src/mining.rs Outdated
Comment thread protocols/v2/handlers-sv2/src/mining.rs Outdated
Comment thread protocols/v2/handlers-sv2/src/mining.rs Outdated
Comment thread protocols/v2/handlers-sv2/src/mining.rs Outdated
Comment thread protocols/v2/handlers-sv2/src/mining.rs Outdated
Comment thread protocols/v2/handlers-sv2/src/lib.rs
Previously, `HandlerError` only supported a fixed set of internal error types.
This made it difficult for downstream users implementing library traits to
propagate their own custom error types.

This commit introduces a new `External(Box<dyn Error + Send + Sync>)` variant
to allow wrapping arbitrary error values. This enables implementors to return
non-library errors without requiring changes to the core `HandlerError` enum.
@Shourya742 Shourya742 force-pushed the 2025-07-08-handlers-refactor branch from b709c97 to 52626ca Compare July 30, 2025 13:35
@Shourya742

Copy link
Copy Markdown
Member Author

Thanks for the review, @GitGab19. All suggestions have been addressed.

Comment thread protocols/v2/handlers-sv2/src/mining.rs
Comment thread protocols/v2/handlers-sv2/src/mining.rs
@GitGab19 GitGab19 merged commit 402a0f2 into stratum-mining:main Jul 31, 2025
11 checks passed
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.

Refactor handlers to be sync-agnostic

4 participants