profile
viewpoint
Tanner tanner0101 @vapor NYC tanner.xyz Software engineer and creator of the Vapor web framework.

kylebrowning/APNSwift 368

An HTTP/2 APNS library built on swift-nio

swift-server/swift-service-lifecycle 202

Cleanly startup and shutdown server application, freeing resources in order before exiting.

swift-server/swift-backtrace 197

💥 Backtraces for Swift on Linux

stormpath/Turnstile 161

An authentication framework for Swift.

MrLotU/SwiftPrometheus 51

Client side Prometheus library in Swift

Mordil/RediStack 45

Non-blocking, event-driven Swift client for Redis.

tanner0101/activity-bar 37

iOS 7 style progress bar for showing ogoing activity

ketzusaka/Hummingbird 13

Simple Socket library in Swift

ketzusaka/Strand 13

A simple Swift pthread wrapper

issue openedswift-server/swift-service-lifecycle

Swift Metrics is included in the Package but is never used

Is there a plan to use it at some point?

created time in 4 hours

pull request commentvapor/sql-kit

Resurrect support for Codables with nullable fields

@danramteke The PR could read a bit more like release notes, like:

When a type conforms to `Codable`, its nullable fields will now be encoded as null, which will correctly map to nullable fields in the database table (#122, fixes #121).

Otherwise it still looks OK to me 🙂

danramteke

comment created time in 9 hours

Pull request review commentvapor/redis

Support for Multiple Redis instances

+import Vapor++extension Application {+    private struct RedisStorageKey: StorageKey {+        typealias Value = RedisStorage+    }+    var redisStorage: RedisStorage {+        if self.storage[RedisStorageKey.self] == nil {+            let redisStorage = RedisStorage()+            self.storage[RedisStorageKey.self] = redisStorage+            self.lifecycle.use(RedisStorage.Lifecycle(redisStorage: redisStorage))+        }+        return self.storage[RedisStorageKey.self]!+    }+}++class RedisStorage {+    private var lock: Lock+    private var configurations: [RedisID: RedisConfiguration]+    fileprivate var pools: [PoolKey: RedisConnectionPool] {+        willSet {+            guard pools.isEmpty else {+                fatalError("editing pools after application has booted is not supported")+            }+        }+    }++    init() {+        self.configurations = [:]+        self.pools = [:]+        self.lock = .init()+    }++    func use(_ redisConfiguration: RedisConfiguration, as id: RedisID = .default) {+        self.configurations[id] = redisConfiguration+    }++    func configuration(for id: RedisID = .default) -> RedisConfiguration? {+        self.configurations[id]+    }++    func ids() -> Set<RedisID> {+        Set(self.configurations.keys)+    }++    func pool(for eventLoop: EventLoop, id redisID: RedisID) -> RedisConnectionPool {+        let key = PoolKey(eventLoopKey: eventLoop.key, redisID: redisID)+        guard let pool = pools[key] else {+            fatalError("No redis found for id \(redisID), or the app may not have finished booting. Also, the eventLoop must be from Application's EventLoopGroup.")+        }+        return pool+    }+++}++extension RedisStorage {+    /// Lifecyle Handler for Redis Storage. On boot, it creates a RedisConnectionPool for each+    /// configurated `RedisID` on each `EventLoop`.+    class Lifecycle: LifecycleHandler {
    final class Lifecycle: LifecycleHandler {
danramteke

comment created time in 10 hours

Pull request review commentvapor/redis

Support for Multiple Redis instances

+import Vapor++extension Application {+    private struct RedisStorageKey: StorageKey {+        typealias Value = RedisStorage+    }+    var redisStorage: RedisStorage {+        if self.storage[RedisStorageKey.self] == nil {+            let redisStorage = RedisStorage()+            self.storage[RedisStorageKey.self] = redisStorage+            self.lifecycle.use(RedisStorage.Lifecycle(redisStorage: redisStorage))+        }+        return self.storage[RedisStorageKey.self]!+    }+}++class RedisStorage {
final class RedisStorage {
danramteke

comment created time in 10 hours

Pull request review commentvapor/redis

Support for Multiple Redis instances

+import Foundation+import Redis+import Vapor+import Logging+import XCTVapor++fileprivate extension RedisID {+    static let one: RedisID = "one"+    static let two: RedisID = "two"+}++class MultipleRedisTests: XCTestCase {++    var redisConfig: RedisConfiguration!+    var redisConfig2: RedisConfiguration!++    override func setUpWithError() throws {+        try super.setUpWithError()++        redisConfig  = try RedisConfiguration(hostname: Environment.get("REDIS_HOSTNAME")    ?? "localhost",+                                              port:     Environment.get("REDIS_PORT")?.int   ?? 6379)+        redisConfig2 = try RedisConfiguration(hostname: Environment.get("REDIS_HOSTNAME_2")  ?? "localhost",+                                              port:     Environment.get("REDIS_PORT_2")?.int ?? 6380)

please follow Vapor style, see also my comment in RedisTests.swift

danramteke

comment created time in 10 hours

Pull request review commentvapor/redis

Support for Multiple Redis instances

+import Foundation+import Redis+import Vapor+import Logging+import XCTVapor++fileprivate extension RedisID {+    static let one: RedisID = "one"+    static let two: RedisID = "two"+}++class MultipleRedisTests: XCTestCase {++    var redisConfig: RedisConfiguration!+    var redisConfig2: RedisConfiguration!++    override func setUpWithError() throws {+        try super.setUpWithError()++        redisConfig  = try RedisConfiguration(hostname: Environment.get("REDIS_HOSTNAME")    ?? "localhost",+                                              port:     Environment.get("REDIS_PORT")?.int   ?? 6379)+        redisConfig2 = try RedisConfiguration(hostname: Environment.get("REDIS_HOSTNAME_2")  ?? "localhost",+                                              port:     Environment.get("REDIS_PORT_2")?.int ?? 6380)+    }++    func testApplicationRedis() throws {+        let app = Application()+        defer { app.shutdown() }++        app.redis(.one).configuration = redisConfig+        app.redis(.two).configuration = redisConfig2++        try app.boot()++        let info1 = try app.redis(.one).send(command: "INFO").wait()+        XCTAssertContains(info1.string, "redis_version")++        let info2 = try app.redis(.two).send(command: "INFO").wait()+        XCTAssertContains(info2.string, "redis_version")+    }++    +

newlines

danramteke

comment created time in 10 hours

Pull request review commentvapor/redis

Support for Multiple Redis instances

+import Foundation+import Redis+import Vapor+import Logging+import XCTVapor++fileprivate extension RedisID {+    static let one: RedisID = "one"+    static let two: RedisID = "two"+}++class MultipleRedisTests: XCTestCase {++    var redisConfig: RedisConfiguration!+    var redisConfig2: RedisConfiguration!++    override func setUpWithError() throws {+        try super.setUpWithError()++        redisConfig  = try RedisConfiguration(hostname: Environment.get("REDIS_HOSTNAME")    ?? "localhost",+                                              port:     Environment.get("REDIS_PORT")?.int   ?? 6379)+        redisConfig2 = try RedisConfiguration(hostname: Environment.get("REDIS_HOSTNAME_2")  ?? "localhost",+                                              port:     Environment.get("REDIS_PORT_2")?.int ?? 6380)+    }++    func testApplicationRedis() throws {+        let app = Application()+        defer { app.shutdown() }++        app.redis(.one).configuration = redisConfig+        app.redis(.two).configuration = redisConfig2++        try app.boot()++        let info1 = try app.redis(.one).send(command: "INFO").wait()+        XCTAssertContains(info1.string, "redis_version")++        let info2 = try app.redis(.two).send(command: "INFO").wait()+        XCTAssertContains(info2.string, "redis_version")+    }++    ++    func testSetAndGet() throws {+        let app = Application()+        defer { app.shutdown() }++        app.redis(.one).configuration = redisConfig+        app.redis(.two).configuration = redisConfig2++        app.get("test1") { req in+            req.redis(.one).get("name").map {+                $0.description+            }+        }+        app.get("test2") { req in+            req.redis(.two).get("name").map {+                $0.description+            }+        }++        try app.boot()++        try app.redis(.one).set("name", to: "redis1").wait()+        try app.redis(.two).set("name", to: "redis2").wait()++        try app.test(.GET, "test1") { res in+            XCTAssertContains(res.body.string, "redis1")+        }++        try app.test(.GET, "test2") { res in+            XCTAssertContains(res.body.string, "redis2")+        }++

newline

danramteke

comment created time in 10 hours

Pull request review commentvapor/redis

Support for Multiple Redis instances

+import Vapor++extension Application.Redis {+    /// The Redis configuration to use to communicate with a Redis instance.+    ///+    /// See `Application.Redis.id`+    public var configuration: RedisConfiguration? {+        get {+            self.application.redisStorage.configuration(for: self.id)+        }+        nonmutating set {+            guard let newConfig = newValue else {+                fatalError("editing pools after application has booted is not supported")

is this message correct? It seems to be copied from RedisStorage.swift

danramteke

comment created time in 10 hours

Pull request review commentvapor/redis

Support for Multiple Redis instances

+import Vapor++extension Application {+    private struct RedisStorageKey: StorageKey {+        typealias Value = RedisStorage+    }+    var redisStorage: RedisStorage {+        if self.storage[RedisStorageKey.self] == nil {+            let redisStorage = RedisStorage()+            self.storage[RedisStorageKey.self] = redisStorage+            self.lifecycle.use(RedisStorage.Lifecycle(redisStorage: redisStorage))+        }+        return self.storage[RedisStorageKey.self]!+    }+}++class RedisStorage {+    private var lock: Lock+    private var configurations: [RedisID: RedisConfiguration]+    fileprivate var pools: [PoolKey: RedisConnectionPool] {+        willSet {+            guard pools.isEmpty else {+                fatalError("editing pools after application has booted is not supported")+            }+        }+    }++    init() {+        self.configurations = [:]+        self.pools = [:]+        self.lock = .init()+    }++    func use(_ redisConfiguration: RedisConfiguration, as id: RedisID = .default) {+        self.configurations[id] = redisConfiguration+    }++    func configuration(for id: RedisID = .default) -> RedisConfiguration? {+        self.configurations[id]+    }++    func ids() -> Set<RedisID> {+        Set(self.configurations.keys)+    }++    func pool(for eventLoop: EventLoop, id redisID: RedisID) -> RedisConnectionPool {+        let key = PoolKey(eventLoopKey: eventLoop.key, redisID: redisID)+        guard let pool = pools[key] else {+            fatalError("No redis found for id \(redisID), or the app may not have finished booting. Also, the eventLoop must be from Application's EventLoopGroup.")+        }+        return pool+    }++

redundant newlines

danramteke

comment created time in 10 hours

Pull request review commentvapor/redis

Support for Multiple Redis instances

 import Vapor import Logging import XCTVapor +extension String {+    var int: Int? { Int(self) }+}+ class RedisTests: XCTestCase {+    var redisConfig: RedisConfiguration!++    override func setUpWithError() throws {+        try super.setUpWithError()+        redisConfig = try RedisConfiguration(hostname: Environment.get("REDIS_HOSTNAME") ?? "localhost",+                                             port:     Environment.get("REDIS_PORT")?.int ?? 6379)
        redisConfig = try RedisConfiguration(
            hostname: Environment.get("REDIS_HOSTNAME") ?? "localhost",
            port: Environment.get("REDIS_PORT")?.int ?? 6379
        )
danramteke

comment created time in 10 hours

Pull request review commentvapor/redis

Support for Multiple Redis instances

+import Vapor++extension Application {+    private struct RedisStorageKey: StorageKey {+        typealias Value = RedisStorage+    }+    var redisStorage: RedisStorage {+        if self.storage[RedisStorageKey.self] == nil {+            let redisStorage = RedisStorage()+            self.storage[RedisStorageKey.self] = redisStorage+            self.lifecycle.use(RedisStorage.Lifecycle(redisStorage: redisStorage))+        }+        return self.storage[RedisStorageKey.self]!

Please avoid ! by rewriting using guard.

danramteke

comment created time in 10 hours

pull request commentvapor/multipart-kit

BUG FIX: Multipart/form-data crashed if data was missing

I'll try to add those later today, thanks for pointing out!

JaapWijnen

comment created time in 11 hours

issue closedvapor/toolbox

Build Toolbox on Centos7 fail

I succeed install swift-release-5.3.2 on my centOS 7, while I continued to install toolbox, there had been error.

here is the error message:

git -C /root/toolbox/.build/repositories/mustache-d8034efc remote update -p output: Unknown option: -C usage: git [--version] [--help] [-c name=value] [--exec-path[=<path>]] [--html-path] [--man-path] [--info-path] [-p|--paginate|--no-pager] [--no-replace-objects] [--bare] [--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>] <command> [<args>]

Fatal error: Error raised at top level: build.ShellError(terminationStatus: 1): file Swift/ErrorType.swift, line 200 Current stack trace: 0 libswiftCore.so 0x00007f1a4b7a2a20 swift_reportError + 50 1 libswiftCore.so 0x00007f1a4b813810 swift_stdlib_reportFatalErrorInFile + 115 2 libswiftCore.so 0x00007f1a4b4fb9f5 <unavailable> + 1399285 3 libswiftCore.so 0x00007f1a4b4fb637 <unavailable> + 1398327 4 libswiftCore.so 0x00007f1a4b4fbbd2 <unavailable> + 1399762 5 libswiftCore.so 0x00007f1a4b4fa070 assertionFailure(::file:line:flags:) + 517 6 libswiftCore.so 0x00007f1a4b563786 <unavailable> + 1824646 7 build 0x000056158fb4618b <unavailable> + 8587 8 libc.so.6 0x00007f1a4a272460 __libc_start_main + 245 9 build 0x000056158fb45eb9 <unavailable> + 7865 make: *** [build] 非法指令 make: *** 正在删除文件“build”

I got no idea to work it out, could you help me ?

closed time in 18 hours

foxstudiohua

issue commentvapor/toolbox

Build Toolbox on Centos7 fail

What command is triggering that? It's likely to be caused by SwiftPM requiring the -C flag which was introduced in Git 1.18. Try updating your version of Git

Thank you very much ! Updating git to latest version resolve my issues. BTW, the commands triggered issues were following:

foxstudiohua

comment created time in 18 hours

pull request commentvapor/sql-kit

Resurrect support for Codables with nullable fields

@siemensikkema @gwynne any updates? Fwiw, I've been using this in prod without issues.

danramteke

comment created time in 20 hours

push eventraywenderlich/vpr-materials

Richard Critz

commit sha ab044457819f66db49ceec10001116213a3c0993

Style Guide compliance

view details

Richard Critz

commit sha ac4c45e7cda465da06450ae0413a0345a520c502

Fix logout

view details

push time in 21 hours

issue commentvapor/toolbox

Build Toolbox on Centos7 fail

What command is triggering that? It's likely to be caused by SwiftPM requiring the -C flag which was introduced in Git 1.18. Try updating your version of Git

foxstudiohua

comment created time in a day

issue commentvapor/vapor

How to run Vapor on macOS App ?

This looks like an Xcode/network or proxy issue. Can you clone the repo from the command line?

CloseServer

comment created time in a day

push eventvapor/docs

Hailong

commit sha c5713dc869a58deb66064ebbe736a53ca312ad67

Fix the table name in foreign key sample code. (#586)

view details

push time in a day

PR merged vapor/docs

Fix the table name in foreign key sample code.

<!-- 🚀 Thank you for contributing! -->

<!-- Describe your changes clearly and use examples if possible. --> The correct table name should be stars according to the context. <!-- When this PR is merged, the title and body will be --> <!-- used to generate a release automatically. -->

+2 -2

0 comment

1 changed file

Hailong

pr closed time in a day

push eventvapor/docs

Hailong

commit sha e787fe6ca404af1a46bdd39a386252fe18fdc1fe

Replace create() with update() in migration. (#587)

view details

push time in a day

PR merged vapor/docs

Replace create() with update() in migration.

<!-- 🚀 Thank you for contributing! -->

<!-- Describe your changes clearly and use examples if possible. --> This migration needs to use update() <!-- When this PR is merged, the title and body will be --> <!-- used to generate a release automatically. -->

+1 -1

0 comment

1 changed file

Hailong

pr closed time in a day

push eventvapor/docs

Hailong

commit sha ded3416ca9aa981c81dded1f52636640ec4a9168

Remove extraneous argument label for sort() method. (#588)

view details

push time in a day

PR merged vapor/docs

Remove extraneous argument label for sort() method.

<!-- 🚀 Thank you for contributing! -->

<!-- Describe your changes clearly and use examples if possible. --> Remove the extraneous argument label by. <!-- When this PR is merged, the title and body will be --> <!-- used to generate a release automatically. -->

+1 -1

0 comment

1 changed file

Hailong

pr closed time in a day

issue openedvapor/vapor

How to run Vapor on macOS App ?

I want to go through the Mac OS app package.swift To add vapor, but Zong always fails. Is there any other good solution?

image

created time in a day

delete branch raywenderlich/vpr-materials

delete branch : making-simple-web-app-part-2

delete time in 2 days

push eventraywenderlich/vpr-materials

Tim

commit sha ac8bc186e20b6992cdaeef647def5ca51e93507c

Update starter project

view details

Tim

commit sha ede4b99a0a26b7f6cf8796323e93372ae4abe6c7

Update final project

view details

Richard Critz

commit sha 9997803f1352627d3345c5eaffcd3dac437caa11

Style Guide compliance

view details

Darren Ferguson

commit sha 88452277fa01645316b375c957853e203c6cf55f

Ch17 final pass edit

view details

Darren Ferguson

commit sha 7ac2e4ca078652a6fc6081564a6b303bfd77705b

Merge pull request #4 from raywenderlich/making-simple-web-app-part-2 Making A Simple Web App Part 2

view details

push time in 2 days

push eventraywenderlich/vpr-materials

Darren Ferguson

commit sha 88452277fa01645316b375c957853e203c6cf55f

Ch17 final pass edit

view details

push time in 2 days

delete branch raywenderlich/vpr-materials

delete branch : making-simple-web-app

delete time in 2 days

more