Skip to content

[REQUEST] Possibility to disable deduplication against in-flight requests? #376

Open
@loucadufault

Description

@loucadufault

There is a possibility for an inconsistent state of the backend to be seen by the application when calls to the batch function are coalesced under certain conditions.

The scenario is as follows:

await userLoader.load('userA.name')

// elsewhere in the application
storeInCache(await userLoader.loadMany('userA.name', 'userA.updatedAt'))

Let's say the second call to load executes after the first has already triggered the batch function to request from the backend. By the time the second call to load triggers the batch function, the first request is already in-flight, so it makes a second request with the remaining key 'userA.updatedAt'.

Let's also say that by coincidence, userA's name was updated in the backend at time T which caused the state in the backend to atomically change to a new value for userA.name and userA.updatedAt. So userA has a first state at t < T, and a second state at t > T. T is right after the first request to the backend resolved, but right before the second request is received.

Because the second request to the backend deduplicated the 'userA.name' against the in-flight request, the returned value is from the prior state. However, since the 'userA.updatedAt' was received from a later request, the returned value is from the later state. This means that our call to storeInCache will store a version of userA that mixes values from the two real versions of the entity in the backend, creating a representation of the state that never existed in the backend.

The problem also exists for the more basic scenario where 'userA.name' is retrieved and cached at an earlier time, but that can be fixed with this approach from the docs:

More complex cache behavior can be achieved by calling .clear() or .clearAll() rather than disabling the cache completely. For example, this DataLoader will provide unique keys to a batch function due to the memoization cache being enabled, but will immediately clear its cache when the batch function is called so later requests will load new values.

But this doesn't take care of this more complex scenario, since the two loads will coalesce to the same batch function call.

Obviously this is poor backend design and a rare edge case, but I was interested to see if there was any way to mitigate this problem since it does exist.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions