protected function doOnce(string $queueName, Envelope $envelope) : array
    {
        $result = false;
        $message = $envelope->unwrap();

        $this->getLogger()->debug('Handling message {msg}', ['msg' => self::nameOf($message)]);
        try {
            $result = $this->handleMessage($message);
        } catch (Exception\MustStop $e) {
            $this->driver->ack($queueName, $envelope);
            throw $e;
        } catch (Exception\ShouldReleaseMessage $e) {
            $this->driver->release($queueName, $envelope);
            $this->getLogger()->debug('Releasing message {msg} due to {cls} exception: {err}', [
                'msg' => self::nameOf($message),
                'cls' => get_class($e),
                'err' => $e->getMessage(),
            ]);
            return [$result, true];
        } catch (\Exception $e) {
            // any other exception is simply logged. We and marked as failed
            // below. We only log here because we can't make guarantees about
            // the implementation of the handler and whether or not it actually
            // throws exceptions on failure (see PcntlForkingHandler).
            $this->getLogger()->critical('Unexpected {cls} exception handling {name} message: {msg}', [
                'cls'   => get_class($e),
                'name'  => self::nameOf($message),
                'msg'   => $e->getMessage()
            ]);
            $result = false;
        }
        $this->getLogger()->debug('Handled message {msg}', ['msg' => self::nameOf($message)]);

        if ($result) {
            $willRetry = false;
            $this->driver->ack($queueName, $envelope);
            $this->getLogger()->debug('Acknowledged message {msg}', ['msg' => self::nameOf($message)]);
        } else {
            $willRetry = $this->failed($queueName, $envelope);
            $this->getLogger()->debug('Failed message {msg}', ['msg' => self::nameOf($message)]);
        }

        return [$result, $willRetry];
    }