Browse Source

Update to Kitura 2.6 and Swift-Kuery 3.0 (#4354)

* Add KituraNIO variants

* Classify Kitura as full stack, platform KituraNet

* Remove unnecessary permutations

* Update to Swift-Kuery 3.0 and Kitura 2.6

* Use sequential method for multiple queries with Kuery 3.0
David Jones 6 years ago
parent
commit
46550cf03d

+ 5 - 5
frameworks/Swift/kitura/Package.swift

@@ -6,12 +6,12 @@ import PackageDescription
 let package = Package(
 let package = Package(
     name: "Kitura-TechEmpower",
     name: "Kitura-TechEmpower",
     dependencies: [
     dependencies: [
-        .package(url: "https://github.com/IBM-Swift/Kitura.git", .upToNextMinor(from: "2.5.0")),
-        .package(url: "https://github.com/IBM-Swift/LoggerAPI.git", from: "1.7.0"),
-        .package(url: "https://github.com/IBM-Swift/HeliumLogger.git", from: "1.7.0"),
+        .package(url: "https://github.com/IBM-Swift/Kitura.git", .upToNextMinor(from: "2.6.0")),
+        .package(url: "https://github.com/IBM-Swift/LoggerAPI.git", from: "1.8.0"),
+        .package(url: "https://github.com/IBM-Swift/HeliumLogger.git", from: "1.8.0"),
         .package(url: "https://github.com/IBM-Swift/Configuration.git", from: "3.0.0"),
         .package(url: "https://github.com/IBM-Swift/Configuration.git", from: "3.0.0"),
-        .package(url: "https://github.com/IBM-Swift/Swift-Kuery-PostgreSQL.git", from: "1.0.0"),
-        .package(url: "https://github.com/IBM-Swift/Swift-Kuery-ORM.git", from: "0.3.0"),
+        .package(url: "https://github.com/IBM-Swift/Swift-Kuery-PostgreSQL.git", from: "2.0.0"),
+        .package(url: "https://github.com/IBM-Swift/Swift-Kuery-ORM.git", from: "0.4.0"),
         .package(url: "https://github.com/IBM-Swift/Kitura-StencilTemplateEngine.git", from: "1.9.0"),
         .package(url: "https://github.com/IBM-Swift/Kitura-StencilTemplateEngine.git", from: "1.9.0"),
         .package(url: "https://github.com/IBM-Swift/Kitura-MustacheTemplateEngine.git", from: "1.7.2"),
         .package(url: "https://github.com/IBM-Swift/Kitura-MustacheTemplateEngine.git", from: "1.7.2"),
         .package(url: "https://github.com/OpenKitten/MongoKitten.git", from: "4.1.3"),
         .package(url: "https://github.com/OpenKitten/MongoKitten.git", from: "4.1.3"),

+ 1 - 1
frameworks/Swift/kitura/Sources/KueryPostgres/Postgres.swift

@@ -36,7 +36,7 @@ let dbName = manager["db:name"] as? String ?? "hello_world"
 let dbUser = manager["db:user"] as? String ?? "benchmarkdbuser"
 let dbUser = manager["db:user"] as? String ?? "benchmarkdbuser"
 let dbPass = manager["db:password"] as? String ?? "benchmarkdbpass"
 let dbPass = manager["db:password"] as? String ?? "benchmarkdbpass"
 
 
-let dbConnPoolOpts = ConnectionPoolOptions(initialCapacity: 20, maxCapacity: 50, timeout:10000)
+let dbConnPoolOpts = ConnectionPoolOptions(initialCapacity: 20, maxCapacity: 50)
 
 
 public let dbConnPool = PostgreSQLConnection.createPool(host: dbHost, port: dbPort, options: [.databaseName(dbName), .userName(dbUser), .password(dbPass)], poolOptions: dbConnPoolOpts)
 public let dbConnPool = PostgreSQLConnection.createPool(host: dbHost, port: dbPort, options: [.databaseName(dbName), .userName(dbUser), .password(dbPass)], poolOptions: dbConnPoolOpts)
 
 

+ 128 - 50
frameworks/Swift/kitura/Sources/KueryPostgresRaw/PostgresRaw.swift

@@ -55,25 +55,85 @@ var update = Update(world, set: [(world.randomNumber, RandomRow.randomValue)])
 ///
 ///
 public func getFortunes(callback: @escaping ([Fortune]?, AppError?) -> Void) -> Void {
 public func getFortunes(callback: @escaping ([Fortune]?, AppError?) -> Void) -> Void {
     // Get a dedicated connection object for this transaction from the pool
     // Get a dedicated connection object for this transaction from the pool
-    guard let dbConn = dbConnPool.getConnection() else {
-        return callback(nil, AppError.OtherError("Timed out waiting for a DB connection from the pool"))
-    }
-    // Initiate database query
-    let query = Select(from: fortunes)
-    dbConn.execute(query: query) { result in
-        var resultFortunes: [Fortune]? = nil
-        guard let rows = result.asRows, result.success else {
-            return callback(nil, AppError.DBKueryError("Query failed: \(String(describing: result.asError))"))
+    dbConnPool.getConnection { (dbConn, dbConnErr) in
+        guard let dbConn = dbConn else {
+            guard let err = dbConnErr else {
+                return callback(nil, AppError.OtherError("Unknown error getting connection from pool"))
+            }
+            return callback(nil, AppError.OtherError("Error getting connection from pool: \(err)"))
         }
         }
-        do {
-            resultFortunes = try rows.map { try Fortune.init(row: $0) }
-        } catch {
-            return callback(nil, AppError.DataFormatError("\(error)"))
+        // Initiate database query
+        let query = Select(from: fortunes)
+        dbConn.execute(query: query) { result in
+            var resultFortunes: [Fortune] = []
+            // Retrieve all rows from the query result
+            result.asRows {
+                results, err in
+                guard let results = results else {
+                    guard let err = err else {
+                        return callback(nil, AppError.DBKueryError("Query failed, and no error was returned"))
+                    }
+                    return callback(nil, AppError.DBKueryError("Query failed: \(err)"))
+                }
+                do {
+                    // Transform the result rows into an array of Fortune objects
+                    resultFortunes = try results.map { try Fortune.init(row: $0) }
+                } catch {
+                    return callback(nil, AppError.DataFormatError("\(error)"))
+                }
+                // Invoke callback with results
+                callback(resultFortunes, nil)
+            }
         }
         }
-        // Invoke callback with results
-        callback(resultFortunes, nil)
     }
     }
+}
 
 
+/// Alternate implementation of getFortunes that uses ResultSet.forEach to fetch each
+/// database row sequentially, rather than QueryResult.asRows (which produces an array
+/// of rows). The benefit of forEach is that we do not need to hold two copies of the
+/// entire result set in memory.
+///
+/// - Parameter callback: The callback that will be invoked once the DB query
+///                       has completed and results are available, passing an
+///                       optional [Fortune] (on success) or AppError on
+///                       failure.
+///
+public func getFortunes_forEach(callback: @escaping ([Fortune]?, AppError?) -> Void) -> Void {
+    // Get a dedicated connection object for this transaction from the pool
+    dbConnPool.getConnection { (dbConn, dbConnErr) in
+        guard let dbConn = dbConn else {
+            guard let err = dbConnErr else {
+                return callback(nil, AppError.OtherError("Unknown error getting connection from pool"))
+            }
+            return callback(nil, AppError.OtherError("Error getting connection from pool: \(err)"))
+        }
+        // Initiate database query
+        let query = Select(from: fortunes)
+        dbConn.execute(query: query) { result in
+            var resultFortunes: [Fortune] = []
+            guard let results = result.asResultSet else {
+                guard let queryErr = result.asError else {
+                    return callback(nil, AppError.DBKueryError("Expected a result set, but result was \(result)"))
+                }
+                return callback(nil, AppError.DBKueryError("Query failed: \(queryErr)"))
+            }
+            // Build an array of Fortune objects
+            results.forEach { (values, rowErr, next) in
+                guard let values = values else {
+                    // Reached the final row - call back with the results
+                    return callback(resultFortunes, nil)
+                }
+                // Append this Fortune to the list
+                do {
+                    resultFortunes.append(try Fortune(values: values))
+                    // Process the next column
+                    next()
+                } catch {
+                    return callback(nil, AppError.DataFormatError("\(error)"))
+                }
+            }
+        }
+    }
 }
 }
 
 
 /// Get a random row (range 1 to 10,000) from the database.
 /// Get a random row (range 1 to 10,000) from the database.
@@ -85,33 +145,46 @@ public func getFortunes(callback: @escaping ([Fortune]?, AppError?) -> Void) ->
 ///
 ///
 public func getRandomRow_Raw(callback: @escaping (RandomRow?, AppError?) -> Void) -> Void {
 public func getRandomRow_Raw(callback: @escaping (RandomRow?, AppError?) -> Void) -> Void {
     // Get a dedicated connection object for this transaction from the pool
     // Get a dedicated connection object for this transaction from the pool
-    guard let dbConn = dbConnPool.getConnection() else {
-        return callback(nil, AppError.OtherError("Timed out waiting for a DB connection from the pool"))
-    }
-    // Select random row from database range
-    let rnd = RandomRow.randomId
-    let query = Select(world.randomNumber, from: world)
-        .where(world.id == rnd)
-    // Initiate database query
-    dbConn.execute(query: query) { result in
-        var resultRow: RandomRow? = nil
-        guard let resultSet = result.asResultSet, result.success else {
-            return callback(nil, AppError.DBKueryError("Query failed: \(String(describing: result.asError))"))
+    dbConnPool.getConnection { (dbConn, dbConnErr) in
+        guard let dbConn = dbConn else {
+            guard let dbConnErr = dbConnErr else {
+                return callback(nil, AppError.OtherError("Unknown error getting connection from pool"))
+            }
+            return callback(nil, AppError.OtherError("Error getting connection from pool: \(dbConnErr)"))
         }
         }
-            
-        for row in resultSet.rows {
-            for value in row {
-                guard let value = value else {
-                    return callback(nil, AppError.DBKueryError("Error: randomNumber value is nil"))
+        // Select random row from database range
+        let rnd = RandomRow.randomId
+        let query = Select(world.randomNumber, from: world)
+            .where(world.id == rnd)
+        // Initiate database query
+        dbConn.execute(query: query) { result in
+            guard let resultSet = result.asResultSet else {
+                guard let queryErr = result.asError else {
+                    return callback(nil, AppError.DBKueryError("Expected a result set, but result was \(result)"))
                 }
                 }
-                guard let randomNumber = value as? Int32 else {
-                    return callback(nil, AppError.DBKueryError("Error: could not convert \(value) to Int32"))
+                return callback(nil, AppError.DBKueryError("Query failed: \(queryErr)"))
+            }
+            resultSet.nextRow {
+                values, nextErr in
+                guard let values = values else {
+                    guard let nextErr = nextErr else {
+                        return callback(nil, AppError.DBKueryError("Query failed, and no error was returned"))
+                    }
+                    return callback(nil, AppError.DBKueryError("Query failed: \(nextErr)"))
+                }
+                // There should be exactly one value
+                guard values.count == 1 else {
+                    return callback(nil, AppError.DBKueryError("\(values.count) values returned, expected 1, for query '\(query)'"))
+                }
+                // The value should be an Int32
+                guard let randomNumber = values[0] as? Int32 else {
+                    return callback(nil, AppError.DBKueryError("Could not convert \(String(describing: values[0])) to Int32"))
                 }
                 }
-                resultRow = RandomRow(id: rnd, randomNumber: Int(randomNumber))
+                let resultRow = RandomRow(id: rnd, randomNumber: Int(randomNumber))
+                // Invoke callback with results
+                callback(resultRow, nil)
             }
             }
         }
         }
-        // Invoke callback with results
-        callback(resultRow, nil)
     }
     }
 }
 }
 
 
@@ -123,20 +196,25 @@ public func getRandomRow_Raw(callback: @escaping (RandomRow?, AppError?) -> Void
 ///
 ///
 public func updateRow_Raw(id: Int, callback: @escaping (AppError?) -> Void) -> Void {
 public func updateRow_Raw(id: Int, callback: @escaping (AppError?) -> Void) -> Void {
     // Get a dedicated connection object for this transaction from the pool
     // Get a dedicated connection object for this transaction from the pool
-    guard let dbConn = dbConnPool.getConnection() else {
-        return callback(AppError.OtherError("Timed out waiting for a DB connection from the pool"))
-    }
-    // Generate a random number for this row
-    let rndValue = RandomRow.randomValue
-    let query = Update(world, set: [(world.randomNumber, rndValue)])
-        .where(world.id == id)
-    // Initiate database query
-    dbConn.execute(query: query) { result in
-        guard result.success else {
-            return callback(AppError.DBKueryError("Update failed: \(String(describing: result.asError))"))
+    dbConnPool.getConnection { (dbConn, err) in
+        guard let dbConn = dbConn else {
+            guard let err = err else {
+                return callback(AppError.OtherError("Unknown error getting connection from pool"))
+            }
+            return callback(AppError.OtherError("Error getting connection from pool: \(err)"))
+        }
+        // Generate a random number for this row
+        let rndValue = RandomRow.randomValue
+        let query = Update(world, set: [(world.randomNumber, rndValue)])
+            .where(world.id == id)
+        // Initiate database query
+        dbConn.execute(query: query) { result in
+            guard result.success else {
+                return callback(AppError.DBKueryError("Update failed: \(String(describing: result.asError))"))
+            }
+            // Invoke callback once done
+            callback(nil)
         }
         }
-        // Invoke callback once done
-        callback(nil)
     }
     }
 }
 }
 
 

+ 24 - 1
frameworks/Swift/kitura/Sources/TechEmpowerCommon/Fortune.swift

@@ -30,7 +30,7 @@ public struct Fortune: Codable {
     }
     }
 
 
     /// Create a Fortune instance from a [String: Any?] dictionary,
     /// Create a Fortune instance from a [String: Any?] dictionary,
-    /// such as that retrieved by Kuery.
+    /// such as that retrieved by Kuery using `QueryResult.asRows()`.
     ///
     ///
     /// - Parameter row: A dictionary representing the fields of a
     /// - Parameter row: A dictionary representing the fields of a
     ///                  Fortune database row.
     ///                  Fortune database row.
@@ -52,6 +52,29 @@ public struct Fortune: Codable {
         self.init(id: Int(id), message: message)
         self.init(id: Int(id), message: message)
     }
     }
 
 
+    /// Create a Fortune instance from an [Any?] array, such as that retrieved
+    /// by Kuery using `ResultSet.forEach()`.
+    ///
+    /// - Parameter row: An array representing the fields of a Fortune
+    ///                  database row.
+    /// - throws: if the fields and types contained in the array do not match
+    ///           those expected.
+    public init(values: [Any?]) throws {
+        // There should be two columns
+        guard values.count == 2 else {
+            throw AppError.DBKueryError("Expected 2 values but found \(values.count)")
+        }
+        // First should be an Int32
+        guard let id = values[0] as? Int32 else {
+            throw AppError.DataFormatError("Fortune id '\(String(describing: values[0]))' is not an Int")
+        }
+        // Second should be a String
+        guard let msg = values[1] as? String else {
+            throw AppError.DataFormatError("Fortune message '\(String(describing: values[1]))' is not a String")
+        }
+        self.init(id: Int(id), message: msg)
+    }
+
 }
 }
 
 
 extension Fortune: Comparable {
 extension Fortune: Comparable {

+ 61 - 55
frameworks/Swift/kitura/benchmark_config.json

@@ -6,12 +6,12 @@
       "plaintext_url": "/plaintext",
       "plaintext_url": "/plaintext",
       "port": 8080,
       "port": 8080,
       "approach": "Realistic",
       "approach": "Realistic",
-      "classification": "Micro",
+      "classification": "Fullstack",
       "database": "none",
       "database": "none",
       "framework": "Kitura",
       "framework": "Kitura",
       "language": "Swift",
       "language": "Swift",
       "orm": "none",
       "orm": "none",
-      "platform": "Kitura",
+      "platform": "KituraNet",
       "webserver": "Kitura",
       "webserver": "Kitura",
       "os": "Linux",
       "os": "Linux",
       "database_os": "Linux",
       "database_os": "Linux",
@@ -20,17 +20,17 @@
     },
     },
     "postgres": {
     "postgres": {
       "db_url": "/db",
       "db_url": "/db",
-      "query_url": "/queriesParallel?queries=",
+      "query_url": "/queries?queries=",
       "fortune_url": "/fortunes",
       "fortune_url": "/fortunes",
-      "update_url": "/updatesParallel?queries=",
+      "update_url": "/updates?queries=",
       "port": 8080,
       "port": 8080,
       "approach": "Realistic",
       "approach": "Realistic",
-      "classification": "Micro",
+      "classification": "Fullstack",
       "database": "Postgres",
       "database": "Postgres",
       "framework": "Kitura",
       "framework": "Kitura",
       "language": "Swift",
       "language": "Swift",
       "orm": "Raw",
       "orm": "Raw",
-      "platform": "Kitura",
+      "platform": "KituraNet",
       "webserver": "Kitura",
       "webserver": "Kitura",
       "os": "Linux",
       "os": "Linux",
       "database_os": "Linux",
       "database_os": "Linux",
@@ -39,17 +39,15 @@
     },
     },
     "postgres-orm": {
     "postgres-orm": {
       "db_url": "/db",
       "db_url": "/db",
-      "query_url": "/queriesParallel?queries=",
       "fortune_url": "/fortunes",
       "fortune_url": "/fortunes",
-      "update_url": "/updatesParallel?queries=",
       "port": 8080,
       "port": 8080,
       "approach": "Realistic",
       "approach": "Realistic",
-      "classification": "Micro",
+      "classification": "Fullstack",
       "database": "Postgres",
       "database": "Postgres",
       "framework": "Kitura",
       "framework": "Kitura",
       "language": "Swift",
       "language": "Swift",
       "orm": "Full",
       "orm": "Full",
-      "platform": "Kitura",
+      "platform": "KituraNet",
       "webserver": "Kitura",
       "webserver": "Kitura",
       "os": "Linux",
       "os": "Linux",
       "database_os": "Linux",
       "database_os": "Linux",
@@ -58,17 +56,16 @@
     },
     },
     "postgres-orm-codable": {
     "postgres-orm-codable": {
       "db_url": "/db",
       "db_url": "/db",
-      "query_url": "/queriesParallel?queries=",
-      "fortune_url": "/fortunes",
-      "update_url": "/updatesParallel?queries=",
+      "query_url": "/queries?queries=",
+      "update_url": "/updates?queries=",
       "port": 8080,
       "port": 8080,
       "approach": "Realistic",
       "approach": "Realistic",
-      "classification": "Micro",
+      "classification": "Fullstack",
       "database": "Postgres",
       "database": "Postgres",
       "framework": "Kitura",
       "framework": "Kitura",
       "language": "Swift",
       "language": "Swift",
       "orm": "Full",
       "orm": "Full",
-      "platform": "Kitura",
+      "platform": "KituraNet",
       "webserver": "Kitura",
       "webserver": "Kitura",
       "os": "Linux",
       "os": "Linux",
       "database_os": "Linux",
       "database_os": "Linux",
@@ -82,12 +79,12 @@
       "update_url": "/updates?queries=",
       "update_url": "/updates?queries=",
       "port": 8080,
       "port": 8080,
       "approach": "Realistic",
       "approach": "Realistic",
-      "classification": "Micro",
+      "classification": "Fullstack",
       "database": "MongoDB",
       "database": "MongoDB",
       "framework": "Kitura",
       "framework": "Kitura",
       "language": "Swift",
       "language": "Swift",
       "orm": "Raw",
       "orm": "Raw",
-      "platform": "Kitura",
+      "platform": "KituraNet",
       "webserver": "Kitura",
       "webserver": "Kitura",
       "os": "Linux",
       "os": "Linux",
       "database_os": "Linux",
       "database_os": "Linux",
@@ -99,12 +96,29 @@
       "plaintext_url": "/plaintext",
       "plaintext_url": "/plaintext",
       "port": 8080,
       "port": 8080,
       "approach": "Realistic",
       "approach": "Realistic",
-      "classification": "Micro",
+      "classification": "Fullstack",
       "database": "none",
       "database": "none",
       "framework": "Kitura",
       "framework": "Kitura",
       "language": "Swift",
       "language": "Swift",
       "orm": "none",
       "orm": "none",
-      "platform": "Kitura",
+      "platform": "KituraNet",
+      "webserver": "Kitura",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "Kitura",
+      "notes": ""
+    },
+    "nio": {
+      "json_url": "/json",
+      "plaintext_url": "/plaintext",
+      "port": 8080,
+      "approach": "Realistic",
+      "classification": "Fullstack",
+      "database": "none",
+      "framework": "Kitura",
+      "language": "Swift",
+      "orm": "none",
+      "platform": "KituraNIO",
       "webserver": "Kitura",
       "webserver": "Kitura",
       "os": "Linux",
       "os": "Linux",
       "database_os": "Linux",
       "database_os": "Linux",
@@ -113,110 +127,102 @@
     },
     },
     "gcd-postgres": {
     "gcd-postgres": {
       "db_url": "/db",
       "db_url": "/db",
-      "query_url": "/queriesParallel?queries=",
       "fortune_url": "/fortunes",
       "fortune_url": "/fortunes",
-      "update_url": "/updatesParallel?queries=",
       "port": 8080,
       "port": 8080,
       "approach": "Realistic",
       "approach": "Realistic",
-      "classification": "Micro",
+      "classification": "Fullstack",
       "database": "Postgres",
       "database": "Postgres",
       "framework": "Kitura",
       "framework": "Kitura",
       "language": "Swift",
       "language": "Swift",
       "orm": "Raw",
       "orm": "Raw",
-      "platform": "Kitura",
+      "platform": "KituraNet",
       "webserver": "Kitura",
       "webserver": "Kitura",
       "os": "Linux",
       "os": "Linux",
       "database_os": "Linux",
       "database_os": "Linux",
       "display_name": "Kitura",
       "display_name": "Kitura",
       "notes": ""
       "notes": ""
     },
     },
-    "gcd-postgres-orm": {
+    "nio-postgres": {
       "db_url": "/db",
       "db_url": "/db",
-      "query_url": "/queriesParallel?queries=",
+      "query_url": "/queries?queries=",
       "fortune_url": "/fortunes",
       "fortune_url": "/fortunes",
-      "update_url": "/updatesParallel?queries=",
+      "update_url": "/updates?queries=",
       "port": 8080,
       "port": 8080,
       "approach": "Realistic",
       "approach": "Realistic",
-      "classification": "Micro",
+      "classification": "Fullstack",
       "database": "Postgres",
       "database": "Postgres",
       "framework": "Kitura",
       "framework": "Kitura",
       "language": "Swift",
       "language": "Swift",
-      "orm": "Full",
-      "platform": "Kitura",
+      "orm": "Raw",
+      "platform": "KituraNIO",
       "webserver": "Kitura",
       "webserver": "Kitura",
       "os": "Linux",
       "os": "Linux",
       "database_os": "Linux",
       "database_os": "Linux",
       "display_name": "Kitura",
       "display_name": "Kitura",
       "notes": ""
       "notes": ""
     },
     },
-    "gcd-postgres-orm-codable": {
+    "gcd-postgres-orm": {
       "db_url": "/db",
       "db_url": "/db",
-      "query_url": "/queriesParallel?queries=",
       "fortune_url": "/fortunes",
       "fortune_url": "/fortunes",
-      "update_url": "/updatesParallel?queries=",
       "port": 8080,
       "port": 8080,
       "approach": "Realistic",
       "approach": "Realistic",
-      "classification": "Micro",
+      "classification": "Fullstack",
       "database": "Postgres",
       "database": "Postgres",
       "framework": "Kitura",
       "framework": "Kitura",
       "language": "Swift",
       "language": "Swift",
       "orm": "Full",
       "orm": "Full",
-      "platform": "Kitura",
+      "platform": "KituraNet",
       "webserver": "Kitura",
       "webserver": "Kitura",
       "os": "Linux",
       "os": "Linux",
       "database_os": "Linux",
       "database_os": "Linux",
       "display_name": "Kitura",
       "display_name": "Kitura",
       "notes": ""
       "notes": ""
     },
     },
-    "gcd-mongodb": {
+    "nio-postgres-orm": {
       "db_url": "/db",
       "db_url": "/db",
-      "query_url": "/queries?queries=",
       "fortune_url": "/fortunes",
       "fortune_url": "/fortunes",
-      "update_url": "/updates?queries=",
       "port": 8080,
       "port": 8080,
       "approach": "Realistic",
       "approach": "Realistic",
-      "classification": "Micro",
-      "database": "MongoDB",
+      "classification": "Fullstack",
+      "database": "Postgres",
       "framework": "Kitura",
       "framework": "Kitura",
       "language": "Swift",
       "language": "Swift",
-      "orm": "Raw",
-      "platform": "Kitura",
+      "orm": "Full",
+      "platform": "KituraNIO",
       "webserver": "Kitura",
       "webserver": "Kitura",
       "os": "Linux",
       "os": "Linux",
       "database_os": "Linux",
       "database_os": "Linux",
       "display_name": "Kitura",
       "display_name": "Kitura",
       "notes": ""
       "notes": ""
     },
     },
-    "nio": {
-      "json_url": "/json",
-      "plaintext_url": "/plaintext",
+    "gcd-postgres-orm-codable": {
+      "db_url": "/db",
       "port": 8080,
       "port": 8080,
       "approach": "Realistic",
       "approach": "Realistic",
-      "classification": "Micro",
-      "database": "none",
+      "classification": "Fullstack",
+      "database": "Postgres",
       "framework": "Kitura",
       "framework": "Kitura",
       "language": "Swift",
       "language": "Swift",
-      "orm": "none",
-      "platform": "Kitura",
+      "orm": "Full",
+      "platform": "KituraNet",
       "webserver": "Kitura",
       "webserver": "Kitura",
       "os": "Linux",
       "os": "Linux",
       "database_os": "Linux",
       "database_os": "Linux",
       "display_name": "Kitura",
       "display_name": "Kitura",
       "notes": ""
       "notes": ""
     },
     },
-    "nio-postgres": {
+    "nio-postgres-orm-codable": {
       "db_url": "/db",
       "db_url": "/db",
-      "query_url": "/queriesParallel?queries=",
-      "fortune_url": "/fortunes",
-      "update_url": "/updatesParallel?queries=",
+      "query_url": "/queries?queries=",
+      "update_url": "/updates?queries=",
       "port": 8080,
       "port": 8080,
       "approach": "Realistic",
       "approach": "Realistic",
-      "classification": "Micro",
+      "classification": "Fullstack",
       "database": "Postgres",
       "database": "Postgres",
       "framework": "Kitura",
       "framework": "Kitura",
       "language": "Swift",
       "language": "Swift",
-      "orm": "Raw",
-      "platform": "Kitura",
+      "orm": "Full",
+      "platform": "KituraNIO",
       "webserver": "Kitura",
       "webserver": "Kitura",
       "os": "Linux",
       "os": "Linux",
       "database_os": "Linux",
       "database_os": "Linux",

+ 8 - 0
frameworks/Swift/kitura/kitura-nio-postgres-orm-codable.dockerfile

@@ -0,0 +1,8 @@
+FROM swift:4.1
+
+ADD ./ /kitura
+WORKDIR /kitura
+RUN apt update -yqq && apt install -yqq libpq-dev
+ENV KITURA_NIO=1
+RUN swift build -c release
+CMD .build/release/TechEmpowerPostgresORMCodable

+ 3 - 2
frameworks/Swift/kitura/kitura-gcd-mongodb.dockerfile → frameworks/Swift/kitura/kitura-nio-postgres-orm.dockerfile

@@ -3,5 +3,6 @@ FROM swift:4.1
 ADD ./ /kitura
 ADD ./ /kitura
 WORKDIR /kitura
 WORKDIR /kitura
 RUN apt update -yqq && apt install -yqq libpq-dev
 RUN apt update -yqq && apt install -yqq libpq-dev
-RUN swift build -c release -Xswiftc -DGCD_ASYNCH
-CMD .build/release/TechEmpowerMongoKitten
+ENV KITURA_NIO=1
+RUN swift build -c release
+CMD .build/release/TechEmpowerPostgresORM