1
votes

In GraphQL (Apollo, Sequelize and SQLite), I am using a field to resolve the model type of a polymorphic association. When caching, a problem in resolving the association appears.

Backend:

class AssignTModel extends Model {
    async getAction(options)  {     
        if (!this.actionType) return Promise.resolve(null);
            const mixinMethodName = `get${uppercaseFirst(this.actionType)}`;
            const action=await this[mixinMethodName](options);
            if (action) action.myResolve=this.actionType;
            return action;
        }
    }
    AssignTModel.init({
        id:{ type: Sequelize.INTEGER,
            primaryKey: true,
            autoIncrement: true     },
    . . .
        actionId:{ type: Sequelize.INTEGER},
        actionType:{ type: DataTypes.STRING },
    }, {sequelize,modelName: 'assignt'});
    . . .
    AssignTModel.belongsTo(ReminderModel, { foreignKey: 'actionId', constraints: false });
    AssignTModel.belongsTo(ServiceModel, { foreignKey: 'actionId', constraints: false });
    const AssignT = sequelize.models.assignt;
    . . .
const typeDefs = gql`
 union Action = Reminder | Service
    type AssignT{
        id:Int
  . . .

        action:Action
    }
. . .
    type Query {
      . . .
      action(id:Int):[Action],
    . . .

  const resolvers = {
. . .
    Action:{
        __resolveType(obj, context, info){
          if(obj && obj.myResolve && obj.myResolve === "reminder" ){
            return 'Reminder';
          }

          if(obj && obj.myResolve && obj.myResolve === "service" ){
            return 'Service';
          }
          return null;
        },
    },
. . .
    AssignT: {
        . . .
        action: async (assignt) => assignt.getAction(),
    },

Frontend:

In the React.JS application when I enable Cache on a Query I am getting a problem in resolving the polymorphic association:

FORM_QUERY = gql`query ($id:Int){
                  nodes:assignT(id:$id){
                    id
                    . . .
                    action {
                        ... on Reminder{
                            id
                            label
                          }
                        ... on Service{
                            id
                            label
                          }
                    }
                  }
                }`;

Not OK --> <Query query={FORM_QUERY} variables={{id:id}} fetchPolicy="cache-and-network">

OK --> <Query query={FORM_QUERY} variables={{id:id}} fetchPolicy="no-cache">

This problem does not appear on the GraphQL Playground that is why I doubted the Cache.

How can I solve this problem while maintaining Cache?

1
I think I have the same issue. Could you give more details about the errors it raises ?Thomas
@Thomas it works when the action is Reminder and simply does not load data (I got empty data) when the action is Service and gives a warning concerning fields defined in Reminder but not in Service.Paul Ghobril

1 Answers

1
votes

Found and solved. I am posting the answer so it may help someone facing the same problem.

The problem was about not using the IntrospectionFragmentMatcher. In fact, I have seen this warning but I was planning to solve it later on and did not directly make the link to my problem.

the solution is as follows:

import { InMemoryCache, NormalizedCacheObject,IntrospectionFragmentMatcher } from 'apollo-cache-inmemory';
import {ApolloClient} from "apollo-boost";

const possibleTypes = {
  __schema: {
    types: [{
        kind: 'UNION',
        name: 'Action',
        possibleTypes: [
          { name: 'Service' },
          { name: 'Reminder' },
        ]
      },
    ]
  },
}

const fragmentMatcher = new IntrospectionFragmentMatcher({
    introspectionQueryResultData: possibleTypes
})
const cache = new InMemoryCache({
                    fragmentMatcher
                })
const uri= 'http://localhost:4000/';
const link = createHttpLink({ uri, fetch });
const client= new ApolloClient({
  cache,
  link
});