Skip to content

Commit 60161fa

Browse files
authored
Remove requirement that payload types are Sendable. (#59)
* Remove requirement that payload types are Sendable. * Refactor InMemoryDynamoDBCompositePrimaryKeyTable into several extensions.
1 parent 5eef5d9 commit 60161fa

File tree

40 files changed

+1743
-1563
lines changed

40 files changed

+1743
-1563
lines changed

README.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ An item can be retrieved from the DynamoDB table using the following-
120120
let retrievedItem: StandardTypedDatabaseItem<PayloadType>? = try await table.getItem(forKey: key)
121121
```
122122

123-
The `getItem` operation return an optional `TypedDatabaseItem` which will be nil if the item doesn't exist in the table. These operations will also fail if the *RowType* recorded in the database row doesn't match the type being requested.
123+
The `getItem` operation return an optional `TypedTTLDatabaseItem` which will be nil if the item doesn't exist in the table. These operations will also fail if the *RowType* recorded in the database row doesn't match the type being requested.
124124

125125
## Update
126126

@@ -623,7 +623,7 @@ By default, this operation will fail if an item with the same partition key and
623623
The main entities provided by this package are
624624
* *CompositePrimaryKey*: a struct that stores the partition and sort values for a composite primary key.
625625
* *TimeToLive*: a struct that stores TTL timestamp for a database item.
626-
* *TypedDatabaseItemWithTimeToLive*: a struct that manages decoding and encoding rows of a particular type along with any TTL settings from polymorphic database tables.
626+
* *TypedTTLDatabaseItem*: a struct that manages decoding and encoding rows of a particular type along with any TTL settings from polymorphic database tables.
627627
* *TypedDatabaseItem*: a typealias that points to `TypedDatabaseItemWithTimeToLive` with default `StandardTimeToLiveAttributes` generic type for backwards compatibility.
628628
* *PolymorphicDatabaseItem*: a struct that manages decoding rows that are one out of a number of types from polymorphic database tables.
629629
* *DynamoDBCompositePrimaryKeyTable*: a protocol for interacting with a DynamoDB database table.
@@ -647,15 +647,15 @@ The TimeToLive struct defines the TTL timestamp value for a row in the database.
647647
let timeToLive = StandardTimeToLive(timeToLiveTimestamp: 123456789)
648648
```
649649

650-
## TypedDatabaseItemWithTimeToLive
650+
## TypedTTLDatabaseItem
651651

652-
The TypedDatabaseItemWithTimeToLive struct manages a number of attributes in the database table to enable decoding and encoding rows to and from the correct type. In addition it also manages other conveniences such as versioning. The attributes this struct will add to a database row are-
652+
The TypedTTLDatabaseItem struct manages a number of attributes in the database table to enable decoding and encoding rows to and from the correct type. In addition it also manages other conveniences such as versioning. The attributes this struct will add to a database row are-
653653
* *CreateDate*: The timestamp when the row was created.
654654
* *RowType*: Specifies the schema used by the other attributes of this row.
655655
* *RowVersion*: A version number for the values currently in this row. Used to enable optimistic locking.
656656
* *LastUpdatedDate*: The timestamp when the row was last updated.
657657

658-
Similar to CompositePrimaryKey, this package provides a typealias called `StandardTypedDatabaseItem` that expects the standard partition, sort key, and TTL attribute names.
658+
Similar to CompositePrimaryKey, this package provides a typealias called `TypedDatabaseItem` that expects the standard partition, sort key, and TTL attribute names.
659659

660660
This struct can be instantiated as shown-
661661

@@ -683,7 +683,7 @@ or with TTL-
683683
let updatedDatabaseItem = newDatabaseItem.createUpdatedItem(withValue: updatedValue, andTimeToLive: updatedTimeToLive)
684684
```
685685

686-
This function will create a new instance of TypedDatabaseItemWithTimeToLive with the same key and updated LastUpdatedDate and RowVersion values. By default, performing a **PutItem** operation with this item on a table where this row already exists and the RowVersion isn't equal to the value of the original row will fail.
686+
This function will create a new instance of TypedTTLDatabaseItem with the same key and updated LastUpdatedDate and RowVersion values. By default, performing a **PutItem** operation with this item on a table where this row already exists and the RowVersion isn't equal to the value of the original row will fail.
687687

688688
## DynamoDBCompositePrimaryKeyTable
689689

@@ -703,7 +703,7 @@ Internally `AWSDynamoDBCompositePrimaryKeyTable` uses a custom Decoder and Encod
703703

704704
## PrimaryKeyAttributes
705705

706-
`CompositePrimaryKey`, `TypedDatabaseItemWithTimeToLive` and `PolymorphicDatabaseItem` are all generic to a type conforming to the `PrimaryKeyAttributes` protocol. This protocol can be used to use custom attribute names for the partition and sort keys.
706+
`CompositePrimaryKey`, `TypedTTLDatabaseItem` and `PolymorphicDatabaseItem` are all generic to a type conforming to the `PrimaryKeyAttributes` protocol. This protocol can be used to use custom attribute names for the partition and sort keys.
707707

708708
```swift
709709
public struct MyPrimaryKeyAttributes: PrimaryKeyAttributes {
@@ -718,7 +718,7 @@ public struct MyPrimaryKeyAttributes: PrimaryKeyAttributes {
718718

719719
## TimeToLiveAttributes
720720

721-
`TimeToLive`, `TypedDatabaseItemWithTimeToLive` and `PolymorphicDatabaseItem` are all generic to a type conforming to the `TimeToLiveAttributes` protocol. This protocol can be used to use custom attribute names for the TTL timestamp.
721+
`TimeToLive`, `TypedTTLDatabaseItem` and `PolymorphicDatabaseItem` are all generic to a type conforming to the `TimeToLiveAttributes` protocol. This protocol can be used to use custom attribute names for the TTL timestamp.
722722

723723
```swift
724724
public struct MyTimeToLiveAttributes: TimeToLiveAttributes {

Sources/DynamoDBTables/AWSDynamoDBCompositePrimaryKeyTable+DynamoDBTableAsync.swift

Lines changed: 26 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,13 @@ import Logging
3030

3131
/// DynamoDBTable conformance async functions
3232
public extension AWSDynamoDBCompositePrimaryKeyTable {
33-
func insertItem(_ item: TypedDatabaseItem<some Any, some Any>) async throws {
33+
func insertItem(_ item: TypedTTLDatabaseItem<some Any, some Any, some Any>) async throws {
3434
let putItemInput = try getInputForInsert(item)
3535

3636
try await putItem(forInput: putItemInput, withKey: item.compositePrimaryKey)
3737
}
3838

39-
func clobberItem(_ item: TypedDatabaseItem<some Any, some Any>) async throws {
39+
func clobberItem(_ item: TypedTTLDatabaseItem<some Any, some Any, some Any>) async throws {
4040
let attributes = try getAttributes(forItem: item)
4141

4242
let putItemInput = AWSDynamoDB.PutItemInput(item: attributes,
@@ -45,16 +45,17 @@ public extension AWSDynamoDBCompositePrimaryKeyTable {
4545
try await self.putItem(forInput: putItemInput, withKey: item.compositePrimaryKey)
4646
}
4747

48-
func updateItem<AttributesType, ItemType>(newItem: TypedDatabaseItem<AttributesType, ItemType>,
49-
existingItem: TypedDatabaseItem<AttributesType, ItemType>) async throws
48+
func updateItem<AttributesType, ItemType, TimeToLiveAttributesType>(
49+
newItem: TypedTTLDatabaseItem<AttributesType, ItemType, TimeToLiveAttributesType>,
50+
existingItem: TypedTTLDatabaseItem<AttributesType, ItemType, TimeToLiveAttributesType>) async throws
5051
{
5152
let putItemInput = try getInputForUpdateItem(newItem: newItem, existingItem: existingItem)
5253

5354
try await putItem(forInput: putItemInput, withKey: newItem.compositePrimaryKey)
5455
}
5556

56-
func getItem<AttributesType, ItemType>(forKey key: CompositePrimaryKey<AttributesType>) async throws
57-
-> TypedDatabaseItem<AttributesType, ItemType>?
57+
func getItem<AttributesType, ItemType, TimeToLiveAttributesType>(forKey key: CompositePrimaryKey<AttributesType>) async throws
58+
-> TypedTTLDatabaseItem<AttributesType, ItemType, TimeToLiveAttributesType>?
5859
{
5960
let getItemInput = try getInputForGetItem(forKey: key)
6061

@@ -66,7 +67,7 @@ public extension AWSDynamoDBCompositePrimaryKeyTable {
6667
self.logger.trace("Value returned from DynamoDB.")
6768

6869
do {
69-
let decodedItem: TypedDatabaseItem<AttributesType, ItemType>? =
70+
let decodedItem: TypedTTLDatabaseItem<AttributesType, ItemType, TimeToLiveAttributesType>? =
7071
try DynamoDBDecoder().decode(DynamoDBClientTypes.AttributeValue.m(item))
7172
return decodedItem
7273
} catch {
@@ -86,7 +87,7 @@ public extension AWSDynamoDBCompositePrimaryKeyTable {
8687
_ = try await self.dynamodb.deleteItem(input: deleteItemInput)
8788
}
8889

89-
func deleteItem(existingItem: TypedDatabaseItem<some Any, some Any>) async throws {
90+
func deleteItem(existingItem: TypedTTLDatabaseItem<some Any, some Any, some Any>) async throws {
9091
let deleteItemInput = try getInputForDeleteItem(existingItem: existingItem)
9192

9293
let logMessage = "dynamodb.deleteItem with key: \(existingItem.compositePrimaryKey), "
@@ -230,10 +231,10 @@ public extension AWSDynamoDBCompositePrimaryKeyTable {
230231
}
231232
}
232233

233-
func query<AttributesType, ItemType>(forPartitionKey partitionKey: String,
234-
sortKeyCondition: AttributeCondition?,
235-
consistentRead: Bool) async throws
236-
-> [TypedDatabaseItem<AttributesType, ItemType>]
234+
func query<AttributesType, ItemType, TimeToLiveAttributesType>(forPartitionKey partitionKey: String,
235+
sortKeyCondition: AttributeCondition?,
236+
consistentRead: Bool) async throws
237+
-> [TypedTTLDatabaseItem<AttributesType, ItemType, TimeToLiveAttributesType>]
237238
{
238239
try await self.partialQuery(forPartitionKey: partitionKey,
239240
sortKeyCondition: sortKeyCondition,
@@ -242,13 +243,13 @@ public extension AWSDynamoDBCompositePrimaryKeyTable {
242243
}
243244

244245
// function to return a future with the results of a query call and all future paginated calls
245-
private func partialQuery<AttributesType, ItemType>(
246+
private func partialQuery<AttributesType, ItemType, TimeToLiveAttributesType>(
246247
forPartitionKey partitionKey: String,
247248
sortKeyCondition: AttributeCondition?,
248-
exclusiveStartKey: String?,
249-
consistentRead: Bool) async throws -> [TypedDatabaseItem<AttributesType, ItemType>]
249+
exclusiveStartKey _: String?,
250+
consistentRead: Bool) async throws -> [TypedTTLDatabaseItem<AttributesType, ItemType, TimeToLiveAttributesType>]
250251
{
251-
let paginatedItems: ([TypedDatabaseItem<AttributesType, ItemType>], String?) =
252+
let paginatedItems: ([TypedTTLDatabaseItem<AttributesType, ItemType, TimeToLiveAttributesType>], String?) =
252253
try await query(forPartitionKey: partitionKey,
253254
sortKeyCondition: sortKeyCondition,
254255
limit: nil,
@@ -259,7 +260,7 @@ public extension AWSDynamoDBCompositePrimaryKeyTable {
259260
// if there are more items
260261
if let lastEvaluatedKey = paginatedItems.1 {
261262
// returns a future with all the results from all later paginated calls
262-
let partialResult: [TypedDatabaseItem<AttributesType, ItemType>] = try await self.partialQuery(
263+
let partialResult: [TypedTTLDatabaseItem<AttributesType, ItemType, TimeToLiveAttributesType>] = try await self.partialQuery(
263264
forPartitionKey: partitionKey,
264265
sortKeyCondition: sortKeyCondition,
265266
exclusiveStartKey: lastEvaluatedKey,
@@ -273,13 +274,13 @@ public extension AWSDynamoDBCompositePrimaryKeyTable {
273274
}
274275
}
275276

276-
func query<AttributesType, ItemType>(forPartitionKey partitionKey: String,
277-
sortKeyCondition: AttributeCondition?,
278-
limit: Int?,
279-
scanIndexForward: Bool,
280-
exclusiveStartKey: String?,
281-
consistentRead: Bool) async throws
282-
-> (items: [TypedDatabaseItem<AttributesType, ItemType>], lastEvaluatedKey: String?)
277+
func query<AttributesType, ItemType, TimeToLiveAttributesType>(forPartitionKey partitionKey: String,
278+
sortKeyCondition: AttributeCondition?,
279+
limit: Int?,
280+
scanIndexForward: Bool,
281+
exclusiveStartKey: String?,
282+
consistentRead: Bool) async throws
283+
-> (items: [TypedTTLDatabaseItem<AttributesType, ItemType, TimeToLiveAttributesType>], lastEvaluatedKey: String?)
283284
{
284285
let queryInput = try AWSDynamoDB.QueryInput.forSortKeyCondition(
285286
partitionKey: partitionKey, targetTableName: targetTableName,
@@ -310,7 +311,7 @@ public extension AWSDynamoDBCompositePrimaryKeyTable {
310311
}
311312

312313
if let outputAttributeValues = queryOutput.items {
313-
let items: [TypedDatabaseItem<AttributesType, ItemType>]
314+
let items: [TypedTTLDatabaseItem<AttributesType, ItemType, TimeToLiveAttributesType>]
314315

315316
do {
316317
items = try outputAttributeValues.map { values in

Sources/DynamoDBTables/AWSDynamoDBCompositePrimaryKeyTable+deleteItems.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ public extension AWSDynamoDBCompositePrimaryKeyTable {
5252
try throwOnBatchExecuteStatementErrors(response: response)
5353
}
5454

55-
private func deleteChunkedItems(_ existingItems: [some DatabaseItem]) async throws {
55+
private func deleteChunkedItems(_ existingItems: [TypedTTLDatabaseItem<some Any, some Any, some Any>]) async throws {
5656
// if there are no items, there is nothing to update
5757
guard existingItems.count > 0 else {
5858
return
@@ -80,7 +80,7 @@ public extension AWSDynamoDBCompositePrimaryKeyTable {
8080
}
8181
}
8282

83-
func deleteItems(existingItems: [some DatabaseItem]) async throws {
83+
func deleteItems(existingItems: [TypedTTLDatabaseItem<some Any, some Any, some Any>]) async throws {
8484
// BatchExecuteStatement has a maximum of 25 statements
8585
// This function handles pagination internally.
8686
let chunkedItems = existingItems.chunked(by: maximumUpdatesPerExecuteStatement)

Sources/DynamoDBTables/AWSDynamoDBCompositePrimaryKeyTable+execute.swift

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -128,11 +128,11 @@ public extension AWSDynamoDBCompositePrimaryKeyTable {
128128
return itemLists.flatMap { $0 }
129129
}
130130

131-
func execute<AttributesType, ItemType>(
131+
func execute<AttributesType, ItemType, TimeToLiveAttributesType>(
132132
partitionKeys: [String],
133133
attributesFilter: [String]?,
134134
additionalWhereClause: String?, nextToken: String?) async throws
135-
-> (items: [TypedDatabaseItem<AttributesType, ItemType>], lastEvaluatedKey: String?)
135+
-> (items: [TypedTTLDatabaseItem<AttributesType, ItemType, TimeToLiveAttributesType>], lastEvaluatedKey: String?)
136136
{
137137
// if there are no partitions, there will be no results to return
138138
// succeed immediately with empty results
@@ -158,7 +158,7 @@ public extension AWSDynamoDBCompositePrimaryKeyTable {
158158
let nextToken = executeOutput.nextToken
159159

160160
if let outputAttributeValues = executeOutput.items {
161-
let items: [TypedDatabaseItem<AttributesType, ItemType>]
161+
let items: [TypedTTLDatabaseItem<AttributesType, ItemType, TimeToLiveAttributesType>]
162162

163163
do {
164164
items = try outputAttributeValues.map { values in
@@ -176,16 +176,17 @@ public extension AWSDynamoDBCompositePrimaryKeyTable {
176176
}
177177
}
178178

179-
func execute<AttributesType, ItemType>(
179+
func execute<AttributesType, ItemType, TimeToLiveAttributesType>(
180180
partitionKeys: [String],
181181
attributesFilter: [String]?,
182182
additionalWhereClause: String?) async throws
183-
-> [TypedDatabaseItem<AttributesType, ItemType>]
183+
-> [TypedTTLDatabaseItem<AttributesType, ItemType, TimeToLiveAttributesType>]
184184
{
185185
// ExecuteStatement API has a maximum limit on the number of decomposed read operations per request.
186186
// This function handles pagination internally.
187187
let chunkedPartitionKeys = partitionKeys.chunked(by: maximumKeysPerExecuteStatement)
188-
let itemLists = try await chunkedPartitionKeys.concurrentMap { chunk -> [TypedDatabaseItem<AttributesType, ItemType>] in
188+
let itemLists = try await chunkedPartitionKeys.concurrentMap { chunk
189+
-> [TypedTTLDatabaseItem<AttributesType, ItemType, TimeToLiveAttributesType>] in
189190
try await self.partialExecute(partitionKeys: chunk,
190191
attributesFilter: attributesFilter,
191192
additionalWhereClause: additionalWhereClause,
@@ -225,14 +226,14 @@ public extension AWSDynamoDBCompositePrimaryKeyTable {
225226
}
226227
}
227228

228-
private func partialExecute<AttributesType, ItemType>(
229+
private func partialExecute<AttributesType, ItemType, TimeToLiveAttributesType>(
229230
partitionKeys: [String],
230231
attributesFilter: [String]?,
231232
additionalWhereClause: String?,
232233
nextToken: String?) async throws
233-
-> [TypedDatabaseItem<AttributesType, ItemType>]
234+
-> [TypedTTLDatabaseItem<AttributesType, ItemType, TimeToLiveAttributesType>]
234235
{
235-
let paginatedItems: ([TypedDatabaseItem<AttributesType, ItemType>], String?) =
236+
let paginatedItems: ([TypedTTLDatabaseItem<AttributesType, ItemType, TimeToLiveAttributesType>], String?) =
236237
try await execute(partitionKeys: partitionKeys,
237238
attributesFilter: attributesFilter,
238239
additionalWhereClause: additionalWhereClause,
@@ -241,7 +242,7 @@ public extension AWSDynamoDBCompositePrimaryKeyTable {
241242
// if there are more items
242243
if let returnedNextToken = paginatedItems.1 {
243244
// returns a future with all the results from all later paginated calls
244-
let partialResult: [TypedDatabaseItem<AttributesType, ItemType>] = try await self.partialExecute(
245+
let partialResult: [TypedTTLDatabaseItem<AttributesType, ItemType, TimeToLiveAttributesType>] = try await self.partialExecute(
245246
partitionKeys: partitionKeys,
246247
attributesFilter: attributesFilter,
247248
additionalWhereClause: additionalWhereClause,

0 commit comments

Comments
 (0)