Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds lazy connecting to MeowProvider #4

Merged
merged 4 commits into from Feb 22, 2019
Merged
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
47 changes: 33 additions & 14 deletions Sources/MeowVapor/MeowProvider.swift
Expand Up @@ -12,20 +12,48 @@ public final class MeowProvider: Provider {
return .done(on: container)
}

let lazy: Bool
let connectionSettings: ConnectionSettings

public init(_ uri: String) throws {
/// Connects to the MongoDB server or cluster located at the URI
///
/// If `lazy` is set to true, the first error Meow throws will occur on the first query, not when creating the database, manager or context.
/// The advantage of using `lazy` is the ability to call `request.make(Meow.Context.self)` and `request.make(Meow.Manager.self)`
///
/// For backwards compatibility and predictability, lazy defaults to `false`
public init(_ uri: String, lazy: Bool = false) throws {
Obbut marked this conversation as resolved.
Show resolved Hide resolved
self.connectionSettings = try ConnectionSettings(uri)
self.lazy = lazy
}

public func register(_ services: inout Services) throws {
let managerFactory = BasicServiceFactory(Future<Meow.Manager>.self, supports: []) { container in
return MongoKitten.Database.connect(settings: self.connectionSettings, on: container.eventLoop).map { database in
Meow.Manager(database: database)
if lazy {
services.register { container -> Meow.Manager in
let database = try MongoKitten.Database.lazyConnect(settings: self.connectionSettings, on: container.eventLoop)
return Meow.Manager(database: database)
}

services.register { container -> Future<Meow.Manager> in
do {
let manager = try container.make(Meow.Manager.self)
return container.eventLoop.future(manager)
} catch {
return container.eventLoop.future(error: error)
}
}

services.register { container -> Meow.Context in
return try container.make(Meow.Manager.self).makeContext()
}
} else {
services.register { container in
return MongoKitten.Database.connect(settings: self.connectionSettings, on: container.eventLoop).map { database in
Meow.Manager(database: database)
}
}
}

let contextFactory = BasicServiceFactory(Future<Meow.Context>.self, supports: []) { container in
services.register { container -> Future<Context> in
let managerContainer: Container
// The context manager should be on the super container (so every request has its own context but shares a database connection with other requests)
if let subContainer = container as? SubContainer {
Expand All @@ -37,9 +65,6 @@ public final class MeowProvider: Provider {
let manager = try managerContainer.make(Future<Manager>.self)
return manager.map { $0.makeContext() }
}

services.register(managerFactory)
services.register(contextFactory)
}
}

Expand All @@ -48,10 +73,4 @@ public extension Request {
public func meow() -> Future<Meow.Context> {
return Future.flatMap(on: self) { try self.privateContainer.make(Future<Meow.Context>.self) }
}

@available(*, deprecated, message: "Use request.meow() instead of request.make(Context.self) to create a Meow context. Meow contexts should have a lifetime of one request, and making it on the request would allow the context to exceed this lifespan.")
public func make(_ type: Meow.Context.Type) throws -> Meow.Context {
assertionFailure()
return try self.make()
}
}