Skip to content

Conversation

@samuelarbibe
Copy link
Contributor

@samuelarbibe samuelarbibe commented Jan 17, 2026

Fix: Optimize incremental update many records

Problem

The batch update process was using optimisticEffect on every updateManyRecords call within the incremental loop. This caused redundant API calls and potential performance issues during the update process, as optimistic updates and side effects were triggered for each chunk of records rather than once for the entire operation.

Solution

This PR optimizes the useIncrementalUpdateManyRecords hook by:

  1. Disabling optimistic effects, aggregate query refetches, and object operation registration for each individual batch in the loop (skipOptimisticEffect: true, skipRefetchAggregateQueries: true, skipRegisterObjectOperation: true).
  2. Performing a single refetch of records and aggregate queries in the finally block after all batches are processed.
  3. Batching the dispatchObjectRecordOperationBrowserEvent to run once at the end with all updated record IDs.

Changes

  • Modified useIncrementalUpdateManyRecords.ts:
    • Passed skipOptimisticEffect: true to updateManyRecords.
    • Moved refetchFindManyRecords, refetchAggregateQueries, and dispatchObjectRecordOperationBrowserEvent to the finally block of the incrementalFetchAndMutate process.
  • Updated useIncrementalUpdateManyRecords.test.tsx:
    • Added assertions to verify skipOptimisticEffect is true.
    • Verified that refetches occur after the process completes.

After changes:

Screenshot 2026-01-17 at 13 23 10

Closes #17117

… many queries after incremental updates and skip optimistic effects during the update.
@samuelarbibe
Copy link
Contributor Author

Hey @charlesBochet :)
Fixed it, but only partially - can't seem to update the table's data after updating.
Called a refetch, and it actually refetches the data, but still doesn't seem to show the updated data.

I don't know if it has something to do with the cache.
Can I get some assistance on that?

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Jan 17, 2026

Greptile Summary

This PR successfully optimizes incremental batch record updates by deferring all Apollo cache refetches and browser event dispatches until after all batches complete, eliminating the redundant FindMany API calls that were triggered for each batch. The implementation correctly disables optimistic effects during individual batch mutations and consolidates all updates into a single refetch operation at the end, directly addressing issue #17117.

Key Changes:

  • Added skipOptimisticEffect: true to updateManyRecords calls within the batch loop to prevent triggering redundant optimistic effects for each batch
  • Created new useRefetchFindManyRecords hook to encapsulate Apollo FindMany query refetch logic
  • Moved all refetch operations (refetchFindManyRecords, refetchAggregateQueries) and event dispatch to the finally block to execute once after all batches complete
  • Simplified useUpdateMultipleRecordsActions by removing an unnecessary wrapper function
  • Updated tests to verify the new skipOptimisticEffect parameter and assert that refetches occur in the cleanup phase

Test Coverage:

The test suite now verifies that the optimization works correctly including edge cases like process failures, where the finally block still executes to maintain consistency.

Confidence Score: 4/5

  • This PR is safe to merge with a minor test assertion improvement recommended
  • The implementation is sound and directly addresses the performance issue described in Batch edit is triggering too many FindManyRequests #17117. All changes follow existing patterns, use well-established APIs, and the logic is correct. The optimization defers cache updates appropriately to reduce redundant API calls. One minor concern: the test assertion on lines 117-118 should use .toHaveBeenCalledTimes(1) instead of just .toHaveBeenCalled() to strictly verify the refetch is called exactly once per the custom instruction guidelines. This is a style/best-practice issue rather than a functional problem.
  • The test file should be updated to use stricter assertion patterns for verifying mock call counts, but the implementation files are production-ready.

Important Files Changed

Filename Overview
packages/twenty-front/src/modules/object-record/hooks/useIncrementalUpdateManyRecords.ts Optimized hook to disable optimistic effects and refetches during incremental batch updates, deferring all cache updates and events to a single operation after all batches complete. This eliminates redundant API calls and improves performance when updating thousands of records.
packages/twenty-front/src/modules/object-record/hooks/useRefetchFindManyRecords.ts New hook that encapsulates Apollo cache refetch logic for FindMany queries. Clean, single-purpose hook that follows existing patterns in the codebase. Correctly uses Apollo's refetchQueries API to reload all FindMany results for the object type.
packages/twenty-front/src/modules/object-record/record-update-multiple/hooks/useUpdateMultipleRecordsActions.ts Simplified hook to remove unnecessary wrapper function that only passed through the incremental update function. Direct aliasing improves code clarity and eliminates an unnecessary indirection layer.
packages/twenty-front/src/modules/object-record/hooks/tests/useIncrementalUpdateManyRecords.test.tsx Test suite updates add coverage for new skipOptimisticEffect parameter and verify refetchFindManyRecords is called. However, the refetch assertion uses a fragile pattern accessing mock.results[0] instead of storing a direct reference, and doesn't assert the function is called exactly once (should use toHaveBeenCalledTimes(1) per custom instructions).

Sequence Diagram

sequenceDiagram
    participant UI as UI Component
    participant Hook as useIncrementalUpdateManyRecords
    participant Fetch as useIncrementalFetchAndMutate
    participant Update as useUpdateManyRecords
    participant Apollo as Apollo Cache
    participant Event as Browser Event

    UI->>Hook: incrementalUpdateManyRecords(fields)
    Hook->>Fetch: incrementalFetchAndMutate(callback)
    
    Note over Fetch,Update: Batch 1 (Pages 1-3)
    Fetch->>Fetch: Fetch page 1
    Fetch->>Update: updateManyRecords({<br/>skipOptimisticEffect: true,<br/>skipRefetchAggregateQueries: true,<br/>skipRegisterObjectOperation: true})
    Update->>Apollo: Mutate (no cache update)
    Update-->>Fetch: Success
    Fetch->>Fetch: Fetch page 2
    Fetch->>Update: updateManyRecords({...skip flags})
    Update->>Apollo: Mutate (no cache update)
    Update-->>Fetch: Success
    Fetch->>Fetch: Fetch page 3
    Fetch->>Update: updateManyRecords({...skip flags})
    Update->>Apollo: Mutate (no cache update)
    Update-->>Fetch: Success

    Note over Fetch: All batches complete
    Fetch-->>Hook: Complete
    
    Note over Hook,Event: Finally block executes
    Hook->>Apollo: refetchFindManyRecords()
    Apollo-->>Hook: Queries reloaded
    Hook->>Apollo: refetchAggregateQueries()
    Apollo-->>Hook: Aggregates reloaded
    Hook->>Event: dispatchObjectRecordOperationBrowserEvent<br/>(all record IDs)
    Event-->>UI: Listeners notified of bulk operation

    Hook-->>UI: totalUpdatedCount
Loading

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

4 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

@github-actions
Copy link
Contributor

🚀 Preview Environment Ready!

Your preview environment is available at: http://bore.pub:35138

This environment will automatically shut down when the PR is closed or after 5 hours.

Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

No issues found across 4 files

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Batch edit is triggering too many FindManyRequests

1 participant