diff --git a/Dockerfile b/Dockerfile index 4325f0367345..0df95c628df7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,8 +4,8 @@ ARG DEBIAN_FRONTEND=noninteractive # WARNING: DON'T PUT A SPACE AFTER ANY BACKSLASH OR APT WILL BREAK # One -q produces output suitable for logging (mostly hides # progress indicators) -RUN apt-get -yqq update && \ - apt-get -yqq install \ +RUN apt-get -y update && \ + apt-get -y install \ -o Dpkg::Options::="--force-confdef" \ -o Dpkg::Options::="--force-confold" \ cloc \ diff --git a/frameworks/Swift/vapor/benchmark_config.json b/frameworks/Swift/vapor/benchmark_config.json index 1bd0d8e2242a..dad97c97842e 100755 --- a/frameworks/Swift/vapor/benchmark_config.json +++ b/frameworks/Swift/vapor/benchmark_config.json @@ -93,6 +93,23 @@ "display_name": "Vapor", "notes": "", "versus": "None" + }, + "swifql": { + "plaintext_url": "/plaintext", + "json_url": "/json", + "port": 8080, + "approach": "Realistic", + "classification": "Fullstack", + "framework": "Vapor", + "language": "Swift", + "flavor": "None", + "platform": "None", + "webserver": "None", + "os": "Linux", + "database_os": "Linux", + "display_name": "Vapor", + "notes": "", + "versus": "swift-nio" } }] } diff --git a/frameworks/Swift/vapor/config.toml b/frameworks/Swift/vapor/config.toml index e629702ef665..d71b5d8c7e4c 100644 --- a/frameworks/Swift/vapor/config.toml +++ b/frameworks/Swift/vapor/config.toml @@ -51,3 +51,16 @@ orm = "Micro" platform = "None" webserver = "None" versus = "None" + +[swifql] +urls.plaintext = "/plaintext" +urls.json = "/json" +approach = "Realistic" +classification = "Fullstack" +database = "Postgres" +database_os = "Linux" +os = "Linux" +orm = "Micro" +platform = "None" +webserver = "None" +versus = "None" \ No newline at end of file diff --git a/frameworks/Swift/vapor/vapor-swifql-ikiga/.dockerignore b/frameworks/Swift/vapor/vapor-swifql-ikiga/.dockerignore new file mode 100644 index 000000000000..2d9f16e2d276 --- /dev/null +++ b/frameworks/Swift/vapor/vapor-swifql-ikiga/.dockerignore @@ -0,0 +1,2 @@ +.build/ +.swiftpm/ diff --git a/frameworks/Swift/vapor/vapor-swifql-ikiga/.gitignore b/frameworks/Swift/vapor/vapor-swifql-ikiga/.gitignore new file mode 100644 index 000000000000..920fa825731a --- /dev/null +++ b/frameworks/Swift/vapor/vapor-swifql-ikiga/.gitignore @@ -0,0 +1,12 @@ +Packages +.build +xcuserdata +*.xcodeproj +DerivedData/ +.DS_Store +db.sqlite +.swiftpm +.env +.env.* +! .env.example +.vscode diff --git a/frameworks/Swift/vapor/vapor-swifql-ikiga/Package.swift b/frameworks/Swift/vapor/vapor-swifql-ikiga/Package.swift new file mode 100644 index 000000000000..1672173f5f6d --- /dev/null +++ b/frameworks/Swift/vapor/vapor-swifql-ikiga/Package.swift @@ -0,0 +1,44 @@ +// swift-tools-version:5.10 + +import PackageDescription + +let package = Package( + name: "vapor-swifql-ikiga", + platforms: [ + .macOS(.v13) + ], + products: [ + .executable(name: "app", targets: ["App"]) + ], + dependencies: [ + // 💧 A server-side Swift web framework. + .package(url: "https://github.com/vapor/vapor.git", from: "4.99.3"), + // 🔵 Non-blocking, event-driven networking for Swift. Used for custom executors + .package(url: "https://github.com/apple/swift-nio.git", from: "2.65.0"), + // json encoder/decoder + .package(url: "https://github.com/orlandos-nl/IkigaJSON.git", from: "2.0.0"), + // sql builder + .package(url: "https://github.com/SwifQL/VaporBridges.git", from: "1.0.0-rc"), + .package(url: "https://github.com/SwifQL/PostgresBridge.git", from: "1.0.0-rc"), + ], + targets: [ + .executableTarget( + name: "App", + dependencies: [ + .product(name: "Vapor", package: "vapor"), + .product(name: "NIOCore", package: "swift-nio"), + .product(name: "NIOPosix", package: "swift-nio"), + .product(name: "VaporBridges", package: "VaporBridges"), + .product(name: "PostgresBridge", package: "PostgresBridge"), + .product(name: "IkigaJSON", package: "IkigaJSON") + ], + path: "Sources", + swiftSettings: swiftSettings + ) + ] +) + +var swiftSettings: [SwiftSetting] { [ + .enableUpcomingFeature("DisableOutwardActorInference"), + .enableExperimentalFeature("StrictConcurrency"), +] } diff --git a/frameworks/Swift/vapor/vapor-swifql-ikiga/Sources/Models/Fortune.swift b/frameworks/Swift/vapor/vapor-swifql-ikiga/Sources/Models/Fortune.swift new file mode 100644 index 000000000000..e0ae62f104fe --- /dev/null +++ b/frameworks/Swift/vapor/vapor-swifql-ikiga/Sources/Models/Fortune.swift @@ -0,0 +1,12 @@ +import Bridges + +final class Fortune: Table { + @Column("id") + var id: Int32? + + @Column("message") + var message: String + + init() {} +} + diff --git a/frameworks/Swift/vapor/vapor-swifql-ikiga/Sources/Models/World.swift b/frameworks/Swift/vapor/vapor-swifql-ikiga/Sources/Models/World.swift new file mode 100644 index 000000000000..8fbcdb6a42f3 --- /dev/null +++ b/frameworks/Swift/vapor/vapor-swifql-ikiga/Sources/Models/World.swift @@ -0,0 +1,11 @@ +import Bridges + +final class World: Table { + @Column("id") + var id: Int32? + + @Column("randomnumber") + var randomnumber: Int + + init() {} +} diff --git a/frameworks/Swift/vapor/vapor-swifql-ikiga/Sources/configure.swift b/frameworks/Swift/vapor/vapor-swifql-ikiga/Sources/configure.swift new file mode 100644 index 000000000000..6ce612729be7 --- /dev/null +++ b/frameworks/Swift/vapor/vapor-swifql-ikiga/Sources/configure.swift @@ -0,0 +1,69 @@ +import IkigaJSON +import PostgresBridge +import Vapor +import VaporBridges + + +extension DatabaseHost { + public static var DbHost: DatabaseHost { + return .init( + hostname: "tfb-database", + port: 5432, + username: "benchmarkdbuser", + password: "benchmarkdbpassword", + tlsConfiguration: nil + ) + } +} + +extension DatabaseIdentifier { + public static var Db: DatabaseIdentifier { + .init(name: "hello_world", host: .DbHost) + } +} + + +public func configure(_ app: Application) throws { + var decoder = IkigaJSONDecoder() + decoder.settings.dateDecodingStrategy = .iso8601 + ContentConfiguration.global.use(decoder: decoder as ContentDecoder, for: .json) + + var encoder = IkigaJSONEncoder() + encoder.settings.dateEncodingStrategy = .iso8601 + ContentConfiguration.global.use(encoder: encoder as ContentEncoder, for: .json) + + app.http.server.configuration.serverName = "Vapor" + app.logger.logLevel = .notice + app.logger.notice("💧 VAPOR") + app.logger.notice("System.coreCount: \(System.coreCount)") + + try routes(app) + + try app.run() +} + +public func routes(_ app: Application) throws { + app.get("plaintext") { req async in + "Hello, world!" + } + + app.get("json") { req async in + ["message": "Hello, world!"] + } + + app.get("db") { req throws -> EventLoopFuture in + req.postgres.connection(to: DbHost) { conn throws -> _ in + guard let world = try World + .select + .where(\World.$id == Int.random(in: 1...10_000)) + .execute(on: conn) + .first(decoding: World.self) + else { + throw Abort(.notFound) + } + + return world + } + } + +} diff --git a/frameworks/Swift/vapor/vapor-swifql-ikiga/Sources/json.swift b/frameworks/Swift/vapor/vapor-swifql-ikiga/Sources/json.swift new file mode 100644 index 000000000000..ada57f0c3e34 --- /dev/null +++ b/frameworks/Swift/vapor/vapor-swifql-ikiga/Sources/json.swift @@ -0,0 +1,52 @@ +// Setup custom JSONEncoder/Decoder + +import IkigaJSON +import Vapor + + +extension IkigaJSONEncoder: ContentEncoder { + public func encode( + _ encodable: E, + to body: inout ByteBuffer, + headers: inout HTTPHeaders + ) throws { + headers.contentType = .json + try self.encodeAndWrite(encodable, into: &body) + } + + public func encode(_ encodable: E, to body: inout ByteBuffer, headers: inout HTTPHeaders, userInfo: [CodingUserInfoKey : Sendable]) throws where E : Encodable { + var encoder = self + encoder.userInfo = userInfo + headers.contentType = .json + try encoder.encodeAndWrite(encodable, into: &body) + } + + public func encode(_ encodable: E, to body: inout ByteBuffer, headers: inout HTTPHeaders, userInfo: [CodingUserInfoKey : Any]) throws where E : Encodable { + var encoder = self + encoder.userInfo = userInfo + headers.contentType = .json + try encoder.encodeAndWrite(encodable, into: &body) + } +} + +extension IkigaJSONDecoder: ContentDecoder { + public func decode( + _ decodable: D.Type, + from body: ByteBuffer, + headers: HTTPHeaders + ) throws -> D { + return try self.decode(D.self, from: body) + } + + public func decode(_ decodable: D.Type, from body: ByteBuffer, headers: HTTPHeaders, userInfo: [CodingUserInfoKey : Sendable]) throws -> D where D : Decodable { + let decoder = IkigaJSONDecoder(settings: settings) + decoder.settings.userInfo = userInfo + return try decoder.decode(D.self, from: body) + } + + public func decode(_ decodable: D.Type, from body: ByteBuffer, headers: HTTPHeaders, userInfo: [CodingUserInfoKey : Any]) throws -> D where D : Decodable { + let decoder = IkigaJSONDecoder(settings: settings) + decoder.settings.userInfo = userInfo + return try decoder.decode(D.self, from: body) + } +} diff --git a/frameworks/Swift/vapor/vapor-swifql-ikiga/Sources/main.swift b/frameworks/Swift/vapor/vapor-swifql-ikiga/Sources/main.swift new file mode 100644 index 000000000000..c0f871c5daea --- /dev/null +++ b/frameworks/Swift/vapor/vapor-swifql-ikiga/Sources/main.swift @@ -0,0 +1,12 @@ +import Vapor +import PostgresBridge +import IkigaJSON +import Logging + +var env = try Environment.detect() +try LoggingSystem.bootstrap(from: &env) + +let app = Application(env) +defer { app.shutdown() } + +try configure(app) diff --git a/frameworks/Swift/vapor/vapor-swifql.dockerfile b/frameworks/Swift/vapor/vapor-swifql.dockerfile new file mode 100644 index 000000000000..222cd29ed716 --- /dev/null +++ b/frameworks/Swift/vapor/vapor-swifql.dockerfile @@ -0,0 +1,29 @@ +# ================================ +# Build image +# ================================ +FROM swift:5.10 as build +WORKDIR /build + +# Copy entire repo into container +COPY ./vapor-swifql-ikiga . + +# Compile with optimizations +RUN swift build \ + -c release \ + -Xswiftc -enforce-exclusivity=unchecked + +# ================================ +# Run image +# ================================ +FROM swift:5.10-slim +WORKDIR /run + +# Copy build artifacts +COPY --from=build /build/.build/release /run + +# Copy Swift runtime libraries +COPY --from=build /usr/lib/swift/ /usr/lib/swift/ + +EXPOSE 8080 + +ENTRYPOINT ["./app", "serve", "--env", "production", "--hostname", "0.0.0.0", "--port", "8080"]