Class DynamoDbClient
- Namespace
- DynaSharp
- Assembly
- DynaSharp.dll
The client for Amazon DynamoDB: it owns the resolved configuration, the credentials and the HTTP connections that every request of the library runs on. The way in is Table<T>() for an entity that declares its table, Table<T>(string) to name it, and Table(string, string, string?) for a table without a model.
public sealed class DynamoDbClient : IDisposable
- Inheritance
-
DynamoDbClient
- Implements
- Inherited Members
- Extension Methods
Remarks
A table is the primary API: client.Table("Shop", "pk", "sk") gives a Table<T>, whose methods are the DynamoDB
operations on items. The request API, with one method per DynamoDB operation that takes and returns the request and response records, is in the
DynaSharp.Requests namespace: add using DynaSharp.Requests; and see DynamoDbRequests, which also
describes how errors, retries and telemetry behave.
Create one client per application (or per region and credentials) and keep it for the lifetime of the process: it holds the HTTP connections. Instances are thread-safe, and every operation can run concurrently with others.
The client is configured through DynamoDbClientOptions. Whatever the options leave unset is read from the
environment the way the AWS SDKs do (AWS_REGION, AWS_ENDPOINT_URL_DYNAMODB, AWS_ACCESS_KEY_ID and so on).
Configuration problems surface when the client is created, not on the first request. Requests are signed with AWS Signature
Version 4.
Dispose the client to release its connections. A client created with an HttpHandler does not dispose that handler.
Constructors
DynamoDbClient()
Initializes a new instance of the DynamoDbClient class that takes all settings from the environment:
the region from AWS_REGION (or AWS_DEFAULT_REGION, or the selected profile in the shared AWS config file),
the endpoint from AWS_ENDPOINT_URL_DYNAMODB (or AWS_ENDPOINT_URL, otherwise the public endpoint of the region)
and the credentials from the default chain of the AWS SDKs, see DefaultCredentialsProvider.
public DynamoDbClient()
Exceptions
- InvalidOperationException
No region is configured, or a region or endpoint environment variable is invalid.
DynamoDbClient(DynamoDbClientOptions)
Initializes a new instance of the DynamoDbClient class.
public DynamoDbClient(DynamoDbClientOptions options)
Parameters
optionsDynamoDbClientOptionsThe settings. Options that are not set fall back to the environment, see DynamoDbClientOptions. The client reads the options once; changing the options object later has no effect.
Remarks
Credentials are not looked up here, but with the first request. A client without credentials is created successfully and fails its first request with a CredentialsUnavailableException. When Credentials is not set, the client uses a DefaultCredentialsProvider: environment variables, then a web identity token file (IRSA on EKS), then the shared AWS files, then the container credentials endpoint (ECS, EKS Pod Identity), then the instance metadata service (EC2). It logs the source it chose and failed refreshes to LoggerFactory. The only file read when the client is created is the shared AWS config file, and only when no region is set in the options or the environment.
Exceptions
- ArgumentNullException
optionsor its TimeProvider is null.- ArgumentOutOfRangeException
AttemptTimeout is neither positive nor InfiniteTimeSpan, or exceeds about 49.7 days; or MaxAttempts is below 1.
- ArgumentException
ServiceUrl is not an absolute http or https URL without user info, path, query and fragment.
- InvalidOperationException
No region is configured, or a region or endpoint environment variable is invalid.
Properties
Options
Gets the options as the client resolved them when it was created: the region, the endpoint and the credentials provider it really uses, also those that came from the environment.
public DynamoDbClientOptions Options { get; }
Property Value
Remarks
Resolved once. A region from the environment or a profile and an endpoint from AWS_ENDPOINT_URL are here and not null, and
Credentials is the provider in use, also the default chain that the client made itself. Nothing is read again, so the environment of today can say something else.
A second client. It is new DynamoDbClient(client.Options with { MaxAttempts = 1 }). It shares the provider and with it the cached credentials, and a handler the first client was given. A handler the first
client made stays its own, so HttpHandler is null there and the second client makes one too, and each outlives the other.
The endpoint of the service stays out. ServiceUrl holds an endpoint that came from the options or from AWS_ENDPOINT_URL, which a copy keeps. The public endpoint that the client derived from its region, and one
from AWS_ENDPOINT_URL_DYNAMODB (or AWS_ENDPOINT_URL_DYNAMODB_STREAMS for a streams client), are in use and still stay null here, on purpose: they belong to the service and the region
of this client, not to a copy. So client.Options with { Region = other } goes to the endpoint of the new region, and new DynamoDbStreamsClient(client.Options) gets its own endpoint, also when
AWS_ENDPOINT_URL_DYNAMODB is set.
The options hold a provider and not credentials, and ToString() prints only its type.
Methods
DescribeTableAsync(string, CancellationToken)
Reads the definition and state of a table by its name (DescribeTable): status, key schema, indexes and approximate counts, which DynamoDB updates about every six hours.
public Task<DescribeTableResponse> DescribeTableAsync(string tableName, CancellationToken cancellationToken = default)
Parameters
tableNamestringThe table name, or its ARN.
cancellationTokenCancellationTokenCancels the request.
Returns
- Task<DescribeTableResponse>
The response. Table holds the description, and is null only if the response omits it.
Remarks
It is DescribeTableAsync(DynamoDbClient, DescribeTableRequest, CancellationToken) without a request to build and without using DynaSharp.Requests;, and it returns
what that returns. A Table<T> at hand has DescribeTableAsync(CancellationToken).
The result is eventually consistent: right after creating a table it may still be reported as missing, which WaitUntilActiveAsync(CancellationToken) bears with.
Exceptions
- ArgumentException
tableNameis null or empty.- ObjectDisposedException
The client is disposed.
- ResourceNotFoundException
The table does not exist.
- ValidationException
DynamoDB rejects the request, for example because the table name is malformed.
- AccessDeniedException
The credentials lack permission for
dynamodb:DescribeTableon the table.- DynamoDbException
DynamoDB returns any other error, or a response that is not a DynamoDB response. A throttling or server error surfaces only when the last attempt failed with it too.
- CredentialsUnavailableException
No credentials can be found.
- HttpRequestException
The request could not be sent or the response could not be read, on every attempt.
- TimeoutException
The last attempt did not complete within AttemptTimeout.
- OperationCanceledException
cancellationTokenwas cancelled.
Dispose()
Releases the HTTP connections. Requests still running may fail. Calling it again has no effect.
public void Dispose()
Remarks
The handler given in HttpHandler is not disposed; its owner does that.
SendRawAsync(string, ReadOnlyMemory<byte>, CancellationToken)
Sends a DynamoDB operation by name, with a request body that you write as JSON, and returns the response body as JSON. It is for
the operations and parameters that DynaSharp does not model: an operation without a request type, such as
DescribeLimits or DescribeEndpoints, or a parameter that a modeled operation does not have yet.
public Task<byte[]> SendRawAsync(string operation, ReadOnlyMemory<byte> requestJson, CancellationToken cancellationToken = default)
Parameters
operationstringThe operation name as DynamoDB knows it, for example
DescribeLimits. It consists of ASCII letters and digits; it is sent as theX-Amz-Targetheader and is the operation of the span and the metrics of the call.requestJsonReadOnlyMemory<byte>The request body as UTF-8 bytes, such as
"""{}"""u8.ToArray(): a JSON object in the format of the DynamoDB API (AWS JSON 1.0), with attribute values in their typed form, for example{"TableName":"Users","Key":{"pk":{"S":"user-1"}}}, or{}for an operation without parameters. The bytes are copied; they are not read or checked, so DynamoDB reports a request it cannot parse. The memory can be reused as soon as the returned task has completed.cancellationTokenCancellationTokenCancels the request.
Returns
- Task<byte[]>
The body of the response as UTF-8 JSON, exactly as DynamoDB sent it. It is not parsed, so a success response that is not JSON is returned too.
Remarks
The call runs through the same pipeline as the operations of DynaSharp.Requests: it is signed, sent to the endpoint of
the client, repeated as MaxAttempts says, bounded by
AttemptTimeout, and an error response surfaces as the same DynamoDbException
types, which name the operation. The retries send the same bytes again. As for every call, a retry can apply a write
twice when the first attempt reached DynamoDB and its response was lost: guard such requests with a condition or an idempotency
token of the operation, or set MaxAttempts to 1.
Telemetry is that of the other calls, minus what the library cannot read from JSON it does not parse: the span is
named DynamoDB.<operation> and the duration, retry and throttle measurements carry the operation, but there is no
table tag and no consumed capacity. The request and the response never appear in telemetry or logs.
Exceptions
- ArgumentNullException
operationis null.- ArgumentException
operationis empty or contains a character other than an ASCII letter or digit.- ObjectDisposedException
The client is disposed.
- ValidationException
DynamoDB rejects the request, for example because it is not valid JSON or has a parameter the operation does not know.
- AccessDeniedException
The credentials lack permission for the operation.
- DynamoDbException
DynamoDB returns any other error, an operation it does not know, or a response that is not a DynamoDB response. A throttling or server error surfaces only when the last attempt failed with it too.
- CredentialsUnavailableException
No credentials can be found.
- HttpRequestException
The request could not be sent or the response could not be read, on every attempt.
- TimeoutException
The last attempt did not complete within AttemptTimeout.
- OperationCanceledException
cancellationTokenwas cancelled.
Table(string, string, string?)
Opens a table without a schema, which reads and writes Item. It makes no request, so a table that does not exist shows up with the first command. Hold the result in a field: it is immutable and thread-safe.
public Table<Item> Table(string name, string partitionKey, string? sortKey = null)
Parameters
namestringThe table name, or its ARN.
partitionKeystringThe attribute name of the partition key.
sortKeystringThe attribute name of the sort key, or null if the table has none.
Returns
Exceptions
- ArgumentException
nameorpartitionKeyis null or empty, orsortKeyis empty.
Table<T>()
Opens the table an entity declares, through Table or Table, as TableNaming names it. It makes no request, so a table that does not exist shows up with the first command.
public Table<T> Table<T>() where T : IDynamoDbEntity<T>
Returns
- Table<T>
The table.
Type Parameters
TThe entity, which declares its table.
Examples
// Order declares [DynamoDbEntity(Table = "Shop")], or the assembly [assembly: DynamoDbDefaults(Table = "Shop")].
using var client = new DynamoDbClient(new DynamoDbClientOptions { TableNaming = name => $"dev-{name}" });
var orders = client.Table<Order>(); // "dev-Shop"
var scratch = client.Table<Order>("test-1"); // "test-1", as given
Remarks
Declared, then named. The declaration of the entity wins over the default of its assembly, and TableNaming, if set, turns the result into the name
the client opens, such as dev-orders for orders. Table<T>(string) skips both and opens the name it is given.
Hold the result. The table is immutable and thread-safe, so a field or a singleton keeps it. Every call runs TableNaming again.
No declaration. An entity of the compilation that declares no table is DYNA238 at the call, and an entity from elsewhere throws here.
Exceptions
- InvalidOperationException
Tdeclares no table, or TableNaming returned null or an empty name.
Table<T>(string)
Opens a table as an entity type sees it: key names, indexes and discriminator come from the entity. It makes no request, so a table that does not exist shows up with the first command. Hold the result in a field: it is immutable and thread-safe.
public Table<T> Table<T>(string name) where T : IDynamoDbEntity<T>
Parameters
namestringThe table name, or its ARN.
Returns
- Table<T>
The table.
Type Parameters
TThe entity. A nested document has no key, so it does not fit here, which the constraint enforces, and neither does Item: a table without a schema is opened with Table(string, string, string?).
Exceptions
- ArgumentException
nameis null or empty.
TransactGet()
Starts a transaction of reads (TransactGetItems): up to 100 gets on any tables, which see one snapshot. See TransactGetCommand.
public TransactGetCommand TransactGet()
Returns
- TransactGetCommand
The command.
TransactWrite()
Starts a transaction of writes (TransactWriteItems): up to 100 puts, updates, deletes and condition checks on any tables, which take effect
together or not at all. See TransactWriteCommand.
public TransactWriteCommand TransactWrite()
Returns
- TransactWriteCommand
The command, which needs an action before it can be sent.