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
Show file tree
Hide file tree
Changes from all 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
1 change: 1 addition & 0 deletions Package.swift
Expand Up @@ -10,6 +10,7 @@ let package = Package(
targets: ["MeowVapor"]),
],
dependencies: [
.package(url: "https://github.com/OpenKitten/MongoKitten.git", from: "5.1.1"),
.package(url: "https://github.com/OpenKitten/Meow.git", from: "2.0.0"),
.package(url: "https://github.com/vapor/vapor.git", from: "3.0.0")
],
Expand Down
8 changes: 3 additions & 5 deletions README.md
Expand Up @@ -15,18 +15,16 @@ Add MeowVapor as a dependency via SPM and run `swift package update`.
Add Meow to your Vapor services. Be sure to change the MongoDB URI to point to your server.

```swift
let meow = try MeowProvider("mongodb://ocalhost")
let meow = try MeowProvider(uri: "mongodb://localhost")
try services.register(meow)
```

## Using MeowVapor

```swift
router.get { request -> Future<[User]> in
return request.meow().flatMap { context in
// Start using Meow!
return context.find(User.self).getAllResults()
}
let context = try request.make(Meow.Context.self)
return context.find(User.self).getAllResults()
}
```

Expand Down
53 changes: 39 additions & 14 deletions Sources/MeowVapor/MeowProvider.swift
Expand Up @@ -12,20 +12,54 @@ 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
@available(*, deprecated, message: "A new initializer is introduced which is more explicit and connects lazily to your database. See our raedme for more information.")
public convenience init(_ uri: String) throws {
try self.init(uri: uri, lazy: false)
}

/// 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 = true) throws {
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 +71,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 +79,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()
}
}