Skip to content

Commit

Permalink
Merge pull request #649 from vapor/tn-b2
Browse files Browse the repository at this point in the history
beta.2
  • Loading branch information
tanner0101 authored Dec 9, 2019
2 parents 82f15d7 + 7229607 commit 5adacb3
Show file tree
Hide file tree
Showing 6 changed files with 136 additions and 111 deletions.
9 changes: 1 addition & 8 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,8 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- run: swift test --enable-test-discovery
- run: swift test --enable-test-discovery --sanitize=thread
bionic:
container:
image: vapor/swift:5.1-bionic
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- run: swift test --enable-test-discovery
thread:
container:
image: vapor/swift:5.1-bionic
runs-on: ubuntu-latest
Expand Down
4 changes: 2 additions & 2 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ let package = Package(
.library(name: "Fluent", targets: ["Fluent"]),
],
dependencies: [
.package(url: "https://github.com/vapor/fluent-kit.git", .branch("master")),
.package(url: "https://github.com/vapor/vapor.git", .branch("master")),
.package(url: "https://github.com/vapor/fluent-kit.git", from: "1.0.0-beta.2"),
.package(url: "https://github.com/vapor/vapor.git", from: "4.0.0-beta.2"),
],
targets: [
.target(name: "Fluent", dependencies: ["FluentKit", "Vapor"]),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,35 +1,72 @@
import Vapor

public struct DatabaseSessions: SessionDriver {
public let databaseID: DatabaseID?
extension Application.Fluent {
public var sessions: Sessions {
.init(fluent: self)
}

public struct Sessions {
let fluent: Application.Fluent
}
}

extension Application.Fluent.Sessions {
public func middleware<User>(
for user: User.Type,
databaseID: DatabaseID? = nil
) -> Middleware
where User: SessionAuthenticatable, User: Model, User.SessionID == User.IDValue
{
DatabaseSessionAuthenticator<User>(databaseID: databaseID).middleware()
}

public func driver(_ databaseID: DatabaseID? = nil) -> SessionDriver {
DatabaseSessions(databaseID: databaseID)
}
}

extension Application.Sessions.Provider {
public static var fluent: Self {
return .fluent(nil)
}

public static func fluent(_ databaseID: DatabaseID?) -> Self {
.init {
$0.sessions.use { $0.fluent.sessions.driver(databaseID) }
}
}
}

private struct DatabaseSessions: SessionDriver {
let databaseID: DatabaseID?

public init(databaseID: DatabaseID? = nil) {
init(databaseID: DatabaseID? = nil) {
self.databaseID = databaseID
}

public func createSession(_ data: SessionData, for request: Request) -> EventLoopFuture<SessionID> {
func createSession(_ data: SessionData, for request: Request) -> EventLoopFuture<SessionID> {
let id = self.generateID()
return Session(key: id, data: data)
.create(on: request.db(self.databaseID))
.map { id }
}

public func readSession(_ sessionID: SessionID, for request: Request) -> EventLoopFuture<SessionData?> {
func readSession(_ sessionID: SessionID, for request: Request) -> EventLoopFuture<SessionData?> {
return Session.query(on: request.db(self.databaseID))
.filter(\.$key == sessionID)
.first()
.map { $0?.data }
}

public func updateSession(_ sessionID: SessionID, to data: SessionData, for request: Request) -> EventLoopFuture<SessionID> {
func updateSession(_ sessionID: SessionID, to data: SessionData, for request: Request) -> EventLoopFuture<SessionID> {
return Session.query(on: request.db(self.databaseID))
.filter(\.$key == sessionID)
.set(\.$data, to: data)
.update()
.map { sessionID }
}

public func deleteSession(_ sessionID: SessionID, for request: Request) -> EventLoopFuture<Void> {
func deleteSession(_ sessionID: SessionID, for request: Request) -> EventLoopFuture<Void> {
return Session.query(on: request.db(self.databaseID))
.filter(\.$key == sessionID)
.delete()
Expand All @@ -44,15 +81,13 @@ public struct DatabaseSessions: SessionDriver {
}
}

extension SessionID: Codable {
public init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
try self.init(string: container.decode(String.self))
}

public func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
try container.encode(self.string)
private struct DatabaseSessionAuthenticator<User>: SessionAuthenticator
where User: SessionAuthenticatable, User: Model, User.SessionID == User.IDValue
{
let databaseID: DatabaseID?

func resolve(sessionID: User.SessionID, for request: Request) -> EventLoopFuture<User?> {
User.find(sessionID, on: request.db)
}
}

Expand Down
145 changes: 73 additions & 72 deletions Sources/Fluent/FluentProvider.swift
Original file line number Diff line number Diff line change
@@ -1,83 +1,34 @@
import Vapor

public final class Fluent: Provider {
public let application: Application

let databases: Databases
let migrations: Migrations

public init(_ application: Application) {
self.application = application
self.databases = Databases(threadPool: application.threadPool, on: application.eventLoopGroup)
application.commands.use(MigrateCommand(application: application), as: "migrate")
self.migrations = .init()
}

public func willBoot() throws {
struct Signature: CommandSignature {
@Flag(name: "auto-migrate", help: "If true, Fluent will automatically migrate your database on boot")
var autoMigrate: Bool

@Flag(name: "auto-revert", help: "If true, Fluent will automatically revert your database on boot")
var autoRevert: Bool

init() { }
}

let signature = try Signature(from: &self.application.environment.commandInput)
if signature.autoRevert {
try self.application.migrator.setupIfNeeded().wait()
try self.application.migrator.revertAllBatches().wait()
}
if signature.autoMigrate {
try self.application.migrator.setupIfNeeded().wait()
try self.application.migrator.prepareBatch().wait()
}
}

public func shutdown() {
self.databases.shutdown()
}
}

extension Sessions {
public func use(database id: DatabaseID) {
self.use {
DatabaseSessions(databaseID: id)
}
}
}

extension Request {
public var db: Database {
self.db(nil)
}

public func db(_ id: DatabaseID?) -> Database {
self.application.databases
.database(id, logger: self.logger, on: self.eventLoop)!
}
}


extension Application {
public var db: Database {
self.db(nil)
}

public func db(_ id: DatabaseID?) -> Database {
self.databases
.database(id, logger: self.logger, on: self.eventLoopGroup.next())!
}

public var databases: Databases {
self.fluent.databases
self.fluent.storage.databases
}

public var migrations: Migrations {
self.fluent.migrations
self.fluent.storage.migrations
}

public var migrator: Migrator {
Migrator(
databases: self.databases,
Expand All @@ -86,23 +37,73 @@ extension Application {
on: self.eventLoopGroup.next()
)
}

var fluent: Fluent {
self.providers.require(Fluent.self)
}
}

struct FluentStorage {
let databases: Databases
let migrations: Migrations

init(_ app: Application) {
self.databases = Databases(threadPool: app.threadPool, on: app.eventLoopGroup)
self.migrations = Migrations()
public struct Fluent {
final class Storage {
let databases: Databases
let migrations: Migrations

init(threadPool: NIOThreadPool, on eventLoopGroup: EventLoopGroup) {
self.databases = Databases(
threadPool: threadPool,
on: eventLoopGroup
)
self.migrations = .init()
}
}

struct Key: StorageKey {
typealias Value = Storage
}

struct Lifecycle: LifecycleHandler {
func willBoot(_ application: Application) throws {
struct Signature: CommandSignature {
@Flag(name: "auto-migrate", help: "If true, Fluent will automatically migrate your database on boot")
var autoMigrate: Bool

@Flag(name: "auto-revert", help: "If true, Fluent will automatically revert your database on boot")
var autoRevert: Bool

init() { }
}

let signature = try Signature(from: &application.environment.commandInput)
if signature.autoRevert {
try application.migrator.setupIfNeeded().wait()
try application.migrator.revertAllBatches().wait()
}
if signature.autoMigrate {
try application.migrator.setupIfNeeded().wait()
try application.migrator.prepareBatch().wait()
}
}

func shutdown(_ application: Application) {
application.databases.shutdown()
}
}

let application: Application

var storage: Storage {
if self.application.storage[Key.self] == nil {
self.initialize()
}
return self.application.storage[Key.self]!
}

func initialize() {
self.application.storage[Key.self] = .init(
threadPool: self.application.threadPool,
on: self.application.eventLoopGroup
)
self.application.lifecycle.use(Lifecycle())
self.application.commands.use(MigrateCommand(), as: "migrate")
}
}
func shutdown() {
self.databases.shutdown()

public var fluent: Fluent {
.init(application: self)
}
}

15 changes: 6 additions & 9 deletions Sources/Fluent/MigrateCommand.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,11 @@ public final class MigrateCommand: Command {
return "Prepare or revert your database migrations"
}

let application: Application
init(application: Application) {
self.application = application
}
init() { }

public func run(using context: CommandContext, signature: Signature) throws {
context.console.info("Migrate Command: \(signature.revert ? "Revert" : "Prepare")")
try self.application.migrator.setupIfNeeded().wait()
try context.application.migrator.setupIfNeeded().wait()
if signature.revert {
try self.revert(using: context)
} else {
Expand All @@ -30,7 +27,7 @@ public final class MigrateCommand: Command {
}

private func revert(using context: CommandContext) throws {
let migrations = try self.application.migrator.previewRevertLastBatch().wait()
let migrations = try context.application.migrator.previewRevertLastBatch().wait()
guard migrations.count > 0 else {
context.console.print("No migrations to revert.")
return
Expand All @@ -43,15 +40,15 @@ public final class MigrateCommand: Command {
context.console.print(dbid?.string ?? "default")
}
if context.console.confirm("Would you like to continue?".consoleText(.warning)) {
try self.application.migrator.revertLastBatch().wait()
try context.application.migrator.revertLastBatch().wait()
context.console.print("Migration successful")
} else {
context.console.warning("Migration cancelled")
}
}

private func prepare(using context: CommandContext) throws {
let migrations = try self.application.migrator.previewPrepareBatch().wait()
let migrations = try context.application.migrator.previewPrepareBatch().wait()
guard migrations.count > 0 else {
context.console.print("No new migrations.")
return
Expand All @@ -64,7 +61,7 @@ public final class MigrateCommand: Command {
context.console.print(dbid?.string ?? "default")
}
if context.console.confirm("Would you like to continue?".consoleText(.warning)) {
try self.application.migrator.prepareBatch().wait()
try context.application.migrator.prepareBatch().wait()
context.console.print("Migration successful")
} else {
context.console.warning("Migration cancelled")
Expand Down
7 changes: 3 additions & 4 deletions Tests/FluentTests/FluentTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,7 @@ final class FluentTests: XCTestCase {
func testRepositoryPatternDatabase() throws {
let app = Application(.testing)
defer { app.shutdown() }

app.use(Fluent.self)

app.databases.use(TestDatabaseDriver { query in
XCTAssertEqual(query.schema, "posts")
return [
Expand All @@ -46,8 +45,8 @@ final class FluentTests: XCTestCase {
]
}, as: .test)

app.posts.use {
DatabasePostRepository(database: $0.db(.test))
app.posts.use { req in
DatabasePostRepository(database: req.db(.test))
}

app.get("foo") { req -> EventLoopFuture<[Post]> in
Expand Down

0 comments on commit 5adacb3

Please sign in to comment.