Skip to content

feat: add subscription mechanism to receive all processed events #21402

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

Open
wants to merge 19 commits into
base: main
Choose a base branch
from

Conversation

taefi
Copy link
Contributor

@taefi taefi commented May 8, 2025

Description

This pull request introduces a new subscription mechanism for signals, enhances utility methods, and adds comprehensive test coverage to ensure the correctness of new functionality. The changes are primarily focused on enabling subscribers to receive notifications about the results of processed commands and improving the maintainability of the codebase.

New Subscription Mechanism for Signals:

  • Added a subscribeToPublished method in SignalTree that allows subscribers to listen for the results of processed commands. Subscribers can be removed using the returned callback.

Utility Enhancements:

  • Added a new utility class SignalUtils with methods to retrieve the underlying signal tree and validate commands. This class is marked as internal API.

Fixes #21370

Type of change

  • Bugfix
  • Feature

Checklist

  • I have read the contribution guide: https://vaadin.com/docs/latest/guide/contributing/overview/
  • I have added a description following the guideline.
  • The issue is created in the corresponding repository and I have referenced it.
  • I have added tests to ensure my change is effective and works as intended.
  • New and existing tests are passing locally with my change.
  • I have performed self-review and corrected misspellings.

Additional for Feature type of change

  • Enhancement / new feature was discussed in a corresponding GitHub issue and Acceptance Criteria were created.

Copy link

github-actions bot commented May 8, 2025

Test Results

1 229 files  +1  1 229 suites  +1   1h 12m 43s ⏱️ - 3m 27s
8 451 tests +9  8 395 ✅ +9  56 💤 ±0  0 ❌ ±0 
8 854 runs  +6  8 789 ✅ +6  65 💤 ±0  0 ❌ ±0 

Results for commit 80d8b9b. ± Comparison against base commit e23a828.

♻️ This comment has been updated with latest results.

@taefi taefi marked this pull request as ready for review May 8, 2025 12:57
@taefi taefi marked this pull request as draft May 8, 2025 13:09
@taefi taefi marked this pull request as ready for review May 10, 2025 10:30
@taefi taefi requested review from Legioth and mshabarov May 12, 2025 07:18
Copy link
Member

@Legioth Legioth left a comment

Choose a reason for hiding this comment

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

Partial review. Will look at the rest of the tests later.

}

@Override
public void markAsAborted() {
changes.notifyResultHandlers(CommandResult.rejectAll(results,
"Transaction aborted"));

for (SignalCommand command : changes.getCommands()) {
Copy link
Member

Choose a reason for hiding this comment

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

I don't think this is correct. Commands for an aborted transaction will not be "processed" in the sense that that they will not be involved in the official event ordering. An otherwise valid command that is aborted would otherwise be interpreted as accepted by other observers. This should not be an issue for the Hilla integration since I assume it has not case that would lead to aborting a transaction.

Copy link
Contributor Author

@taefi taefi May 15, 2025

Choose a reason for hiding this comment

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

Commands for an aborted transaction will not be "processed" in the sense that that they will not be involved in the official event ordering.

Well, it depends on what we interpret the meaning of processed. To me, the term "processed" means a command that is delivered to the signal(tree), and either managed to change the value or got rejected. The subscriber is just interested in an indicator of signal(tree) received and considered this command (regardless of the result).

Or maybe, I'm not understanding the question here.

Copy link
Member

Choose a reason for hiding this comment

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

The subscriber is supposed to see all submitted commands in the order they have been processed. The commands from an aborted transaction are never really submitted from the tree's point of view, and should thus never be delivered to subscribers. Preventing commands from being submitted is the whole point of aborting a transaction in this way.

If we would show aborted commands to the listener, then we again need to introduce some external way for the subscriber to know that those commands were actually not accepted by the tree since it's not apparent from the previous state of the tree that those commands wouldn't be accepted. I don't see any reason for ever showing those aborted commands to anyone else so I don't think we need to have that as a reason to also start passing the status.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't see any reason for ever showing those aborted commands to anyone else

Just to make sure we are on the same page: by "anyone else" did you mean:

  1. that only the sender of an aborted command should get it back?
    • This looks ideal, and should technically be possible to create a mapping in Hilla's server-side handler to prevent sending the failed ones to others.
  2. Or, no one should get it back?
    • I don't agree. From a Hilla client's POV (an external observer), it only cares about making sure that my command "arrived" to the server, server look at it, and whatever was the decision (acceptance or rejection) its effect is already reflected in the local server's confirmed state. So it should be able to either apply or reject it on its own server's confirmed state based on the guaranteed order of received commands and the previous state.

we again need to introduce some external way for the subscriber to know that those commands were actually not accepted by the tree since it's not apparent from the previous state of the tree

Maybe, I'm missing all the reasons for an aborted transaction, and there are commands that should not be even delivered back to the client that issued it. If the sender of an aborted/failed command doesn't receive it back, it remains in the "locally applied, not reflected in server's state" forever. Ofc, there could be mechanisms to decide a command wasn't accepted, however, those could be partial.

Copy link
Member

Choose a reason for hiding this comment

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

A transaction can be aborted only when running inside Signal.runInTransaction. I don't see why the Hilla integration would do that which means that those concerns are not relevant.

Copy link
Member

@Legioth Legioth May 16, 2025

Choose a reason for hiding this comment

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

No wait. I forgot that the non-transactional path still goes through the same logic when canCommit() is false. So that complicates things significantly. Maybe we have to go back to passing the status to the subscriber after all.

@@ -90,6 +92,8 @@ public enum Type {

private final Type type;

private final Set<Consumer<SignalCommand>> subscribers = new HashSet<>();
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: I like my subscriber ordered to ensure consistency

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Signals] Provide a way of subscribing to changes / events
4 participants