Skip to content

Commit d86787e

Browse files
authored
Remove Sendable conformance from entry types (#44)
Remove Sendable conformance from PolymorphicWriteEntry and PolymorphicTransactionConstraintEntry
1 parent 416a7e8 commit d86787e

16 files changed

+125
-157
lines changed

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,7 @@ and similarly for polymorphic queries, most conveniently by using the `@Polymorp
370370
typealias TestTypeBWriteEntry = StandardWriteEntry<TestTypeB>
371371

372372
@PolymorphicWriteEntry
373-
enum TestPolymorphicWriteEntry: Sendable {
373+
enum TestPolymorphicWriteEntry {
374374
case testTypeA(TestTypeAWriteEntry)
375375
case testTypeB(TestTypeBWriteEntry)
376376
}
@@ -407,7 +407,7 @@ typealias TestTypeAStandardTransactionConstraintEntry = StandardTransactionConst
407407
typealias TestTypeBStandardTransactionConstraintEntry = StandardTransactionConstraintEntry<TestTypeB>
408408

409409
@PolymorphicTransactionConstraintEntry
410-
enum TestPolymorphicTransactionConstraintEntry: Sendable {
410+
enum TestPolymorphicTransactionConstraintEntry {
411411
case testTypeA(TestTypeAStandardTransactionConstraintEntry)
412412
case testTypeB(TestTypeBStandardTransactionConstraintEntry)
413413
}
@@ -428,7 +428,7 @@ about failed transactions. This is enabled by default when using the `@Polymorph
428428

429429
```swift
430430
@PolymorphicWriteEntry(passCompositePrimaryKey: false)
431-
enum TestPolymorphicWriteEntry: Sendable {
431+
enum TestPolymorphicWriteEntry {
432432
case testTypeA(TestTypeAWriteEntry)
433433
case testTypeB(TestTypeBWriteEntry)
434434
}

Sources/DynamoDBTables/AWSDynamoDBCompositePrimaryKeyTable+updateItems.swift

Lines changed: 33 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -175,12 +175,12 @@ public extension AWSDynamoDBCompositePrimaryKeyTable {
175175
_ = try await dynamodb.executeTransaction(input: transactionInput)
176176
}
177177

178-
private func writeTransactionItems(
179-
_ entries: [some PolymorphicWriteEntry], constraints: [some PolymorphicTransactionConstraintEntry]) async throws
178+
private func getExecuteTransactionInput(
179+
_ entries: [some PolymorphicWriteEntry], constraints: [some PolymorphicTransactionConstraintEntry]) throws -> ExecuteTransactionInput?
180180
{
181181
// if there are no items, there is nothing to update
182182
guard entries.count > 0 else {
183-
return
183+
return nil
184184
}
185185

186186
let context = StandardPolymorphicWriteEntryContext<AWSDynamoDBPolymorphicWriteEntryTransform,
@@ -199,9 +199,7 @@ public extension AWSDynamoDBCompositePrimaryKeyTable {
199199
return DynamoDBClientTypes.ParameterizedStatement(statement: statement)
200200
}
201201

202-
let transactionInput = ExecuteTransactionInput(transactStatements: entryStatements + requiredItemsStatements)
203-
204-
_ = try await dynamodb.executeTransaction(input: transactionInput)
202+
return ExecuteTransactionInput(transactStatements: entryStatements + requiredItemsStatements)
205203
}
206204

207205
func transactWrite(_ entries: [WriteEntry<some Any, some Any>]) async throws {
@@ -216,16 +214,29 @@ public extension AWSDynamoDBCompositePrimaryKeyTable {
216214
retriesRemaining: self.retryConfiguration.numRetries)
217215
}
218216

219-
func polymorphicTransactWrite(_ entries: [some PolymorphicWriteEntry]) async throws {
217+
func polymorphicTransactWrite(_ entries: sending [some PolymorphicWriteEntry]) async throws {
220218
let noConstraints: [EmptyPolymorphicTransactionConstraintEntry] = []
221-
return try await self.polymorphicTransactWrite(entries, constraints: noConstraints,
222-
retriesRemaining: self.retryConfiguration.numRetries)
219+
220+
guard let transactionInput = try getExecuteTransactionInput(entries, constraints: noConstraints) else {
221+
// nothing to do
222+
return
223+
}
224+
let inputKeys = entries.map(\.compositePrimaryKey)
225+
226+
try await self.polymorphicTransactWrite(transactionInput, inputKeys: inputKeys,
227+
retriesRemaining: self.retryConfiguration.numRetries)
223228
}
224229

225230
func polymorphicTransactWrite(
226-
_ entries: [some PolymorphicWriteEntry], constraints: [some PolymorphicTransactionConstraintEntry]) async throws
231+
_ entries: sending [some PolymorphicWriteEntry], constraints: sending [some PolymorphicTransactionConstraintEntry]) async throws
227232
{
228-
try await self.polymorphicTransactWrite(entries, constraints: constraints,
233+
guard let transactionInput = try getExecuteTransactionInput(entries, constraints: constraints) else {
234+
// nothing to do
235+
return
236+
}
237+
let inputKeys = entries.map(\.compositePrimaryKey) + constraints.map(\.compositePrimaryKey)
238+
239+
try await self.polymorphicTransactWrite(transactionInput, inputKeys: inputKeys,
229240
retriesRemaining: self.retryConfiguration.numRetries)
230241
}
231242

@@ -336,31 +347,24 @@ public extension AWSDynamoDBCompositePrimaryKeyTable {
336347
return try await self.transactWrite(entries, constraints: constraints, retriesRemaining: retriesRemaining - 1)
337348
}
338349

339-
private func polymorphicTransactWrite(
340-
_ entries: [some PolymorphicWriteEntry], constraints: [some PolymorphicTransactionConstraintEntry],
341-
retriesRemaining: Int) async throws
342-
{
343-
let entryCount = entries.count + constraints.count
344-
345-
if entryCount > AWSDynamoDBLimits.maximumUpdatesPerTransactionStatement {
346-
throw DynamoDBTableError.transactionSizeExceeded(attemptedSize: entryCount,
350+
private func polymorphicTransactWrite(_ transactionInput: ExecuteTransactionInput, inputKeys: [StandardCompositePrimaryKey?], retriesRemaining: Int) async throws {
351+
if inputKeys.count > AWSDynamoDBLimits.maximumUpdatesPerTransactionStatement {
352+
throw DynamoDBTableError.transactionSizeExceeded(attemptedSize: inputKeys.count,
347353
maximumSize: AWSDynamoDBLimits.maximumUpdatesPerTransactionStatement)
348354
}
349355

350356
let result: Swift.Result<Void, DynamoDBTableError>
351357
do {
352-
try await self.writeTransactionItems(entries, constraints: constraints)
358+
_ = try await dynamodb.executeTransaction(input: transactionInput)
353359

354360
result = .success(())
355361
} catch let exception as TransactionCanceledException {
356362
guard let cancellationReasons = exception.properties.cancellationReasons else {
357363
throw DynamoDBTableError.transactionCanceled(reasons: [])
358364
}
359365

360-
let keys = entries.map(\.compositePrimaryKey) + constraints.map(\.compositePrimaryKey)
361-
362366
var isTransactionConflict = false
363-
let reasons = try zip(cancellationReasons, keys).compactMap { cancellationReason, entryKey -> DynamoDBTableError? in
367+
let reasons = try zip(cancellationReasons, inputKeys).compactMap { cancellationReason, entryKey -> DynamoDBTableError? in
364368
let key: StandardCompositePrimaryKey?
365369
if let item = cancellationReason.item {
366370
key = try DynamoDBDecoder().decode(.m(item))
@@ -383,7 +387,7 @@ public extension AWSDynamoDBCompositePrimaryKeyTable {
383387
return DynamoDBTableError.duplicateItem(partitionKey: partitionKey, sortKey: sortKey,
384388
message: cancellationReason.message)
385389
case "ItemCollectionSizeLimitExceeded":
386-
return DynamoDBTableError.transactionSizeExceeded(attemptedSize: entryCount,
390+
return DynamoDBTableError.transactionSizeExceeded(attemptedSize: inputKeys.count,
387391
maximumSize: AWSDynamoDBLimits.maximumUpdatesPerTransactionStatement)
388392
case "TransactionConflict":
389393
isTransactionConflict = true
@@ -403,13 +407,13 @@ public extension AWSDynamoDBCompositePrimaryKeyTable {
403407
}
404408

405409
if isTransactionConflict, retriesRemaining > 0 {
406-
return try await retryPolymorphicTransactWrite(entries, constraints: constraints, retriesRemaining: retriesRemaining)
410+
return try await retryPolymorphicTransactWrite(transactionInput, inputKeys: inputKeys, retriesRemaining: retriesRemaining)
407411
}
408412

409413
result = .failure(DynamoDBTableError.transactionCanceled(reasons: reasons))
410414
} catch let exception as TransactionConflictException {
411415
if retriesRemaining > 0 {
412-
return try await retryPolymorphicTransactWrite(entries, constraints: constraints, retriesRemaining: retriesRemaining)
416+
return try await retryPolymorphicTransactWrite(transactionInput, inputKeys: inputKeys, retriesRemaining: retriesRemaining)
413417
}
414418

415419
let reason = DynamoDBTableError.transactionConflict(message: exception.message)
@@ -428,10 +432,7 @@ public extension AWSDynamoDBCompositePrimaryKeyTable {
428432
}
429433
}
430434

431-
private func retryPolymorphicTransactWrite(
432-
_ entries: [some PolymorphicWriteEntry], constraints: [some PolymorphicTransactionConstraintEntry],
433-
retriesRemaining: Int) async throws
434-
{
435+
private func retryPolymorphicTransactWrite(_ transactionInput: ExecuteTransactionInput, inputKeys: [StandardCompositePrimaryKey?], retriesRemaining: Int) async throws {
435436
// determine the required interval
436437
let retryInterval = Int(self.retryConfiguration.getRetryInterval(retriesRemaining: retriesRemaining))
437438

@@ -440,7 +441,7 @@ public extension AWSDynamoDBCompositePrimaryKeyTable {
440441
try await Task.sleep(nanoseconds: UInt64(retryInterval) * millisecondsToNanoSeconds)
441442

442443
logger.trace("Reattempting request due to remaining retries: \(retryInterval)")
443-
return try await self.polymorphicTransactWrite(entries, constraints: constraints, retriesRemaining: retriesRemaining - 1)
444+
return try await self.polymorphicTransactWrite(transactionInput, inputKeys: inputKeys, retriesRemaining: retriesRemaining - 1)
444445
}
445446

446447
private func writeChunkedItems(_ entries: [some PolymorphicWriteEntry]) async throws {
@@ -464,7 +465,7 @@ public extension AWSDynamoDBCompositePrimaryKeyTable {
464465
try self.throwOnBatchExecuteStatementErrors(response: response)
465466
}
466467

467-
func polymorphicBulkWrite(_ entries: [some PolymorphicWriteEntry]) async throws {
468+
func polymorphicBulkWrite(_ entries: sending [some PolymorphicWriteEntry]) async throws {
468469
// BatchExecuteStatement has a maximum of 25 statements
469470
// This function handles pagination internally.
470471
let chunkedEntries = entries.chunked(by: AWSDynamoDBLimits.maximumUpdatesPerExecuteStatement)

Sources/DynamoDBTables/DynamoDBCompositePrimaryKeyTable.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ public protocol DynamoDBCompositePrimaryKeyTable {
140140
func transactWrite<AttributesType, ItemType>(_ entries: [WriteEntry<AttributesType, ItemType>]) async throws
141141

142142
func polymorphicTransactWrite<WriteEntryType: PolymorphicWriteEntry>(
143-
_ entries: [WriteEntryType]) async throws
143+
_ entries: sending [WriteEntryType]) async throws
144144

145145
/**
146146
* Provides the ability to bulk write database rows in a transaction.
@@ -153,7 +153,7 @@ public protocol DynamoDBCompositePrimaryKeyTable {
153153
_ entries: [WriteEntry<AttributesType, ItemType>], constraints: [TransactionConstraintEntry<AttributesType, ItemType>]) async throws
154154

155155
func polymorphicTransactWrite<WriteEntryType: PolymorphicWriteEntry, TransactionConstraintEntryType: PolymorphicTransactionConstraintEntry>(
156-
_ entries: [WriteEntryType], constraints: [TransactionConstraintEntryType]) async throws
156+
_ entries: sending [WriteEntryType], constraints: sending [TransactionConstraintEntryType]) async throws
157157

158158
/**
159159
* Provides the ability to bulk write database rows
@@ -165,7 +165,7 @@ public protocol DynamoDBCompositePrimaryKeyTable {
165165
func bulkWriteWithoutThrowing<AttributesType, ItemType>(_ entries: [WriteEntry<AttributesType, ItemType>]) async throws
166166
-> Set<DynamoDBClientTypes.BatchStatementErrorCodeEnum>
167167

168-
func polymorphicBulkWrite<WriteEntryType: PolymorphicWriteEntry>(_ entries: [WriteEntryType]) async throws
168+
func polymorphicBulkWrite<WriteEntryType: PolymorphicWriteEntry>(_ entries: sending [WriteEntryType]) async throws
169169

170170
/**
171171
* Retrieves an item from the database table. Returns nil if the item doesn't exist.

Sources/DynamoDBTables/InMemoryDynamoDBCompositePrimaryKeyTable.swift

Lines changed: 10 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -46,19 +46,10 @@ public typealias ExecuteItemFilterType = @Sendable (String, String, String, Poly
4646

4747
public protocol InMemoryTransactionDelegate {
4848
/**
49-
Inject errors into a `transactWrite` call.
49+
Inject errors into a `transactWrite` or `polymorphicTransactWrite` call.
5050
*/
51-
func injectErrors<AttributesType, ItemType>(
52-
_ entries: [WriteEntry<AttributesType, ItemType>], constraints: [TransactionConstraintEntry<AttributesType, ItemType>],
53-
table: InMemoryDynamoDBCompositePrimaryKeyTable) async throws -> [DynamoDBTableError]
54-
55-
/**
56-
Inject errors into a `polymorphicTransactWrite` call.
57-
*/
58-
func injectErrors<WriteEntryType: PolymorphicWriteEntry,
59-
TransactionConstraintEntryType: PolymorphicTransactionConstraintEntry>(
60-
_ entries: [WriteEntryType], constraints: [TransactionConstraintEntryType],
61-
table: InMemoryDynamoDBCompositePrimaryKeyTable) async throws -> [DynamoDBTableError]
51+
func injectErrors<AttributesType>(
52+
inputKeys: [CompositePrimaryKey<AttributesType>?], table: InMemoryDynamoDBCompositePrimaryKeyTable) async throws -> [DynamoDBTableError]
6253
}
6354

6455
public struct InMemoryDynamoDBCompositePrimaryKeyTable: DynamoDBCompositePrimaryKeyTable {
@@ -116,30 +107,32 @@ public struct InMemoryDynamoDBCompositePrimaryKeyTable: DynamoDBCompositePrimary
116107
constraints: [TransactionConstraintEntry<AttributesType, ItemType>]) async throws
117108
{
118109
// if there is a transaction delegate and it wants to inject errors
119-
if let errors = try await transactionDelegate?.injectErrors(entries, constraints: constraints, table: self), !errors.isEmpty {
110+
let inputKeys = entries.map(\.compositePrimaryKey) + constraints.map(\.compositePrimaryKey)
111+
if let errors = try await transactionDelegate?.injectErrors(inputKeys: inputKeys, table: self), !errors.isEmpty {
120112
throw DynamoDBTableError.transactionCanceled(reasons: errors)
121113
}
122114

123115
return try await self.storeWrapper.bulkWrite(entries, constraints: constraints, isTransaction: true)
124116
}
125117

126-
public func polymorphicTransactWrite(_ entries: [some PolymorphicWriteEntry]) async throws {
118+
public func polymorphicTransactWrite(_ entries: sending [some PolymorphicWriteEntry]) async throws {
127119
let noConstraints: [EmptyPolymorphicTransactionConstraintEntry] = []
128120
return try await self.polymorphicTransactWrite(entries, constraints: noConstraints)
129121
}
130122

131123
public func polymorphicTransactWrite(
132-
_ entries: [some PolymorphicWriteEntry], constraints: [some PolymorphicTransactionConstraintEntry]) async throws
124+
_ entries: sending [some PolymorphicWriteEntry], constraints: sending [some PolymorphicTransactionConstraintEntry]) async throws
133125
{
134126
// if there is a transaction delegate and it wants to inject errors
135-
if let errors = try await transactionDelegate?.injectErrors(entries, constraints: constraints, table: self), !errors.isEmpty {
127+
let inputKeys = entries.map(\.compositePrimaryKey) + constraints.map(\.compositePrimaryKey)
128+
if let errors = try await transactionDelegate?.injectErrors(inputKeys: inputKeys, table: self), !errors.isEmpty {
136129
throw DynamoDBTableError.transactionCanceled(reasons: errors)
137130
}
138131

139132
return try await self.storeWrapper.polymorphicBulkWrite(entries, constraints: constraints, isTransaction: true)
140133
}
141134

142-
public func polymorphicBulkWrite(_ entries: [some PolymorphicWriteEntry]) async throws {
135+
public func polymorphicBulkWrite(_ entries: sending [some PolymorphicWriteEntry]) async throws {
143136
let noConstraints: [EmptyPolymorphicTransactionConstraintEntry] = []
144137
return try await self.storeWrapper.polymorphicBulkWrite(entries, constraints: noConstraints, isTransaction: false)
145138
}

Sources/DynamoDBTables/InMemoryDynamoDBCompositePrimaryKeyTableStore.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ actor InMemoryDynamoDBCompositePrimaryKeyTableStore {
232232
}
233233

234234
func polymorphicBulkWrite(
235-
_ entries: [some PolymorphicWriteEntry], constraints: [some PolymorphicTransactionConstraintEntry],
235+
_ entries: sending [some PolymorphicWriteEntry], constraints: [some PolymorphicTransactionConstraintEntry],
236236
isTransaction: Bool) throws
237237
{
238238
let entryCount = entries.count + constraints.count
@@ -664,7 +664,7 @@ extension InMemoryDynamoDBCompositePrimaryKeyTableStore {
664664
}
665665

666666
func handlePolymorphicEntries(
667-
entries: [some PolymorphicWriteEntry], isTransaction: Bool,
667+
entries: sending [some PolymorphicWriteEntry], isTransaction: Bool,
668668
context: StandardPolymorphicWriteEntryContext<InMemoryPolymorphicWriteEntryTransform,
669669
InMemoryPolymorphicTransactionConstraintTransform>)
670670
-> DynamoDBTableError?

Sources/DynamoDBTables/InMemoryDynamoDBCompositePrimaryKeyTableWithIndex.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,17 +86,17 @@ public struct InMemoryDynamoDBCompositePrimaryKeyTableWithIndex<GSILogic: Dynamo
8686
try await self.primaryTable.transactWrite(entries, constraints: constraints)
8787
}
8888

89-
public func polymorphicTransactWrite(_ entries: [some PolymorphicWriteEntry]) async throws {
89+
public func polymorphicTransactWrite(_ entries: sending [some PolymorphicWriteEntry]) async throws {
9090
try await self.primaryTable.polymorphicTransactWrite(entries)
9191
}
9292

9393
public func polymorphicTransactWrite(
94-
_ entries: [some PolymorphicWriteEntry], constraints: [some PolymorphicTransactionConstraintEntry]) async throws
94+
_ entries: sending [some PolymorphicWriteEntry], constraints: sending [some PolymorphicTransactionConstraintEntry]) async throws
9595
{
9696
try await self.primaryTable.polymorphicTransactWrite(entries, constraints: constraints)
9797
}
9898

99-
public func polymorphicBulkWrite(_ entries: [some PolymorphicWriteEntry]) async throws {
99+
public func polymorphicBulkWrite(_ entries: sending [some PolymorphicWriteEntry]) async throws {
100100
try await self.primaryTable.polymorphicBulkWrite(entries)
101101
}
102102

Sources/DynamoDBTables/PolymorphicWriteEntry.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ public protocol PolymorphicTransactionConstraintTransform {
4444

4545
// Conforming types are provided by the application to express the different possible write entries
4646
// and how they can be converted to the table-provided transform type.
47-
public protocol PolymorphicWriteEntry: Sendable {
47+
public protocol PolymorphicWriteEntry {
4848
func handle<Context: PolymorphicWriteEntryContext>(context: Context) throws -> Context.WriteEntryTransformType
4949

5050
var compositePrimaryKey: StandardCompositePrimaryKey? { get }

Sources/DynamoDBTables/SimulateConcurrencyDynamoDBCompositePrimaryKeyTable.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -116,17 +116,17 @@ public class SimulateConcurrencyDynamoDBCompositePrimaryKeyTable: DynamoDBCompos
116116
try await self.wrappedDynamoDBTable.transactWrite(entries, constraints: constraints)
117117
}
118118

119-
public func polymorphicTransactWrite(_ entries: [some PolymorphicWriteEntry]) async throws {
119+
public func polymorphicTransactWrite(_ entries: sending [some PolymorphicWriteEntry]) async throws {
120120
try await self.wrappedDynamoDBTable.polymorphicTransactWrite(entries)
121121
}
122122

123123
public func polymorphicTransactWrite(
124-
_ entries: [some PolymorphicWriteEntry], constraints: [some PolymorphicTransactionConstraintEntry]) async throws
124+
_ entries: sending [some PolymorphicWriteEntry], constraints: sending [some PolymorphicTransactionConstraintEntry]) async throws
125125
{
126126
try await self.wrappedDynamoDBTable.polymorphicTransactWrite(entries, constraints: constraints)
127127
}
128128

129-
public func polymorphicBulkWrite(_ entries: [some PolymorphicWriteEntry]) async throws {
129+
public func polymorphicBulkWrite(_ entries: sending [some PolymorphicWriteEntry]) async throws {
130130
try await self.wrappedDynamoDBTable.polymorphicBulkWrite(entries)
131131
}
132132

0 commit comments

Comments
 (0)