Table of Contents

Struct BatchWriteCommand<T>

Namespace
DynaSharp
Assembly
DynaSharp.dll

A BatchWriteItem under construction: puts and deletes of any number, also of other types and other tables in the same batch, as in shop.BatchWrite().Put(item).Delete(pk, sk).Put(orders, order). It is not atomic, runs in requests of 25 writes, sends again what DynamoDB left unprocessed, and gives up with a BatchIncompleteException. Chain the writes and end with SendAsync(CancellationToken) in one expression.

public readonly ref struct BatchWriteCommand<T> : IRetryable<BatchWriteCommand<T>> where T : IDynamoDbDocument<T>

Type Parameters

T

The type of the table the batch was started on.

Implements
Inherited Members

Examples

var written = await products.BatchWrite().PutAll(catalog).SendAsync(ct);

Remarks

Not atomic. Each write succeeds or fails on its own, and when the batch ends early the writes before that stay applied. A batch has no conditions and no update either: what needs those is a TransactWriteCommand, and costs twice the capacity.

Requests of 25 writes. DynamoDB takes 25 writes and 16 MB in a request, and an item can have 400 KB. The command cuts the batch into requests that fit, which run one after the other.

Unprocessed writes go out again. That happens after a backoff with jitter on TimeProvider. A retry repeats a put or a delete, which is safe: the item ends up as it was written.

It gives up after 8 requests in a row that get nothing done, or as many as MaxStalledRounds(int) says, with a BatchIncompleteException that holds what was not written. A round that writes something does not count against that. Any other failure after a request went through ends the batch the same way, with the failure as its InnerException, and so does a timeout, a lost connection or a server error of the first request. The writes of a request that got no answer count as not written, though DynamoDB may have applied some of them; sending them again is safe. Any other failure of the first request surfaces as it is, and a cancellation stays an OperationCanceledException, which reports no progress.

A key twice. DynamoDB rejects a request that holds one key twice with a ValidationException, and the command does not look for duplicates: an item can hold its key anywhere, and a write costs no read of it here. So a key that occurs twice in one request fails that request, with the requests before it applied and reported, and one that occurs in two requests is written twice, in order.

Telemetry has one span per request, so a batch can make several, and they carry the tables and the capacity of their own request. See GetCommand<T> for what a command is and what it cannot do.

Methods

Delete(Table<Item>, AttributeValue, AttributeValue)

Adds a delete on another table, one without a schema, by the values of the key. A table of an entity takes a generated key instead.

public BatchWriteCommand<T> Delete(Table<Item> table, AttributeValue partitionKey, AttributeValue sortKey = default)

Parameters

table Table<Item>

The table.

partitionKey AttributeValue

The partition key as it is stored. Strings and binary values must not be empty.

sortKey AttributeValue

The sort key as it is stored, which a table with a sort key needs.

Returns

BatchWriteCommand<T>

The command, which replaces this one.

Exceptions

ArgumentNullException

table is null.

ArgumentException

A key is empty, or the table has no sort key.

DeleteAll<TKey>(IEnumerable<TKey>)

Adds a delete of each generated key, any number of them, which SendAsync(CancellationToken) sends in requests of 25 writes. Deleting what does not exist is no error. The keys are written here and now, so the sequence is enumerated once, before anything is sent. It takes a sequence of a generated key, such as ids.Select(Order.Keys.Of), and an IEnumerable<T> of IKey<TEntity>.

public BatchWriteCommand<T> DeleteAll<TKey>(IEnumerable<TKey> keys) where TKey : IKey<T>

Parameters

keys IEnumerable<TKey>

The keys.

Returns

BatchWriteCommand<T>

The command, which replaces this one.

Type Parameters

TKey

The key. A key of another entity is a compile error.

Exceptions

ArgumentNullException

keys or one of them is null.

Delete<TKey>(TKey)

Adds a delete by a generated key. Deleting what does not exist is no error.

public BatchWriteCommand<T> Delete<TKey>(TKey key) where TKey : IKey<T>

Parameters

key TKey

The key.

Returns

BatchWriteCommand<T>

The command, which replaces this one.

Type Parameters

TKey

The key. A key of another entity is a compile error.

Exceptions

ArgumentNullException

key is null.

Delete<TOther, TKey>(Table<TOther>, TKey)

Adds a delete by a generated key on another table.

public BatchWriteCommand<T> Delete<TOther, TKey>(Table<TOther> table, TKey key) where TOther : IDynamoDbDocument<TOther> where TKey : IKey<TOther>

Parameters

table Table<TOther>

The table.

key TKey

The key.

Returns

BatchWriteCommand<T>

The command, which replaces this one.

Type Parameters

TOther

The type of the table.

TKey

The key. A key of another entity is a compile error.

Exceptions

ArgumentNullException

table or key is null.

IgnoreVersion()

Lets the batch write entities with a VersionAttribute as they are: a batch cannot carry a condition, so without this SendAsync(CancellationToken) throws InvalidOperationException for such an entity.

public BatchWriteCommand<T> IgnoreVersion()

Returns

BatchWriteCommand<T>

The command, which replaces this one.

Remarks

The whole batch. It holds for every write of the batch, wherever in the chain it stands. The version of what the batch writes is not checked, and each item is stored with the version of its entity plus one, as a put stores it, so an entity at 0 is stored at 1.

