Git Product home page Git Product logo

Comments (4)

knaeckeKami avatar knaeckeKami commented on June 23, 2024 1

it could be nice to do something like that:

.where((data) => !isDanglingReference(data, config) && !isPartial

the .where((data) => !isDanglingReference(data, config) filter is fine IMO, and this is why this works in the non-nestd case. We would need an additional check check for the nested case, something like this:

Object? denormalizeNode({
  required SelectionSetNode? selectionSet,
  required Object? dataForNode,
  required NormalizationConfig config,
}) {
  if (dataForNode == null) return null;


  if (dataForNode is List) {
     final newList = <Object?>[];
     final reachableData =  dataForNode
         .where((data) => !isDanglingReference(data, config));
     for(final node in reachableDate) {
        try{
            final denormalizedSubNode =  denormalizeNode(
              selectionSet: selectionSet,
              dataForNode: node,
              config: config);
            newList.add(denormalizedSubNode);
        } on PartialDataException { 
            // ignore list items with partial data
        }
    }
    ...

 }

The config actually has a parameter to set whether partial data is allowed or not, but for ferry we have to set it to true, as ferry is strongly typed an partial data would lead to exceptions further down the line when trying the map the denormalized data to the typed objects.

from ferry.

knaeckeKami avatar knaeckeKami commented on June 23, 2024

You can inspect what is happening by inspecting the contents of the cache. (e.g.

       client.cache.store.keys.forEach((key) {
          print(key);
        });
        print(client.cache.store.get('Query'));

The cache stores the results of the queries like this:

{ __typename: Query, 
  pokemons: [ {$ref: Pokemon:0}, {$ref: Pokemon:1}, {$ref: Pokemon:2}, ... ], 
  nestedPokemons: [
     {__typename: NestedPokemon, nested: {$ref: Pokemon:0}}, 
     {__typename: NestedPokemon, nested: {$ref: Pokemon:1}}, 
     ... 
] 

and then each entry like this:

Pokemon:5:  {__typename: Pokemon, id: 5, name: Pokemon 5}

So, when you remove a Pokemon entry from the cache, it is still referenced in the queries.

So, when the data is denormalized, this can lead to issues.

For lists, ferry just ignores the invalid reference, see

.where((data) => !isDanglingReference(data, config))

and

This is what you are seeing in the non-nested case.

For the nested case, the invalid reference happens in a nested object, and we throw a PartialDataException exception here since the referenced object is supposed to be non-nullable.

https://github.com/gql-dart/ferry/blob/f253e437d6ee1bce961dd857697f4f22f2a514e2/packages/normalize/lib/src/denormalize_node.dart#LL78C17-L78C37

I can see why this behavior can be confusing.

from ferry.

knaeckeKami avatar knaeckeKami commented on June 23, 2024

So, evict() does not preserve referential integrity and should be used with caution.

I can imagine improvements in handling danging references though, ferry probably should treat nested objects in lists with dangling references the same is direct dangling references in lists.

I could also see a deleteCascade mode for eviction, where, similarly to the garbage collection method gc(), the whole graph of the cache is traversed so all objects containing references to the evicted entity are removed. This could be very expensive though if the cache is big.

For a workaround for now, you can use writeQuery() to manually remove the evicted item from the the nested query.

from ferry.

ValentinVignal avatar ValentinVignal commented on June 23, 2024

I can imagine improvements in handling danging references though, ferry probably should treat nested objects in lists with dangling references the same is direct dangling references in lists.

Yes it could be nice to do something like that:

.where((data) => !isDanglingReference(data, config) && !isPartial) 

where isPartial is true if the build of the element in the list throw a PartialDataException.

For a workaround for now, you can use writeQuery() to manually remove the evicted item from the nested query.

This is actually what I'm trying to move away from. I'm having a bunch of different queries that fetch a list of Pokemon. When deleting one, I don't really have a way or want to loop over all the cached queries (of potentially different types) to remove the deleted pokemon from the list. That's why I want to use .evict

from ferry.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.