public function runQuery(QueryInterface $query, array $options = [])
    {
        $options += [
            'className' => Entity::class,
            'namespaceId' => $this->namespaceId
        ];

        $iteratorConfig = [
            'itemsKey' => 'batch.entityResults',
            'resultTokenKey' => 'query.startCursor',
            'nextResultTokenKey' => 'batch.endCursor',
            'setNextResultTokenCondition' => function ($res) use ($query) {
                if (isset($res['batch']['moreResults'])) {
                    $moreResultsType = $res['batch']['moreResults'];
                    // Transform gRPC enum to string
                    if (is_numeric($moreResultsType)) {
                        $moreResultsType = MoreResultsType::name($moreResultsType);
                    }

                    return $query->canPaginate() && $moreResultsType === 'NOT_FINISHED';
                }

                return false;
            }
        ];

        $runQueryObj = clone $query;
        $runQueryFn = function (array $args = []) use (&$runQueryObj, $options) {
            $args += [
                'query' => []
            ];

            // The iterator provides the startCursor for subsequent pages as an argument.
            $requestQueryArr = $args['query'] + $runQueryObj->queryObject();
            $request = [
                'projectId' => $this->projectId,
                'partitionId' => $this->partitionId($this->projectId, $options['namespaceId']),
                $runQueryObj->queryKey() => $requestQueryArr
            ] + $this->readOptions($options) + $options;

            $res = $this->connection->runQuery($request);

            // When executing a GQL Query, the server will compute a query object
            // and return it with the first response batch.
            // Automatic pagination with GQL is accomplished by requesting
            // subsequent pages with this query object, and discarding the GQL
            // query. This is done by replacing the GQL object with a Query
            // instance prior to the next iteration of the page.
            if (isset($res['query'])) {
                $runQueryObj = new Query($this->entityMapper, $res['query']);
            }

            return $res;
        };

        return new EntityIterator(
            new EntityPageIterator(
                function (array $entityResult) use ($options) {
                    return $this->mapEntityResult($entityResult, $options['className']);
                },
                $runQueryFn,
                [],
                $iteratorConfig
            )
        );
    }