Skip to content

Implement Client-Side Caching for Calculations #193

@SvenVw

Description

@SvenVw

Background

The fdm-app currently performs several computationally expensive calculations, particularly for features like Norms, Balance, and Advice. These calculations are often re-run whenever relevant components render, casuing users to wait before results are in.

To improve performance and create a more responsive UI, this task proposes implementing a client-side caching layer. This will store the results of expensive calculations in the user's browser, allowing the data to be reused across different parts of the application without repeating the computation.

What This Solves

  • Performance: Reduces the time it takes to display pages that rely on calculated data.
  • User Experience: Creates a faster, smoother, and more responsive UI.
  • Reusability: Allows the calculated output to be easily consumed by multiple components without triggering recalculations.

Implementation Plan

1. Add Dependency to fdm-app

  • Add the object-hash library to fdm-app/package.json. This will be used to create reliable hashes of input data for cache invalidation.

2. Create the Calculation Cache Store

  • Create a new file at fdm-app/app/store/calculations.ts.
  • In this file, define a new zustand store that will manage the cached data.
  • Use the persist middleware from zustand/middleware to save the store's state to localStorage.

3. Configure Cache Persistence and Versioning

  • Configure the persist middleware with a static name (e.g., calculations).
  • Implement automatic cache invalidation on application updates by passing the app's version from fdm-app/package.json to the version option of the middleware.
  • This requires updating fdm-app/vite.config.ts to read the package.json version and expose it as a global variable (e.g., __APP_VERSION__).

4. Implement Cache Logic

  • The store's state will hold the results for norms, balance, and advice.

  • Each cached item will store the data and a hash of the inputs that generated it.

  • Create getter functions (e.g., getNorms) that contain the core caching logic:

    • Generate a hash of the current input data using object-hash.
    • Compare this new hash to the one stored in the cache.
    • Cache Hit: If hashes match, return the cached data.
    • Cache Miss: If hashes do not match, perform the calculation, store the new result and hash, and then return the new data.

5. Implement Cache Invalidation

  • The cache must be invalidated under three conditions:

    1. Input Change: Handled automatically by the hashing mechanism.
    2. App Version Change: Handled automatically by the version middleware option.
    3. User Logout: Add a clearCache action to the store. This action must be called from the application's logout logic to clear all data from the previous session.

6. Refactor fdm-app Routes and Components

  • Identify and refactor the primary routes and components responsible for the calculations.
  • For Norms: The main target for refactoring is the fdm-app/app/routes/farm.$b_id_farm.$calendar.norms.tsx route and its associated components, such as fdm-app/app/components/blocks/norms/farm-norms.tsx and fdm-app/app/components/blocks/norms/field-norms.tsx.
  • For Balance and Advice: Locate the equivalent routes and components for these features and apply the same refactoring pattern.
  • The refactoring will involve replacing direct calls to calculation functions with asynchronous calls to the new zustand store's getter methods.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions