Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement InMemoryCache#modify for surgically transforming fields. #5909

Merged
merged 8 commits into from
Feb 10, 2020

Commits on Feb 10, 2020

  1. Configuration menu
    Copy the full SHA
    59d973e View commit details
    Browse the repository at this point in the history
  2. Configuration menu
    Copy the full SHA
    012f7cc View commit details
    Browse the repository at this point in the history
  3. Support delivering initial cache.watch results immediately, if reques…

    …ted.
    
    I needed this functionality for some tests of cache.modify, but I think I
    can expand it into a version of cache.watch that returns an async iterator
    if you do not supply a callback.
    benjamn committed Feb 10, 2020
    Configuration menu
    Copy the full SHA
    7287039 View commit details
    Browse the repository at this point in the history
  4. Implement InMemoryCache#modify for surgically transforming fields.

    The cache.writeQuery and cache.writeFragment methods do a great job of
    adding data to the cache, but their behavior can be frustrating when
    you're trying to remove specific data from a field. The typical cycle of
    reading data, modifying it, and writing it back into the cache does not
    always simply replace the old data, because it may trigger custom merge
    functions which attempt to combine incoming data with existing data,
    leading to confusion.
    
    For cases when you want to apply a specific transformation to an existing
    field value in the cache, we are introducing a new API, cache.modify(id,
    modifiers), which takes an entity ID and an object mapping field names to
    modifier functions. Each modifier function will be called with the current
    value of the field, and should return a new field value, without modifying
    the existing value (which will be frozen in development).
    
    For example, here is how you might remove a particular Comment from a
    paginated Thread.comments array:
    
      cache.modify(cache.identify(thread), {
        comments(comments: Reference[], { readField }) {
          return comments.filter(comment => idToRemove !== readField("id", comment));
        },
      });
    
    In addition to the field value, modifier functions receive a details
    object that contains various helpers familiar from read/merge functions:
    fieldName, storeFieldName, isReference, toReference, and readField; plus a
    sentinel object (details.DELETE) that can be returned to delete the field
    from the entity object:
    
      cache.modify(id, {
        fieldNameToDelete(_, { DELETE }) {
          return DELETE;
        },
      });
    
    As always, modifications are applied to the cache in a non-destructive
    fashion, without altering any data previously returned by cache.extract().
    Any fields whose values change as a result of calling cache.modify
    invalidate cached queries that previously consumed those fields.
    
    As evidence of the usefulness and generality of this API, I was able to
    reimplement cache.delete almost entirely in terms of cache.modify. Next, I
    plan to eliminate the foot-seeking missile known as cache.writeData, and
    show that cache.modify can handle all of its use cases, too.
    benjamn committed Feb 10, 2020
    Configuration menu
    Copy the full SHA
    a4cf135 View commit details
    Browse the repository at this point in the history
  5. Configuration menu
    Copy the full SHA
    f168aea View commit details
    Browse the repository at this point in the history
  6. Simplify StoreWriter#writeSelectionSetToStore using store.get.

    Follow-up to #5919 and 59d973e.
    
    Now that the policies.rootTypenamesById check happens in store.get, we
    don't have to rely on the getFieldValue wrapper to ensure __typename can
    always be determined.
    benjamn committed Feb 10, 2020
    Configuration menu
    Copy the full SHA
    7c5d4fd View commit details
    Browse the repository at this point in the history
  7. Mention PR #5909 in CHANGELOG.md.

    benjamn committed Feb 10, 2020
    Configuration menu
    Copy the full SHA
    6fdab9d View commit details
    Browse the repository at this point in the history
  8. Configuration menu
    Copy the full SHA
    bd25886 View commit details
    Browse the repository at this point in the history