From c714635dbacf702d6de93b860d85d254bdbafd34 Mon Sep 17 00:00:00 2001 From: Yim Lee Date: Tue, 20 Dec 2022 21:07:41 -0800 Subject: [PATCH] Update README (#12) Add async/await examples --- README.md | 212 +++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 156 insertions(+), 56 deletions(-) diff --git a/README.md b/README.md index 7eb4296..86c58ad 100644 --- a/README.md +++ b/README.md @@ -1,132 +1,232 @@ # Swift Cassandra Client -CassandraClient is a Cassandra client in Swift. The client is based on [Datastax Cassandra C++ Driver](https://github.com/datastax/cpp-driver) wrapping it with Swift friendly APIs and data structures. +CassandraClient is a Cassandra client in Swift. The client is based on [DataStax Cassandra C++ Driver](https://github.com/datastax/cpp-driver), +wrapping it with Swift friendly APIs and data structures. -CassandraClient API currently exposes [SwiftNIO](https://github.com/apple/swift-nio) based futures to simplify integration with SwiftNIO based servers. Swift concurrency based API is also available in Swift 5.5 and newer. +CassandraClient API currently exposes [SwiftNIO](https://github.com/apple/swift-nio) based futures to +simplify integration with SwiftNIO based servers. Swift concurrency based API is also available in Swift 5.5 and newer. ## Usage +### Swift concurrency based API + #### Creating a client instance ```swift - let configuration = CassandraClient.Configuration(...) - let cassandraClient = CassandraClient(configuration: configuration) +var configuration = CassandraClient.Configuration(...) +let cassandraClient = CassandraClient(configuration: configuration) ``` -The client has a default session established (lazily) so that it can be used directly to perform queries on the configured keyspace: +The client has a default session established (lazily) so that it can be used directly to perform +queries on the configured keyspace: ```swift - cassandraClient.query(...) +let result = try await cassandraClient.query(...) ``` -The client must be explicitly shut down when no longer needed. +The client must be explicitly shut down when no longer needed: ```swift - cassandraClient.shutdown() +try cassandraClient.shutdown() ``` #### Creating a session for a different keyspace ```swift - let session = cassandraClient.makeSession(keyspace: "the_keyspace") - session.query(...) +let session = cassandraClient.makeSession(keyspace: ) +let result = try await session.query(...) ``` -The session must be explicitly shut down when no longer needed. +The session must be explicitly shut down when no longer needed: ```swift - session.shutdown() +try session.shutdown() ``` -You can also create a session and pass in a closure, which will automatically release the resource when the closure exists: +You can also create a session and pass in a closure, which will automatically release the resource when the closure exits: ```swift - cassandraClient.withSession(keyspace: "") { session in - session.query(...) - } +try await cassandraClient.withSession(keyspace: ) { session in + ... +} ``` -#### Running result-less commands, e.g. insert, update, delete or DDL +#### Running result-less commands (e.g. insert, update, delete or DDL) ```swift - cassandraClient.run("create table ...") +try await cassandraClient.run("create table ...") ``` -Or at a session level +Or at session level: ```swift - session.run("create table ...") +try await session.run("create table ...") ``` -#### Running queries returning small data-sets that fit in-memory +#### Running queries returning small datasets that fit in memory -Returning a model object, having `Model: Codable` +Returning a model object, having `Model: Codable`: ```swift - cassandraClient.query("select * from table ...").map { (result: [Model]) in - ... - } - - let result: [Model] = try await cassandraClient.query("select * from table ...") +let result: [Model] = try await cassandraClient.query("select * from table ...") ``` ```swift - session.query("select * from table ...").map { (result: [Model]) in - ... - } +let result: [Model] = try await session.query("select * from table ...") +``` - let result: [Model] = try await session.query("select * from table ...") +Or using free-form transformations on the row: + +```swift +let values = try await cassandraClient.query("select * from table ...") { row in + row.column().int32 +} ``` -Or using free-form transformations on the row +```swift +let values = try await session.query("select * from table ...") { row in + row.column().int32 +} +``` + +#### Running queries returning large datasets that do not fit in memory ```swift - cassandraClient.query("select * from table ...") { row in - row.column("column_name").int32 - }.map { value in - ... - } +// `rows` is a sequence that one needs to iterate on +let rows: Rows = try await cassandraClient.query("select * from table ...") ``` ```swift - session.query("select * from table ...") { row in - row.column("column_name").int32 - }.map { value in - ... - } +// `rows` is a sequence that one needs to iterate on +let rows: Rows = try await session.query("select * from table ...") +``` + +### SwiftNIO future based API + +#### Creating a client instance + +```swift +var configuration = CassandraClient.Configuration(...) +let cassandraClient = CassandraClient(configuration: configuration) +``` + +The client has a default session established (lazily) so that it can be used directly to perform +queries on the configured keyspace: + +```swift +let resultFuture = cassandraClient.query(...) +``` + +The client must be explicitly shut down when no longer needed: + +```swift +try cassandraClient.shutdown() +``` + +#### Creating a session for a different keyspace + +```swift +let session = cassandraClient.makeSession(keyspace: ) +let resultFuture = session.query(...) +``` + +The session must be explicitly shut down when no longer needed: + +```swift +try session.shutdown() +``` + +You can also create a session and pass in a closure, which will automatically release the resource when the closure exits: + +```swift +try cassandraClient.withSession(keyspace: ) { session in + ... +} +``` + +#### Running result-less commands (e.g. insert, update, delete or DDL) + +```swift +let voidFuture = cassandraClient.run("create table ...") +``` + +Or at session level: + +```swift +let voidFuture = session.run("create table ...") ``` -#### Running queries returning large data-sets that do not fit in-memory +#### Running queries returning small datasets that fit in memory + +Returning a model object, having `Model: Codable`: ```swift - cassandraClient.query("select * from table ...").map { (rows: Rows) in - // rows is a sequence that one needs to iterate on - rows.map { row in - ... - } +cassandraClient.query("select * from table ...").map { result: [Model] in + ... +} +``` + +```swift +session.query("select * from table ...").map { result: [Model] in + ... +} +``` + +Or using free-form transformations on the row: + +```swift +cassandraClient.query("select * from table ...") { row in + row.column().int32 +}.map { value in + ... +} +``` + +```swift +session.query("select * from table ...") { row in + row.column().int32 +}.map { value in + ... +} +``` + +#### Running queries returning large datasets that do not fit in memory + +```swift +cassandraClient.query("select * from table ...").map { rows: Rows in + // `rows` is a sequence that one needs to iterate on + rows.map { row in + ... } +} ``` ```swift - session.query("select * from table ...").map { (rows: Rows) in - // rows is a sequence that one needs to iterate on - rows.map { row in - ... - } +session.query("select * from table ...").map { rows: Rows in + // `rows` is a sequence that one needs to iterate on + rows.map { row in + ... } +} ``` ## DataStax Driver and libuv -The library depends on [the DataStax driver](https://github.com/datastax/cpp-driver) and [libuv](https://github.com/libuv/libuv), which are included as git submodules. Both of them have source files that are excluded in `Package.swift`. +The library depends on [the DataStax driver](https://github.com/datastax/cpp-driver) and +[libuv](https://github.com/libuv/libuv), which are included as git submodules. Both of them +have source files that are excluded in `Package.swift`. ### DataStax driver -The git submodule is under `Sources/CDataStaxDriver/datastax-cpp-driver`. To update, do `git fetch` then checkout the desired [tag/release](https://github.com/datastax/cpp-driver/releases). The driver's config files are located in `Sources/CDataStaxDriver/extras`. +The git submodule is under `Sources/CDataStaxDriver/datastax-cpp-driver`. To update, +do `git fetch` then checkout the desired [tag/release](https://github.com/datastax/cpp-driver/releases). The +driver's config files are located in `Sources/CDataStaxDriver/extras`. ### libuv -The git submodule is under `Sources/Clibuv/libuv`. To update, do `git fetch` then checkout the desired [tag/release](https://github.com/libuv/libuv/releases). Note that `include` and `uv.h` in `Sources/Clibuv` are symlinked to the corresponding directory/file in `Sources/Clibuv/libuv`. +The git submodule is under `Sources/Clibuv/libuv`. To update, do `git fetch` then checkout +the desired [tag/release](https://github.com/libuv/libuv/releases). Note that `include` +and `uv.h` in `Sources/Clibuv` are symlinked to the corresponding directory/file in `Sources/Clibuv/libuv`. ## Development Setup