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

Allows developers to specify limits on internal consistency #353

Open
dphfox opened this issue Jun 21, 2024 · 1 comment
Open

Allows developers to specify limits on internal consistency #353

dphfox opened this issue Jun 21, 2024 · 1 comment
Labels
enhancement New feature or request not ready - design wanted Good idea but needs design work

Comments

@dphfox
Copy link
Owner

dphfox commented Jun 21, 2024

Fusion currently mandates that the entire reactive graph is kept internally consistent, and always updates in a single atomic step. This is great for developer experience, and should absolutely remain default behaviour, but sometimes it can be okay to sacrifice consistency to allow work to be split across multiple update cycles.

One way we could explore this is by introducing wrapper state objects that are allowed to become inconsistent with the rest of the graph, retaining their previous value when they're evaluated as part of an update step. If there's time to spare within the update step, these objects can pull a new value from the state object they wrap and update their dependents.

A simple example:

local a = scope:Value(2)
local b = scope:Value(5)
local sum = scope:Computed(function(use)
    return use(a) + use(b)
end)
local sum = scope:Inconsistent(sum)
local sumIsEven = scope:Computed(function(use)
    return use(sum) % 2 == 0
end
print(peek(sumIsEven)) --> false

If the update cycle is taking too long, the Inconsistent object is allowed to fall out of lockstep with the rest of the reactive graph, meaning graph objects dependent on it won't run:

doLotsOfWork()
a:set(10)
b:set(12)
print(peek(sumIsEven)) --> false
task.wait(1) -- wait for intensity to die down
print(peek(sumIsEven)) --> true
@dphfox dphfox added enhancement New feature or request not ready - evaluating Currently gauging feedback labels Jun 21, 2024
@dphfox dphfox added not ready - design wanted Good idea but needs design work and removed not ready - evaluating Currently gauging feedback labels Sep 30, 2024
@dphblox
Copy link

dphblox commented Oct 1, 2024

We must be incredibly careful around object lifetimes.

  • For the first version of this feature (or any related feature looking to add "memory" to the reactive graph), we should limit the acceptable inputs only to things that we can guarantee won't ever end up with accessible dangling references.
    • OK: Primitives with value semantics (nil, boolean, string, number, vector)
    • OK: Roblox atomics built from primitives with value semantics (Vector2, Color3, UDim2, RbxScriptSignal, RbxScriptConnection, etc...)
    • Not OK: Tables (both frozen and unfrozen) (can point to dangling references via pairs or metatable)
    • Not OK: Arbitrary userdatas (can point to dangling references via metatable)
    • Not OK: Roblox instances (entire thing becomes a dangling reference after :Destroy())
    • Not OK: Functions (dangling references accessible inside the function chunk via upvalues)
  • Concerns about how to handle destructible inputs are left until a later date for now.

This opt-in design does mean that a subgraph must be completely isolated for it to be effectively severed from instant updates. You also can't guarantee that the whole subgraph update in one go, because the objects aren't in sync with each other.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request not ready - design wanted Good idea but needs design work
Projects
None yet
Development

No branches or pull requests

2 participants