Skip to content

[Messenger] Throw exceptions in BatchHandler in sync mode #49654

@DavidBadura

Description

@DavidBadura

Description

I modified my command handler to use the BatchHandler. I noticed that my handler now behaves differently in sync mode, if you pass null in Acknowledger, than before. In async mode everything runs perfectly.

According to the feature (#43354), the handler in sync mode should work the same as before without the BatchHandler/BatchHandlerTrait.

But if an exception is thrown in the handler, it will be swallowed by the BatchHandlerTrait (sync mode). In other words, the command is always successful, as far as I can tell. Maybe this could also be defined as a bug, because the command always succeeds, which it shouldn't be.

To show this briefly, my Command Batch Handler process method looks like this:

 private function process(array $jobs): void
{
    foreach ($jobs as [$message, $ack]) {
        try {

            // do something...

            $ack->ack();
        } catch (Throwable $e) {
            $ack->nack($e);
        }
    }
}

The following happens when the handler is executed (sync mode):

  • add message in jobs
  • force flush (trigger process)
  • execute process
  • developer need to iterate over the messages (in this case, one message)
    • ack if success
    • nack if error/exception
  • get Acknowledger result

Here is the relevant code place:

if (null === $ack) {
    $ack = new Acknowledger(get_debug_type($this));
    $this->jobs[] = [$message, $ack];
    $this->flush(true);

    return $ack->getResult();
}

The problem now is that nack wasn't handled properly. The $ack->getResult() is always null in case of an error. But what corresponds to a successful command. In my opinion, the following is missing:

if (null === $ack) {
    $ack = new Acknowledger(get_debug_type($this));
    $this->jobs[] = [$message, $ack];
    $this->flush(true);
    
    $error = $ack->getError();
    if ($error) {
        throw $error;
    }

    return $ack->getResult();
}

It is checked if there is an error in the acknowledger, if so, then this is thrown. Otherwise the result is returned (success).

If it's confirmed as a bug or feature, I'm more than happy to do a PR.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions