Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 3 additions & 5 deletions Sources/MongoSwift/APM.swift
Original file line number Diff line number Diff line change
Expand Up @@ -544,12 +544,10 @@ extension ConnectionPool {

// we can pass the MongoClient as unretained because the callbacks are stored on clientHandle, so if the
// callback is being executed, this pool and therefore its parent `MongoClient` must still be valid.
switch self.mode {
case let .single(clientHandle):
mongoc_client_set_apm_callbacks(clientHandle, callbacks, Unmanaged.passUnretained(client).toOpaque())
case let .pooled(pool):
switch self.state {
case let .open(pool):
mongoc_client_pool_set_apm_callbacks(pool, callbacks, Unmanaged.passUnretained(client).toOpaque())
case .none:
case .closed:
fatalError("ConnectionPool was already closed")
}
}
Expand Down
64 changes: 22 additions & 42 deletions Sources/MongoSwift/ConnectionPool.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,30 +12,18 @@ internal struct Connection {

/// A pool of one or more connections.
internal class ConnectionPool {
/// Represents the mode of a `ConnectionPool`.
internal enum Mode {
/// Indicates that we are in single-client mode using the associated pointer to a `mongoc_client_t`.
case single(client: OpaquePointer)
/// Indicates that we are in pooled mode using the associated pointer to a `mongoc_client_pool_t`.
case pooled(pool: OpaquePointer)
/// Represents the state of a `ConnectionPool`.
internal enum State {
/// Indicates that the `ConnectionPool` is open and using the associated pointer to a `mongoc_client_pool_t`.
case open(pool: OpaquePointer)
/// Indicates that the `ConnectionPool` has been closed and contains no connections.
case none
case closed
}

/// The mode of this `ConnectionPool`.
internal private(set) var mode: Mode
/// The state of this `ConnectionPool`.
internal private(set) var state: State

/// Initializes the pool in single mode using the provided pointer to a `mongoc_client_t`.
internal init(stealing pointer: OpaquePointer) {
self.mode = .single(client: pointer)

// This call may fail, and if it does, either the error api version was already set or the client was derived
// from a pool. In either case, the error handling in MongoSwift will be incorrect unless the correct api
// version was set by the caller.
mongoc_client_set_error_api(pointer, MONGOC_ERROR_API_VERSION_2)
}

/// Initializes the pool in pooled mode using the provided `ConnectionString`.
/// Initializes the pool using the provided `ConnectionString`.
internal init(from connString: ConnectionString, options: TLSOptions? = nil) throws {
guard let pool = mongoc_client_pool_new(connString._uri) else {
throw UserError.invalidArgumentError(message: "libmongoc not built with TLS support")
Expand All @@ -45,7 +33,7 @@ internal class ConnectionPool {
throw RuntimeError.internalError(message: "Could not configure error handling on client pool")
}

self.mode = .pooled(pool: pool)
self.state = .open(pool: pool)
if let options = options {
try self.setTLSOptions(options)
}
Expand All @@ -58,37 +46,31 @@ internal class ConnectionPool {

/// Closes the pool, cleaning up underlying resources.
internal func close() {
switch self.mode {
case let .single(clientHandle):
mongoc_client_destroy(clientHandle)
case let .pooled(pool):
switch self.state {
case let .open(pool):
mongoc_client_pool_destroy(pool)
case .none:
case .closed:
return
}
self.mode = .none
self.state = .closed
}

/// Checks out a connection. This connection must be returned to the pool via `checkIn`.
internal func checkOut() throws -> Connection {
switch self.mode {
case let .single(clientHandle):
return Connection(clientHandle)
case let .pooled(pool):
switch self.state {
case let .open(pool):
return Connection(mongoc_client_pool_pop(pool))
case .none:
case .closed:
throw RuntimeError.internalError(message: "ConnectionPool was already closed")
}
}

/// Returns a connection to the pool.
internal func checkIn(_ connection: Connection) {
switch self.mode {
case .single:
return
case let .pooled(pool):
switch self.state {
case let .open(pool):
mongoc_client_pool_push(pool, connection.clientHandle)
case .none:
case .closed:
fatalError("ConnectionPool was already closed")
}
}
Expand Down Expand Up @@ -128,12 +110,10 @@ internal class ConnectionPool {
if let invalidHosts = options.allowInvalidHostnames {
opts.allow_invalid_hostname = invalidHosts
}
switch self.mode {
case let .single(clientHandle):
mongoc_client_set_ssl_opts(clientHandle, &opts)
case let .pooled(pool):
switch self.state {
case let .open(pool):
mongoc_client_pool_set_ssl_opts(pool, &opts)
case .none:
case .closed:
throw RuntimeError.internalError(message: "ConnectionPool was already closed")
}
}
Expand Down
30 changes: 0 additions & 30 deletions Sources/MongoSwift/MongoClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -252,36 +252,6 @@ public class MongoClient {
)
}

/**
* :nodoc:
*/
@available(*, deprecated, message: "Use MongoClient(stealing:) instead.")
public convenience init(fromPointer pointer: OpaquePointer) {
self.init(stealing: pointer)
}

/**
* :nodoc:
* Create a new client from an existing `mongoc_client_t`. The new client will destroy the `mongoc_client_t` upon
* deinitialization.
* Do not use this initializer unless you know what you are doing. You *must* call libmongoc_init *before* using
* this initializer for the first time.
*
* If this client was derived from a pool, ensure that the error api version was set to 2 on the pool.
*
* - Parameters:
* - pointer: the `mongoc_client_t` to store and use internally
*/
public init(stealing pointer: OpaquePointer) {
self.connectionPool = ConnectionPool(stealing: pointer)
self.encoder = BSONEncoder()
self.decoder = BSONDecoder()
self.readConcern = nil
self.readPreference = ReadPreference()
self.writeConcern = nil
self.notificationCenter = NotificationCenter.default
}

/**
* Starts a new `ClientSession` with the provided options.
*
Expand Down
1 change: 0 additions & 1 deletion Tests/LinuxMain.swift
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,6 @@ extension Document_SequenceTests {
extension MongoClientTests {
static var allTests = [
("testListDatabases", testListDatabases),
("testOpaqueInitialization", testOpaqueInitialization),
("testFailedClientInitialization", testFailedClientInitialization),
("testServerVersion", testServerVersion),
("testCodingStrategies", testCodingStrategies),
Expand Down
25 changes: 0 additions & 25 deletions Tests/MongoSwiftTests/MongoClientTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -50,31 +50,6 @@ final class MongoClientTests: MongoSwiftTestCase {
}
}

func testOpaqueInitialization() throws {
if MongoSwiftTestCase.ssl {
print("Skipping test, bypasses SSL setup")
return
}
let connectionString = MongoSwiftTestCase.connStr
var error = bson_error_t()
guard let uri = mongoc_uri_new_with_error(connectionString, &error) else {
throw extractMongoError(error: error)
}

guard let client_t = mongoc_client_new_from_uri(uri) else {
throw UserError.invalidArgumentError(message: "libmongoc not built with TLS support.")
}

let client = MongoClient(stealing: client_t)
let db = client.db(type(of: self).testDatabase)
let coll = db.collection(self.getCollectionName())
let insertResult = try coll.insertOne(["test": 42])
let findResult = try coll.find(["_id": insertResult!.insertedId])
let docs = Array(findResult)
expect(docs[0]["test"]).to(equal(42))
try db.drop()
}

func testFailedClientInitialization() {
// check that we fail gracefully with an error if passing in an invalid URI
expect(try MongoClient("abcd")).to(throwError(UserError.invalidArgumentError(message: "")))
Expand Down
36 changes: 0 additions & 36 deletions release/release.sh
Original file line number Diff line number Diff line change
Expand Up @@ -23,41 +23,5 @@ git tag "v${1}"
git push
git push --tags

# update podspec
cat > ${PWD}/MongoSwift.podspec <<- EOF
Pod::Spec.new do |spec|
spec.name = "MongoSwift"
spec.version = "${1}"
spec.summary = "The Swift driver for MongoDB"
spec.homepage = "https://github.com/mongodb/mongo-swift-driver"
spec.license = 'Apache License, Version 2.0'
spec.authors = {
"Matt Broadstone" => "mbroadst@mongodb.com",
"Kaitlin Mahar" => "kaitlin.mahar@mongodb.com",
"Patrick Freed" => "patrick.freed@mongodb.com"
}

spec.source = {
:git => "https://github.com/mongodb/mongo-swift-driver.git",
:tag => 'v${1}'
}

spec.ios.deployment_target = "11.0"
spec.tvos.deployment_target = "10.2"
spec.watchos.deployment_target = "4.3"

spec.requires_arc = true
spec.source_files = "Sources/MongoSwift/**/*.swift"

spec.dependency 'mongo-embedded-c-driver', '~> 1.13.0-4.0.0'
end
EOF

# publish new podspec
pod trunk push ${PWD}/MongoSwift.podspec --allow-warnings

# cleanup podspec
rm ${PWD}/MongoSwift.podspec

# go to GitHub to publish release notes
open "https://github.com/mongodb/mongo-swift-driver/releases/tag/v${1}"