Skip to content

Using with dataloader-php throws "Could not resolve promise" Exception #150

Closed
@n1ru4l

Description

@n1ru4l

I have three types

type Questionnaire {
  id: Int!
  blocks: [Int]!
}

type Block {
  id: Int!
  wrappers: [Wrapper]!
}

type Wrapper {
  id: Int!
  questions: [Question]!
}

type Question {
  id: Int!
}

type Query {
  questionnaire(questionnaireId: Int!): Questionnaire
  wrapper(wrapperId: Int!): Wrapper
}

Every field that returns a list uses a DataLoader (like in https://github.com/overblog/dataloader-php#using-with-webonyxgraphql). Each DataLoader is identical, despite the tables from which the dataloaders fetch their data.

The following query works fine:

query questionnaire {
  questionnaire(questionnaireId: 1) { # no dataloader
    blocks { # resolver uses dataloader
      wrappers { # resolvers uses dataloader
        id
      }
    }
  }
}

However going one level deeper results in an exception.

query questionnaire {
  questionnaire(questionnaireId: 1) { # no dataloader
    blocks { # resolver uses dataloader
      wrappers { # resolvers uses dataloader
        id
        questions { # resolver uses dataloader
          id
        }
      }
    }
  }
}
InvariantViolation in SyncPromiseAdapter.php line 151:
Could not resolve promise

When I log the status of the promise I get pending.

According to the code this should not happen. https://github.com/webonyx/graphql-php/blob/master/src/Executor/Promise/Adapter/SyncPromiseAdapter.php#L132

When I use the following query (only 2 dataloader) everything is behaving like excpected:

query wrapper {
  wrapper(wrapperId: 1) { # resolvers uses dataloader
    id
    questions { # resolver uses dataloader
      id
    }
  }
}

Edit: This also happens in this resolver function where I chain multiple promises (I am using laravel):

public function resolveIsValidField($questionnaire, $args, $context) {
  $questionnaireId = is_array($questionnaire) ? $questionnaire['id'] : $questionnaire->id;
  /** @var BlockRepositoryInterface $blockRepository */
  $blockRepository = $context['repositories']['blocks'];
  /** @var WrapperRepositoryInterface $wrapperRepository */
  $wrapperRepository = $context['repositories']['wrappers'];
  /** @var QuestionRepositoryInterface $questionRepository */
  $questionRepository = $context['repositories']['questions'];

  $blocks = null;
  $wrappers = null;

  return $blockRepository->findWhereQuestionnaireId($questionnaireId)
    ->then(function (Collection $blockRecords) use (&$blocks, $wrapperRepository) {
      $blocks = $blockRecords;
      $bockIds = $blocks->map(function (Block $block) {
        return $block->id;
      })->toArray();

      return $wrapperRepository->getWhereBlockIds($bockIds);
    })
    ->then(function ($wrapperRecords) use (&$wrappers, $questionRepository) {
      $wrappers = collect($wrapperRecords)->flatten();
      $wrapperIds = $wrappers->pluck('id');
      return $questionRepository->getWhereWrapperIds($wrapperIds->toArray());
    })
    ->then(function ($questionRecords) use (&$blocks, &$wrappers) {
      $questions = collect($questionRecords)->flatten();

      return isQuestionnaireValid($blocks, $wrappers, $questions);
    });
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions