Skip to content

Commit

Permalink
Replace H2 with paragraphs and add section about examples
Browse files Browse the repository at this point in the history
  • Loading branch information
coryan committed Jan 12, 2023
1 parent d72857e commit c94c433
Showing 1 changed file with 41 additions and 20 deletions.
61 changes: 41 additions & 20 deletions google/cloud/doc/error-handling.dox
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@
[input iterators]: https://en.cppreference.com/w/cpp/named_req/InputIterator
[iostream operator<<]: @ref google::cloud::operator<<(std::ostream&,google::cloud::Status const&)

## Overview
@par Overview

In general, the `google-cloud-cpp` libraries return a [StatusOr<T>] if a
function many fail and needs to signal an error. `StatusOr<T>` is an "outcome",
function may fail and needs to signal an error. `StatusOr<T>` is an "outcome",
it contains either the value returned on success, or a description of the
error. Errors are represented by @ref google::cloud::Status, thus the name.
If you are familiar with `std::expected` from C++23, `StatusOr<T>` plays a
Expand All @@ -25,35 +25,35 @@ A `Status` contains more than just the message, in particular, its
[error_info()] member function may return additional information that is useful
during troubleshooting.

## Values with specific error handling
@par Stream Ranges

Some functions return a value that already has a mechanism to signal failures.
For example, some functions return [AsyncStreamingReadWriteRpc<T,U>] (or
technically `std::unique_ptr<AsyncStreamingReadWriteRpc<T,U>>`), and other
functions return classes derived from `std::istream`. In such
cases the library does not wrap the result in a `StatusOr<T>` because the
returned type already has mechanisms to signal errors.
Some functions return [StreamRange<S>], where `S` is a `StatusOr<T>`. These
ranges provide [input iterators] that paginate or stream results from a service,
offering a more idiomatic API. The value type in these iterators is
`StatusOr<T>` because the stream may fail after it has successfully returned
some values. For example, if the request to obtain the next page of results
fails, or if the underlying stream is interrupted by the service.

## Futures
@par Futures

Some functions return a "future" ([future<T>]). This objects represent a value
Some functions return a "future" ([future<T>]). These objects represent a value
that will be obtained asynchronously. By the very nature of asynchronous
operations, the request may fail after the function is called. Therefore, we
have chosen to return `future<StatusOr<T>>`. We think the alternatives are
either incorrect (e.g. `StatusOr<future<T>>` can only handle errors detected
before the function returns), or overly complex
(`StatusOr<future<StatusOr<T>>>`).

## Stream Ranges
@par Values with specific error handling

Similarly, some functions return [StreamRange<S>], where `S` is a `StatusOr<T>`.
These ranges provide [input iterators] that paginate or stream results from a
service, offering a more idiomatic API. The value type in these iterators is
`StatusOr<T>` because the stream may fail after it has successfully returned
some values. For example, if the request to obtain the next page of results
fails, or if the underlying stream is interrupted by the service.
Some functions return a value that already has a mechanism to signal failures.
For example, some functions return [AsyncStreamingReadWriteRpc<T,U>] (or
technically `std::unique_ptr<AsyncStreamingReadWriteRpc<T,U>>`). A small number
of functions return classes derived from `std::istream` or `std::ostream.
In such cases, the library does not wrap the result in a `StatusOr<T>` because
the returned type already has mechanisms to signal errors.

## Example: Using StatusOr<T>
@par Example: Using StatusOr<T>

You can check that a `StatusOr<T>` contains a value by calling the `.ok()`
method, or by using `operator bool()` (like with other smart pointers). If
Expand All @@ -65,7 +65,7 @@ accessing the contained value.

@snippet samples.cc status-or-usage

## Example: Using StatusOr<T> with exceptions
@par Example: Using StatusOr<T> with exceptions

Some applications prefer to throw exceptions on errors. In this case, consider
using [StatusOr<T>::value()]. This function throws a [RuntimeStatusError] if
Expand All @@ -77,6 +77,27 @@ instead of throwing.

@snippet samples.cc status-or-exceptions

@par Error Handling in google-cloud-cpp code samples

The code samples for `google-cloud-cpp` try to emphasize how to use specific
APIs and often have minimal error handling. A typical code sample may simply
throw the status on error, like so:

@code {.cpp}
namespace svc = ::google::cloud::some_service;
[](svc::Client client, std::string const& key) {
auto response = client.SomeRpc(key);
if (!response) throw std::move(response).status();
// ... example continues here ...
}
@endcode

This should not be interpreted as a best practice. If your application is
designed to work with exceptions, then using [StatusOr<T>::value()] is a better
alternative. We just want to show that some error handling is required for these
functions, but at the same time we don't want to obscure the example with a lot
of error handling code.

@see @ref google::cloud::StatusOr
@see @ref google::cloud::Status the class used to describe errors.
@see @ref google::cloud::future for more details on the type returned
Expand Down

0 comments on commit c94c433

Please sign in to comment.