API Design
Concurrency
All functions of the driver are strictly synchronous. They operate and only return a value (or error) when they’re done.
If you want to run operations concurrently, use a go routine. All objects in the driver are designed to be used from multiple concurrent go routines, except Cursor
.
All database objects (except Cursor
) are considered static. After their creation, they won’t change. E.g., after creating a Collection instance, you can remove the collection, but the (Go) instance will still be there. Calling functions on such a removed collection will, of course, fail.
Structured error handling & wrapping
All functions of the driver that can fail return an error value. If that value is not nil, the function call is considered to be failed. In that case, all other return values are set to their zero
values.
All errors are structured using error-checking functions named Is<SomeErrorCategory>
. E.g. IsNotFound(error)
return true if the given error is of the category “not found”. There can be multiple internal error codes that all map onto the same category.
All errors returned from any function of the driver (either internal or exposed) wrap errors using the WithStack
function. This can be used to provide detailed stack traces in case of an error. All error-checking functions use the Cause
function to get the cause of an error instead of the error wrapper.
Note that WithStack
and Cause
are actually variables that you can implement it using your own error wrapper library.
If you, for example, use github.com/pkg/errors, you want to initialize to go driver like this:
import (
driver "github.com/arangodb/go-driver"
"github.com/pkg/errors"
)
func init() {
driver.WithStack = errors.WithStack
driver.Cause = errors.Cause
}
Context-aware
All functions of the driver that involve some kind of long-running operation or support additional options are not given as function arguments have a context.Context argument. This enables you to cancel running requests, pass timeouts/deadlines, and pass additional options.
In all methods that take a context.Context
argument you can pass nil
as value. This is equivalent to passing context.Background()
.
Many functions support one or more optional (and infrequently used) additional options. These can be used with a With <OptionName>
function. e.g., to force a create document call to wait until the data is synchronized to disk, use a prepared context like this:
ctx := driver.WithWaitForSync(parentContext)
collection.CreateDocument(ctx, yourDocument)