Deduplicate unchanged uncached computed var deltas

Merged
MA
1mo ago
+492-28

Type of change

  • New feature (non-breaking change which adds functionality)
  • This change requires a documentation update

Description

Uncached computed vars (@rx.var(cache=False)) are recomputed on every state update, but the recomputed value is only sent to the frontend when it differs from the value that was last sent to the client. This avoids unnecessary re-renders when an uncached var recomputes to the same value.

Key changes:

  1. Delta value tracking: Added _delta_value_key() function to generate comparable keys for values going into deltas. Immutable scalars (str, int, float, bool, None) are their own key; other values are keyed by a digest of their JSON serialization. Values that cannot be serialized are marked as unkeyable and always sent.

  2. ComputedVar recording: Added _record_delta_value() method to ComputedVar that records the last value sent to each client (keyed by client token, since a single state instance can serve multiple clients via linked shared states). Returns whether the value differs from the last recorded value.

  3. Delta filtering: Modified BaseState.get_delta() to skip unchanged uncached computed vars from the delta. For async uncached vars, added _drop_unchanged_delta_value() helper to await the coroutine and drop it if unchanged.

  4. Redis compatibility: The recorded value is stored as an instance attribute (with a special naming convention) so it gets serialized to Redis, ensuring consistency across server restarts.

  5. Documentation: Updated docs/vars/computed_vars.md to explain the new behavior.

Tests

  • Added 7 comprehensive unit tests covering:
    • Basic unchanged value omission
    • Redis state persistence
    • Mutable values and in-place mutations
    • Multi-client scenarios
    • Unkeyable (non-serializable) values
    • Async uncached vars
  • Updated 2 existing tests to reflect the new behavior
  • All tests pass with adequate coverage

Checklist

  • Tests pass with adequate coverage
  • uv run ruff check . and uv run ruff format . clean
  • uv run pyright reflex tests passes
  • Documentation updated

https://claude.ai/code/session_01Fhci3gBdffJ84uzNGKrY3n