private void doCancel(@Nullable String message, @Nullable Throwable cause) {
        if (message == null && cause == null) {
            cause = new CancellationException("Cancelled without a message or cause");
            logger.warn("Cancelling without a message or cause is suboptimal", cause);
        }

        if (closed) {
            return;
        }

        Status status = Status.CANCELLED;
        if (message != null) {
            status = status.withDescription(message);
        }
        if (cause != null) {
            status = status.withCause(cause);
        }
        close(status, new Metadata());
        if (cause == null) {
            req.abort();
        } else {
            req.abort(cause);
        }
    }
Encapsulates the state of a single client call, writing messages from the client and reading responses
from the server, passing to business logic via {@link ClientCall.Listener}.
grpc/src/main/java/com/linecorp/armeria/internal/client/grpc/ArmeriaClientCall.java