The version still advances. Every write of a versioned entity stores a new version, also one without the check: an update adds 1 to the stored version, SET #v = if_not_exists(#v, :zero) + :one, so an item without one, or a new item, gets version 1, and a put or a batch stores the version of its entity plus one, as a checked put does. A writer that holds a copy read before this write then fails with ConditionalCheckFailedException, or in a transaction with TransactionCanceledException, instead of overwriting it. What this write itself overwrites is not checked: it wins over whatever another writer stored since, so it suits a change that does not depend on what was read, such as an Add to a counter.

MaxAttempts(int)

Sets the number of attempts of each request including the first, in place of MaxAttempts. It is about one request and says nothing about writes that come back unprocessed, which MaxStalledRounds(int) bounds.

public BatchWriteCommand<T> MaxAttempts(int attempts)

Parameters

attempts int

The number of attempts.

Returns

BatchWriteCommand<T>

The command, which replaces this one.

Exceptions

ArgumentOutOfRangeException

attempts is below 1.

MaxStalledRounds(int)

Sets how many requests in a row may get nothing done before the batch gives up with BatchIncompleteException, in place of 8. A request that writes something starts the count again, so this bounds a batch that is stuck and not a long one. With 1 the batch gives up at the first request that writes nothing, without a wait, which suits a caller that has a backoff of its own.

public BatchWriteCommand<T> MaxStalledRounds(int rounds)

Parameters

rounds int

The number of requests.

Returns

BatchWriteCommand<T>

The command, which replaces this one.

Exceptions

ArgumentOutOfRangeException

rounds is below 1.

Put(T)

Adds a put of a whole item, which replaces everything under its key. The item is written to the request here and now, so changing it afterwards changes nothing.

public BatchWriteCommand<T> Put(T item)

Parameters

item T

The item, which must hold the key attributes.

Returns

BatchWriteCommand<T>

The command, which replaces this one.

Exceptions

ArgumentNullException

item is null.

PutAll(IEnumerable<T>)

Adds a put of each item, any number of them: SendAsync(CancellationToken) splits the batch into DynamoDB requests of 25 writes for you. An item that fails here fails the whole batch and leaves nothing written.

public BatchWriteCommand<T> PutAll(IEnumerable<T> items)

Parameters

items IEnumerable<T>

The items, which must hold the key attributes.

Returns

BatchWriteCommand<T>

The command, which replaces this one.

Remarks

The whole batch is written into memory here and now, so the sequence is enumerated once, and nothing is sent until SendAsync(CancellationToken). The remarks of BatchWriteCommand<T> say how the requests run and what happens to the writes DynamoDB leaves unprocessed.

Exceptions

ArgumentNullException

items or one of them is null.

KeyFormatException

A key template rejects a value of an item. It names the placeholder, not the item.

Put<TOther>(Table<TOther>, TOther)

Adds a put to another table, or of another type on the same table.

public BatchWriteCommand<T> Put<TOther>(Table<TOther> table, TOther item) where TOther : IDynamoDbDocument<TOther>

Parameters

table Table<TOther>

The table.

item TOther

The item, which must hold the key attributes.

Returns

BatchWriteCommand<T>

The command, which replaces this one.

Type Parameters

TOther

The type of the item.

Exceptions

ArgumentNullException

table or item is null.

ReturnCapacity(ReturnConsumedCapacity)

Asks for the consumed capacity, which goes to ConsumedCapacity and the capacity metric.

public BatchWriteCommand<T> ReturnCapacity(ReturnConsumedCapacity detail = ReturnConsumedCapacity.Total)

Parameters

detail ReturnConsumedCapacity

How much detail to return.

Returns

BatchWriteCommand<T>

The command, which replaces this one.

ReturnMetrics()

Asks for the size estimates of the item collections, which go to ItemCollectionMetrics. DynamoDB has them for tables with a local secondary index.

public BatchWriteCommand<T> ReturnMetrics()

Returns

BatchWriteCommand<T>

The command, which replaces this one.

SendAsync(CancellationToken)

Sends the batch, in as many requests as it takes. A batch without writes sends nothing and returns an empty result.

public ValueTask<BatchWriteResult> SendAsync(CancellationToken cancellationToken = default)

Parameters

cancellationToken CancellationToken

Cancels the batch, also while it waits between rounds. What was written before stays written.

Returns

ValueTask<BatchWriteResult>

The result. Await it once.

Exceptions

InvalidOperationException

The command was already sent, extended or rendered, or it writes an entity with a VersionAttribute without IgnoreVersion().

BatchIncompleteException

DynamoDB left writes unprocessed after every round, a table stayed throttled on the last attempt of a request, a request timed out, lost its connection or met a server error on its last attempt, or any other failure came after a request went through. The failure is then its InnerException. The exception holds what was not written.

ObjectDisposedException

The client is disposed.

ValidationException

DynamoDB rejects the first request, for example because it holds a key twice, or an item above 400 KB.

ResourceNotFoundException

A table does not exist, as the first request finds.

DynamoDbException

DynamoDB returns any other error on the first request that repeating cannot fix.

OperationCanceledException

cancellationToken was cancelled. This does not report progress: what went through before stays applied, and nothing says how much that was.

ToRequestJson()

Renders the body of the first request this command would send, as DynamoDB JSON, without sending it. It ends the command, and is meant for tests and debugging. The text contains the items.

public string ToRequestJson()

Returns

string

The request body.

Exceptions

InvalidOperationException

The command was already sent, extended or rendered.