Skip to content

Commit 684befc

Browse files
meyertst-awsLaren-AWS
authored andcommitted
ListTables done
1 parent eceddcc commit 684befc

File tree

3 files changed

+50
-76
lines changed

3 files changed

+50
-76
lines changed

swift/example_code/dynamodb/ListTables/Sources/DatabaseManager.swift

Lines changed: 39 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@
66
/// SPDX-License-Identifier: Apache-2.0
77

88
// snippet-start:[ddb.swift.databasemanager-all]
9-
import Foundation
109
import AWSDynamoDB
1110
import ClientRuntime
11+
import Foundation
1212

1313
/// A protocol describing the implementation of functions that allow either
1414
/// calling through to Amazon DynamoDB or mocking DynamoDB functions.
@@ -22,26 +22,32 @@ public protocol DatabaseSession {
2222
/// - Parameter input: A `ListTablesInput` object specifying the input
2323
/// parameters for the call to `listTables()`.
2424
///
25-
/// - Returns: A `ListTablesOutput` structure with the results.
26-
func listTables(input: ListTablesInput) async throws -> ListTablesOutput
25+
/// - Returns: A `[String]` list of table names..
26+
func listTables(input: ListTablesInput) async throws -> [String]
2727
}
2828

2929
// snippet-start:[ddb.swift.dynamodbsession]
3030
/// An implementation of the `DatabaseSession` protocol that calls through to
3131
/// DynamoDB for its operations.
3232
public struct DynamoDBSession: DatabaseSession {
33-
let awsRegion: String
3433
let client: DynamoDBClient
3534

3635
// snippet-start:[ddb.swift.dynamodbsession.init]
3736
/// Initialize the `DatabaseSession`.
3837
///
3938
/// - Parameter region: The AWS Region to use for DynamoDB.
4039
///
41-
init(region: String = "us-east-2") throws {
42-
self.awsRegion = region
43-
self.client = try DynamoDBClient(region: awsRegion)
40+
init(region: String? = nil) async throws {
41+
do {
42+
let config = try await DynamoDBClient.DynamoDBClientConfiguration()
43+
if let region = region {
44+
config.region = region
45+
}
46+
47+
self.client = DynamoDBClient(config: config)
48+
}
4449
}
50+
4551
// snippet-end:[ddb.swift.dynamodbsession.init]
4652

4753
// snippet-start:[ddb.swift.dynamodbsession.listtables]
@@ -52,13 +58,31 @@ public struct DynamoDBSession: DatabaseSession {
5258
/// `ListTablesInput` object.
5359
///
5460
/// - Returns: The `ListTablesOutput` returned by `listTables()`.
55-
///
61+
///
5662
/// - Throws: Errors from DynamoDB are thrown as usual.
57-
public func listTables(input: ListTablesInput) async throws -> ListTablesOutput {
58-
return try await client.listTables(input: input)
63+
public func listTables(input: ListTablesInput) async throws -> [String] {
64+
do {
65+
// Use "Paginated" to get all the tables.
66+
// This lets the SDK handle the 'lastEvaluatedTableName' property in "ListTablesOutput".
67+
let pages = client.listTablesPaginated(input: input)
68+
69+
var allTableNames: [String] = []
70+
for try await page in pages {
71+
guard let tableNames = page.tableNames else {
72+
print("Error: no table names returned.")
73+
continue
74+
}
75+
allTableNames += tableNames
76+
}
77+
return allTableNames
78+
} catch {
79+
print("ERROR: listTables:", dump(error))
80+
throw error
81+
}
5982
}
6083
// snippet-end:[ddb.swift.dynamodbsession.listtables]
6184
}
85+
6286
// snippet-end:[ddb.swift.dynamodbsession]
6387

6488
// snippet-start:[ddb.swift.databasemanager]
@@ -77,6 +101,7 @@ public class DatabaseManager {
77101
init(session: DatabaseSession) {
78102
self.session = session
79103
}
104+
80105
// snippet-end:[ddb.swift.databasemanager.init]
81106

82107
// snippet-start:[ddb.swift.databasemanager.gettablelist]
@@ -85,29 +110,12 @@ public class DatabaseManager {
85110
/// - Returns: An array of strings listing all of the tables available
86111
/// in the Region specified when the session was created.
87112
public func getTableList() async throws -> [String] {
88-
var tableList: [String] = []
89-
var lastEvaluated: String? = nil
90-
91-
// Iterate over the list of tables, 25 at a time, until we have the
92-
// names of every table. Add each group to the `tableList` array.
93-
// Iteration is complete when `output.lastEvaluatedTableName` is `nil`.
94-
95-
repeat {
96-
let input = ListTablesInput(
97-
exclusiveStartTableName: lastEvaluated,
98-
limit: 25
99-
)
100-
let output = try await self.session.listTables(input: input)
101-
guard let tableNames = output.tableNames else {
102-
return tableList
103-
}
104-
tableList.append(contentsOf: tableNames)
105-
lastEvaluated = output.lastEvaluatedTableName
106-
} while lastEvaluated != nil
107-
108-
return tableList
113+
let input = ListTablesInput(
114+
)
115+
return try await session.listTables(input: input)
109116
}
110117
// snippet-end:[ddb.swift.databasemanager.gettablelist]
111118
}
119+
112120
// snippet-end:[ddb.swift.databasemanager]
113121
// snippet-end:[ddb.swift.databasemanager-all]

swift/example_code/dynamodb/ListTables/Sources/listtables.swift

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,14 @@
77
/// SPDX-License-Identifier: Apache-2.0
88

99
// snippet-start:[ddb.swift.listtables]
10-
import Foundation
1110
import ArgumentParser
1211
import AWSDynamoDB
1312
import ClientRuntime
13+
import Foundation
1414

1515
struct ExampleCommand: ParsableCommand {
1616
@Option(help: "The AWS Region to run AWS API calls in.")
17-
var awsRegion = "us-east-2"
17+
var awsRegion: String?
1818

1919
@Option(
2020
help: ArgumentHelp("The level of logging for the Swift SDK to perform."),
@@ -45,7 +45,7 @@ struct ExampleCommand: ParsableCommand {
4545

4646
/// Called by ``main()`` to asynchronously run the AWS example.
4747
func runAsync() async throws {
48-
let session = try DynamoDBSession(region: awsRegion)
48+
let session = try await DynamoDBSession(region: awsRegion)
4949
let dbManager = DatabaseManager(session: session)
5050

5151
let tableList = try await dbManager.getTableList()
@@ -72,4 +72,5 @@ struct Main {
7272
}
7373
}
7474
}
75+
7576
// snippet-end:[ddb.swift.listtables]

swift/example_code/dynamodb/ListTables/Tests/ListTablesTests.swift

Lines changed: 7 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -80,54 +80,19 @@ public struct MockDBSession: DatabaseSession {
8080
/// Mock version of the DynamoDB client's `listTables()` function. Returns
8181
/// values from the string array `fakeTableNames` or the one specified as
8282
/// an optional input when creating the `MockDBSession`.
83-
public func listTables(input: ListTablesInput) async throws -> ListTablesOutput {
84-
var output = ListTablesOutput(
85-
lastEvaluatedTableName: nil,
86-
tableNames: nil
87-
)
88-
89-
// Stop at once if there are no table names in the list.
90-
91-
if testTableNames.count == 0 {
92-
return output
83+
public func listTables(input: ListTablesInput) async throws -> [String] {
84+
var maxTables = testTableNames.count
85+
if let limit = input.limit {
86+
maxTables = Swift.min(limit, maxTables)
9387
}
9488

95-
var startIndex: Int
96-
97-
// Get the starting point in the list using the input's
98-
// `exclusiveStartTableName` property. If it's `nil` or the string
99-
// isn't found in the list, use 0 for the index.
100-
101-
if input.exclusiveStartTableName != nil {
102-
startIndex = testTableNames.firstIndex(of: input.exclusiveStartTableName!) ?? 0
103-
} else {
104-
startIndex = 0
105-
}
106-
107-
// Split the full list of table names into the number of parts
108-
// specified by the `limit` parameter, or 100 parts if `limit` is not
109-
// specified.
110-
111-
let chunkSize = input.limit ?? 100
112-
let chunks: [[String]] = stride(from: startIndex, to: testTableNames.count, by: chunkSize).map {
113-
Array(testTableNames[$0 ..< Swift.min($0 + chunkSize, testTableNames.count)])
114-
}
115-
116-
output.tableNames = chunks[0]
117-
if chunks.count == 1 {
118-
output.lastEvaluatedTableName = nil
119-
} else {
120-
output.lastEvaluatedTableName = chunks[1].first
121-
}
122-
123-
return output
89+
return Array(testTableNames[0..<maxTables])
12490
}
12591
}
12692

12793
/// Perform tests on the `getTableList()` function.
12894
final class ListTablesTests: XCTestCase {
129-
static let region = "us-east-2"
130-
95+
13196
/// Class-wide setup function for the test case, which is run *once*
13297
/// before any tests are run.
13398
///
@@ -165,4 +130,4 @@ final class ListTablesTests: XCTestCase {
165130
let list = try await dbManager.getTableList()
166131
XCTAssertEqual(list, testNames, "Returned list of table names doesn't match original list.")
167132
}
168-
}
133+
}

0 commit comments

Comments
 (0)