Skip to content
This repository was archived by the owner on Dec 19, 2019. It is now read-only.
This repository was archived by the owner on Dec 19, 2019. It is now read-only.

Allow scalars as resolver return type #152

@paliarush

Description

@paliarush

Problem statement
All resolvers in Magento must implement Resolver interface, which in its turn forces the instance of \GraphQL\Deferred to be returned by each resolver. To be precise, Magento wrapper for deferred, \Magento\Framework\GraphQl\Query\Resolver\Value, must be returned.

/**
* Fetches the data from persistence models and format it according to the GraphQL schema.
*
* @param \Magento\Framework\GraphQl\Config\Element\Field $field
* @param $context
* @param ResolveInfo $info
* @param array|null $value
* @param array|null $args
* @throws \Exception
* @return Value
*/
public function resolve(
   Field $field,
   $context,
   ResolveInfo $info,
   array $value = null,
   array $args = null
) : Value;

The main reason for using deferred in GraphQL is to optimize performance by solving N+1 problem where it exists.
An example of valid deferred usage in Magento can be found in \Magento\CatalogGraphQl\Model\Resolver\Product::resolve.
In all other cases, when there is no need to solve N+1 problem, we end up with boilerplate code like:

$result = function () use ($data) {
    return $data;
};
 return $this->valueFactory->create($result);

Response type unification is one of the reasons why deferred was made the only possible return type for resolvers. However, after implementing more resolvers it became obvious that current design just adds unnecessary complexity to the resolver implementations.
Proposed solution
In addition to deferred, allow scalars and arrays of scalars as return types for \Magento\CatalogGraphQl\Model\Resolver\Product::resolve.
It will also be easier to customize resolver with plugins, if it returns array/scalar instead of deferred object.
Action items

  1. Modify existing resolvers, which have boilerplate code and do not require solving N+1 problem
    Change
 public function resolve(
     Field $field,
     $context,
     ResolveInfo $info,
     array $value = null,
     array $args = null
 ) : Value;

to

 public function resolve(
     Field $field,
     $context,
     ResolveInfo $info,
     array $value = null,
     array $args = null
 );

Also, replace boilerplate code in resolvers

$result = function () use ($data) {
    return $data;
};

return $this->valueFactory->create($result);

with

return $data;
  1. Document the decision and make sure that all new resolvers return deferred only when necessary. Can just mark PR with "requires-documentation" label to leave this part for Magento's documentation team.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions