Skip to content

Commit

Permalink
Merge pull request #4 from OpenKitten/feature/lazy-connect
Browse files Browse the repository at this point in the history
Adds lazy connecting to MeowProvider
  • Loading branch information
Obbut committed Feb 22, 2019
2 parents d239e53 + 0e9b106 commit 0e67384
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 19 deletions.
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()
}
}

0 comments on commit 0e67384

Please sign in to comment.