Skip to content
Advertisement

“start_batch was called incorrectly” on gRPC unary call

I make an unary call from PHP code like that:

public function getByIDs(array $ids): array
{
    $request = new GetByIDsRequest();
    $request->setIDs($ids);

    $grpcRequest = $this->client->GetByIDs($request, [], ['timeout' => $this->waitTimeout]);
    $response = $this->callWithRetries($grpcRequest);
    if (!$response->isOk()) {
        $status = $response->getStatus();
        throw new GrpcServerException(__FUNCTION__, $status->getDetails(), (int)$status->getCode());
    }

    ... // business logic here
}

private function callWithRetries(GrpcUnaryCall $grpcRequest): GrpcUnaryCallResponse
{
    $response = null;
    for ($attempt = 0; $attempt <= self::$maxRetries; $attempt++) {
        if ($attempt > 0) {
            usleep(mt_rand(1, 5) * self::$waitBeforeRetry);
        }
        $response = $this->unaryCall($grpcRequest);
        $status = $response->getStatus()->getCode();
        if ($response->isOk() || !self::isRetryable($status)) {
            return $response;
        }
    }
    return $response;
}

protected function unaryCall(UnaryCall $call): GrpcUnaryCallResponse
{
   [$response, $status] = $call->wait();

   return new GrpcUnaryCallResponse(
        $response,
        new GrpcStatus($status)
   );
}

Sometimes I get the LogicException with message “start_batch was called incorrectly”. Any thoughts how to deal with that exception and what is the root cause?

Advertisement

Answer

After some investigation I found out that the problem occurs because of reusing the instance of GrpcUnaryCall in retries. You must not do that otherwise you get a core dump.

The reason we got the LogicException but not a core dump is using a patched gRPC extension.

Some more technical details you can find in this issue

User contributions licensed under: CC BY-SA
8 People found this is helpful
Advertisement