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

How about a push-pull model? #6

Open
loreanvictor opened this issue May 10, 2024 · 0 comments
Open

How about a push-pull model? #6

loreanvictor opened this issue May 10, 2024 · 0 comments
Labels
enhancement New feature or request

Comments

@loreanvictor
Copy link
Owner

loreanvictor commented May 10, 2024

Note

This is just based on curiosity. As it would cause a refactoring in all of quel and result in potential changes in the API, I would recommend conducting it in a separate branch and studying it further, whether the changes are worth or not, can they be minimised, and will this idea in general simplify quel's internals or not.

Currently, all changes are pushed eagerly throughout the dependency graph. Consumers can of course cache by debouncing changes happening in the same tick, but the computations will necessarily happen multiple times.

An alternative would be a push-pull system: when a source changes, all listeners are notified without getting the new value. They get the new value when they pull it. This allows a separation for computed values (which do not exist atm in quel), that can avoid recalculating their values (i.e. rerunning their expressions) until their own value is pulled by some other consumer. Propagation of change notification would be sped up drastically, and end consumers (i.e. observations) can properly schedule their response to change notifications.

This would be the new process:

  • When a source is changed, it notifies listeners without giving them the value.
  • A new type of sources, Computed values, are introduced. They will be the default to wrap all expressions instead of Observations.
  • Computed values will notify their listeners whenever one of their tracked sources notifies them.
  • Computed values will mark themselves as dirty whenever one of their tracked sources notifies them.
  • Computed values will rerun their expressions whenever their .get() method is called and they are marked as dirty. This will result in their dirty marking to be removed.
  • Observations will wrap given expression in a Computed, and eagerly refetch its value upon notification. This behaviour can be configured to more performant solutions.

Potential benefits:

  • Performance: Unnecessary rerunning of expressions is avoided.
  • Simplicity: The logic for re-running an expression is potentially simplified, just re-run when fetched and dirty.

Potential complications:

  • .get() becomes async. Even a sync expression might depend on an async expression. This might be a simplification though: currently the value returned by .get() might not reflect changes in the sources the expression depends on.
  • Removing dependencies becomes more complicated. Currently when a change in a source triggers a re-run in an expression, but that expression doesn't use the value of said source, then the dependency is removed. When the re-run doesn't happen immediately after change, then a dirty flag needs to be stored for all tracked sources.
  • Scheduling async runs might be more difficult. Currently, a source is changed, triggering an async re-run (if the expression is async), cancelling any pending re-runs. With this change, a .get() will trigger an async re-run, but multiple other .get()s might occur before said re-run ends. Sometimes these .get()s should subscribe to the same result, other times they should cause a cancellation of that re-run and trigger a new re-run (because new dependent sources have changed in the meanwhile).
@loreanvictor loreanvictor added the enhancement New feature or request label May 10, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

1 participant