question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[AC3]: Cache merges and race conditions causing data overwrites

See original GitHub issue

Intended outcome:

Not 100% sure what’s going on here, but I’m following instructions on merging objects in cache, trying to achieve similar behaviour to AC2.

Given I have multiple queries against the same object, I’m looking to ensure the query results from the same query are merged together in cache, even though the queries don’t reference the ID field.

query Attitude($connection: ID!) {
  connection(connectionId: $connection) {
    device {
      attitude {
        roll
        pitch
        heading
      }
    }
  }
}

query FcSummary($connection: ID!) {
  connection(connectionId: $connection) {
    device {
      arming {
        disabledFlags
      }
      power {
        voltage
        mahDrawn
        amperage
      }
      rc {
        rssi
      }
    }
  }
}

Cache setup:

cache.policies.addTypePolicies({
  Query: {
    fields: {
      connection: {
        keyArgs: ["connectionId"],
        merge: (existing, incoming, { mergeObjects }) => {
          return mergeObjects(existing, incoming);
        },
      },
    },
  },
  Connection: {
    fields: {
      device: {
        merge: (existing, incoming, { mergeObjects }) => {
          return mergeObjects(existing, incoming);
        },
      },
    },
  }
});

Actual outcome:

Some sort race condition seems to be taking place when the caches are merged together. The result of the “Attitude” query is causing the result of the “Summary” query to be overwritten.

Here is an example log of this, where I am logging the cache merges in device:

  • FcSummary is merged with existing cache:
(2020-04-19T23:23:42.929Z) existing: {
    "__typename": "FlightController",
    "sensors": [
        0,
        5
    ],
    "status": {
        "__typename": "Status",
        "cycleTime": 552,
        "i2cError": 7,
        "cpuload": 20
    }
}
client.ts:55 (2020-04-19T23:23:42.929Z) incoming: {
    "__typename": "FlightController",
    "arming": {
        "__typename": "Arming",
        "disabledFlags": [
            2,
            15
        ]
    },
    "power": {
        "__typename": "Power",
        "voltage": 0,
        "mahDrawn": 0,
        "amperage": 0
    },
    "rc": {
        "__typename": "RC",
        "rssi": 144
    }
}
client.ts:56 (2020-04-19T23:23:42.929Z) merged: {
    "__typename": "FlightController",
    "sensors": [
        0,
        5
    ],
    "status": {
        "__typename": "Status",
        "cycleTime": 552,
        "i2cError": 7,
        "cpuload": 20
    },
    "arming": {
        "__typename": "Arming",
        "disabledFlags": [
            2,
            15
        ]
    },
    "power": {
        "__typename": "Power",
        "voltage": 0,
        "mahDrawn": 0,
        "amperage": 0
    },
    "rc": {
        "__typename": "RC",
        "rssi": 144
    }
}
  • Very closely after, “Attitude” is merged. However, it seems the results from the previous merge have not yet reached the cache, and the previous “existing” is used:
(2020-04-19T23:23:42.937Z) existing: {
    "__typename": "FlightController",
    "sensors": [
        0,
        5
    ],
    "status": {
        "__typename": "Status",
        "cycleTime": 552,
        "i2cError": 7,
        "cpuload": 20
    }
}
client.ts:55 (2020-04-19T23:23:42.938Z) incoming: {
    "__typename": "FlightController",
    "attitude": {
        "__typename": "Attitude",
        "roll": -6.6,
        "pitch": 1.6,
        "heading": 108
    }
}
client.ts:56 (2020-04-19T23:23:42.938Z) merged: {
    "__typename": "FlightController",
    "sensors": [
        0,
        5
    ],
    "status": {
        "__typename": "Status",
        "cycleTime": 552,
        "i2cError": 7,
        "cpuload": 20
    },
    "attitude": {
        "__typename": "Attitude",
        "roll": -6.6,
        "pitch": 1.6,
        "heading": 108
    }
}

And as you can see the existing cache data is not up to date with the previous merge, so the second merge ends up overwriting the first. This means that the data for the “Summary” is never resolved and so the data doesn’t get rendered.

How to reproduce the issue: Attempted a code sandbox to reproduce, but could not get a reproduction outside of my repo as it behaves correctly: https://codesandbox.io/s/gracious-tesla-4pc2p

Using a naive merge function ({...existing, ...incoming}), this issue is still present in my codebase.

If I roll back to beta-30 (this is the latest version I can get it to work on) then this issue is fixed against my codebase, which means something was changed between beta-30 and beta-31 to break this for me.

The commit which seems to be the only cause is: https://github.com/apollographql/apollo-client/commit/87b9fd250fd73c5c14409dc461bc2941167df2fe, which looks synchronous to me.

I am totally stumped at this to be honest. My only option for now is to make my device object singleton (keyFields: []) which makes the query results merge correctly.

FYI the queries merge correctly when I add the ID field to all my queries, but I’m not looking to solve it that way as the docs seem to suggest what I am doing should work.

Reference: https://www.apollographql.com/docs/react/v3.0-beta/caching/cache-field-behavior/#merging-non-normalized-objects

Versions

@apollo/client@beta-43 down to @apollo/client@beta-31

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:7 (3 by maintainers)

github_iconTop GitHub Comments

2reactions
fresholliecommented, May 3, 2021

Seems to be solved in later versions, forgot to close this!

0reactions
hwillsoncommented, Apr 30, 2021

Let us know if this is still a concern with @apollo/client@latest - thanks!

Read more comments on GitHub >

github_iconTop Results From Across the Web

Race Conditions/Concurrency Defects in Databases
I came across defects caused by race conditions that might occur when we work with databases, while reading Designing Data-Intensive ...
Read more >
Untitled
drbd (8.0.3-1) * Fixed a race condition that could cause us to continue to traverse a bio after it was freed. (led to...
Read more >
V9000 Release Note v8.3.1.8 - FTP Directory Listing - IBM
This release note applies to the following systems: IBM FlashSystem V9000 Control Enclosure, machine type and model (MTM) 9846-AC3 and 9848-AC3 ...
Read more >
Bug listing with status UNCONFIRMED as at 2022/12/24 17 ...
... binary data to CSV/text" status:UNCONFIRMED resolution: severity:enhancement ... Bug:502428 - "Race condition in merge process" status:UNCONFIRMED ...
Read more >
@apollo/client | Yarn - Package Manager
Apollo Client is a fully-featured caching GraphQL client with ... Better handle deferred queries that have cached or partial cached data for them....
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found