Hello,
We would like to pitch the Swift Cassandra Client package for inclusion in the SSWG incubation process. The library has not yet reached version 1.0, but since it has been used successfully at Apple, we propose to include it in the Incubating maturity level.
Package Description
The Swift Cassandra Client package is a Cassandra database client based on DataStax Cassandra C++ Driver, wrapping it with Swift-friendly APIs and data structures.
It offers API based on SwiftNIO futures, as well as Swift concurrency based API in Swift 5.5 and newer.
Package Name | swift-cassandra-client |
---|---|
Proposed Maturity Level | Incubating |
License | Apache 2.0 |
Dependencies | swift-nio, swift-log |
Motivation
Apple is an active contributor to the Apache Cassandra open source project and server teams at Apple use Cassandra to support various use-cases. The Swift Cassandra Client has been used in that capacity for several years and we believe the broader Swift community would find it useful as well.
Usage
Swift concurrency based API
Creating a client instance
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:
let result = try await cassandraClient.query(...)
The client must be explicitly shut down when no longer needed:
try cassandraClient.shutdown()
Creating a session for a different keyspace
let session = cassandraClient.makeSession(keyspace: <KEYSPACE>)
let result = try await session.query(...)
The session must be explicitly shut down when no longer needed:
try session.shutdown()
You can also create a session and pass in a closure, which will automatically release the resource when the closure exits:
try await cassandraClient.withSession(keyspace: <KEYSPACE>) { session in
...
}
Running result-less commands (e.g. insert, update, delete or DDL)
try await cassandraClient.run("create table ...")
Or at session level:
try await session.run("create table ...")
Running queries returning small datasets that fit in memory
Returning a model object, having Model: Codable
:
let result: [Model] = try await cassandraClient.query("select * from table ...")
let result: [Model] = try await session.query("select * from table ...")
Or using free-form transformations on the row:
let values = try await cassandraClient.query("select * from table ...") { row in
row.column(<COLUMN_NAME>).int32
}
let values = try await session.query("select * from table ...") { row in
row.column(<COLUMN_NAME>).int32
}
Running queries returning large datasets that do not fit in memory
// `rows` is a sequence that one needs to iterate on
let rows: Rows = try await cassandraClient.query("select * from table ...")
// `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
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:
let resultFuture = cassandraClient.query(...)
The client must be explicitly shut down when no longer needed:
try cassandraClient.shutdown()
Creating a session for a different keyspace
let session = cassandraClient.makeSession(keyspace: <KEYSPACE>)
let resultFuture = session.query(...)
The session must be explicitly shut down when no longer needed:
try session.shutdown()
You can also create a session and pass in a closure, which will automatically release the resource when the closure exits:
try cassandraClient.withSession(keyspace: <KEYSPACE>) { session in
...
}
Running result-less commands (e.g. insert, update, delete or DDL)
let voidFuture = cassandraClient.run("create table ...")
Or at session level:
let voidFuture = session.run("create table ...")
Running queries returning small datasets that fit in memory
Returning a model object, having Model: Codable
:
cassandraClient.query("select * from table ...").map { (result: [Model]) in
...
}
session.query("select * from table ...").map { (result: [Model]) in
...
}
Or using free-form transformations on the row:
cassandraClient.query("select * from table ...") { row in
row.column(<COLUMN_NAME>).int32
}.map { value in
...
}
session.query("select * from table ...") { row in
row.column(<COLUMN_NAME>).int32
}.map { value in
...
}
Running queries returning large datasets that do not fit in memory
cassandraClient.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
...
}
}
Maturity justification
As the library has been in use at Apple for several years, and we would like more time and exposure to collect user feedback to move towards its 1.0 release, we propose to include Swift Cassandra Client in Incubating level.