Browse Source

Swift Vapor mongo support (#6947)

* Vapor mongo support

* Vapor mongo using official driver

* Vapor mongo using official driver
Dragos Varovici 3 years ago
parent
commit
a95a312c79

+ 37 - 0
frameworks/Swift/vapor/benchmark_config.json

@@ -74,6 +74,43 @@
       "display_name": "Vapor",
       "display_name": "Vapor",
       "notes": "",
       "notes": "",
       "versus": "None"
       "versus": "None"
+    },
+    "mongo-fluent": {
+      "db_url": "/db",
+      "query_url": "/queries?queries=",
+      "port": 8080,
+      "approach": "Realistic",
+      "classification": "Fullstack",
+      "database": "MongoDb",
+      "framework": "Vapor",
+      "language": "Swift",
+      "flavor": "None",
+      "orm": "Full",
+      "platform": "None",
+      "webserver": "None",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "Vapor",
+      "notes": "",
+      "versus": "None"
+    },
+    "mongo": {
+      "db_url": "/db",
+      "port": 8080,
+      "approach": "Realistic",
+      "classification": "Fullstack",
+      "database": "MongoDb",
+      "framework": "Vapor",
+      "language": "Swift",
+      "flavor": "None",
+      "orm": "Raw",
+      "platform": "None",
+      "webserver": "None",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "Vapor",
+      "notes": "",
+      "versus": "None"
     }
     }
   }]
   }]
 }
 }

+ 29 - 0
frameworks/Swift/vapor/vapor-mongo-fluent.dockerfile

@@ -0,0 +1,29 @@
+# ================================
+# Build image
+# ================================
+FROM swift:5.5 as build
+WORKDIR /build
+
+# Copy entire repo into container
+COPY ./vapor-mongo-fluent .
+
+# Compile with optimizations
+RUN swift build \
+	-c release \
+	-Xswiftc -enforce-exclusivity=unchecked
+
+# ================================
+# Run image
+# ================================
+FROM swift:5.5-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"]

+ 214 - 0
frameworks/Swift/vapor/vapor-mongo-fluent/Package.resolved

@@ -0,0 +1,214 @@
+{
+  "object": {
+    "pins": [
+      {
+        "package": "async-http-client",
+        "repositoryURL": "https://github.com/swift-server/async-http-client.git",
+        "state": {
+          "branch": null,
+          "revision": "170fd536f931c0bffb58f37a53fc238e77f42258",
+          "version": "1.6.4"
+        }
+      },
+      {
+        "package": "async-kit",
+        "repositoryURL": "https://github.com/vapor/async-kit.git",
+        "state": {
+          "branch": null,
+          "revision": "748c026f4dc93c0b9d05fe43a07d3922ca126744",
+          "version": "1.10.0"
+        }
+      },
+      {
+        "package": "BSON",
+        "repositoryURL": "https://github.com/OpenKitten/BSON.git",
+        "state": {
+          "branch": null,
+          "revision": "98a2c90988895f1b985ed0066180995df995924c",
+          "version": "7.0.28"
+        }
+      },
+      {
+        "package": "console-kit",
+        "repositoryURL": "https://github.com/vapor/console-kit.git",
+        "state": {
+          "branch": null,
+          "revision": "75ea3b627d88221440b878e5dfccc73fd06842ed",
+          "version": "4.2.7"
+        }
+      },
+      {
+        "package": "fluent",
+        "repositoryURL": "https://github.com/vapor/fluent.git",
+        "state": {
+          "branch": null,
+          "revision": "ea707ee318066a073c95b2b2df1aa640fcb67f9e",
+          "version": "4.4.0"
+        }
+      },
+      {
+        "package": "fluent-kit",
+        "repositoryURL": "https://github.com/vapor/fluent-kit.git",
+        "state": {
+          "branch": null,
+          "revision": "9fbef6bad614e0b1bf3083f629b40574c97ab0b9",
+          "version": "1.16.0"
+        }
+      },
+      {
+        "package": "fluent-mongo-driver",
+        "repositoryURL": "https://github.com/vapor/fluent-mongo-driver.git",
+        "state": {
+          "branch": null,
+          "revision": "ce519013f51439773fe668d6575888665b0e2dda",
+          "version": "1.0.2"
+        }
+      },
+      {
+        "package": "MongoKitten",
+        "repositoryURL": "https://github.com/orlandos-nl/MongoKitten.git",
+        "state": {
+          "branch": null,
+          "revision": "311b793a4d3d3462ea4c569acbcd5366d1528dc8",
+          "version": "6.7.1"
+        }
+      },
+      {
+        "package": "multipart-kit",
+        "repositoryURL": "https://github.com/vapor/multipart-kit.git",
+        "state": {
+          "branch": null,
+          "revision": "2dd9368a3c9580792b77c7ef364f3735909d9996",
+          "version": "4.5.1"
+        }
+      },
+      {
+        "package": "DNSClient",
+        "repositoryURL": "https://github.com/OpenKitten/NioDNS.git",
+        "state": {
+          "branch": null,
+          "revision": "7517b774d48833f04869fcde668d2f338fadc464",
+          "version": "2.0.6"
+        }
+      },
+      {
+        "package": "routing-kit",
+        "repositoryURL": "https://github.com/vapor/routing-kit.git",
+        "state": {
+          "branch": null,
+          "revision": "a0801a36a6ad501d5ad6285cbcd4774de6b0a734",
+          "version": "4.3.0"
+        }
+      },
+      {
+        "package": "sql-kit",
+        "repositoryURL": "https://github.com/vapor/sql-kit.git",
+        "state": {
+          "branch": null,
+          "revision": "8587674e7e2499fd2017840973f416182025b02d",
+          "version": "3.12.1"
+        }
+      },
+      {
+        "package": "swift-backtrace",
+        "repositoryURL": "https://github.com/swift-server/swift-backtrace.git",
+        "state": {
+          "branch": null,
+          "revision": "d3e04a9d4b3833363fb6192065b763310b156d54",
+          "version": "1.3.1"
+        }
+      },
+      {
+        "package": "swift-crypto",
+        "repositoryURL": "https://github.com/apple/swift-crypto.git",
+        "state": {
+          "branch": null,
+          "revision": "9b5ef28601a9c745c9cdb54d3f243e28ac830982",
+          "version": "2.0.1"
+        }
+      },
+      {
+        "package": "swift-log",
+        "repositoryURL": "https://github.com/apple/swift-log.git",
+        "state": {
+          "branch": null,
+          "revision": "5d66f7ba25daf4f94100e7022febf3c75e37a6c7",
+          "version": "1.4.2"
+        }
+      },
+      {
+        "package": "swift-metrics",
+        "repositoryURL": "https://github.com/apple/swift-metrics.git",
+        "state": {
+          "branch": null,
+          "revision": "3edd2f57afc4e68e23c3e4956bc8b65ca6b5b2ff",
+          "version": "2.2.0"
+        }
+      },
+      {
+        "package": "swift-nio",
+        "repositoryURL": "https://github.com/apple/swift-nio.git",
+        "state": {
+          "branch": null,
+          "revision": "addf69cfe60376c325397c8926589415576b1dd1",
+          "version": "2.34.0"
+        }
+      },
+      {
+        "package": "swift-nio-extras",
+        "repositoryURL": "https://github.com/apple/swift-nio-extras.git",
+        "state": {
+          "branch": null,
+          "revision": "f73ca5ee9c6806800243f1ac415fcf82de9a4c91",
+          "version": "1.10.2"
+        }
+      },
+      {
+        "package": "swift-nio-http2",
+        "repositoryURL": "https://github.com/apple/swift-nio-http2.git",
+        "state": {
+          "branch": null,
+          "revision": "326f7f9a8c8c8402e3691adac04911cac9f9d87f",
+          "version": "1.18.4"
+        }
+      },
+      {
+        "package": "swift-nio-ssl",
+        "repositoryURL": "https://github.com/apple/swift-nio-ssl.git",
+        "state": {
+          "branch": null,
+          "revision": "36f6419f2b1b6490a8c0faa840298e28027cefe9",
+          "version": "2.16.3"
+        }
+      },
+      {
+        "package": "swift-nio-transport-services",
+        "repositoryURL": "https://github.com/apple/swift-nio-transport-services.git",
+        "state": {
+          "branch": null,
+          "revision": "e7f5278a26442dc46783ba7e063643d524e414a0",
+          "version": "1.11.3"
+        }
+      },
+      {
+        "package": "vapor",
+        "repositoryURL": "https://github.com/vapor/vapor.git",
+        "state": {
+          "branch": null,
+          "revision": "80750314e0d9ae11b3886df7f43f495b0661d2dc",
+          "version": "4.52.2"
+        }
+      },
+      {
+        "package": "websocket-kit",
+        "repositoryURL": "https://github.com/vapor/websocket-kit.git",
+        "state": {
+          "branch": null,
+          "revision": "b1c4df8f6c848c2e977726903bbe6578eed723ad",
+          "version": "2.2.0"
+        }
+      }
+    ]
+  },
+  "version": 1
+}

+ 29 - 0
frameworks/Swift/vapor/vapor-mongo-fluent/Package.swift

@@ -0,0 +1,29 @@
+// swift-tools-version:5.5
+import PackageDescription
+
+let package = Package(
+    name: "vapor-fluent",
+    platforms: [
+        .macOS(.v12)
+    ],
+    products: [
+        .executable(name: "app", targets: ["App"])
+    ],
+    dependencies: [
+        .package(url: "https://github.com/vapor/vapor.git", from: "4.52.2"),
+        .package(url: "https://github.com/vapor/fluent.git", from: "4.4.0"),
+        .package(url: "https://github.com/vapor/fluent-mongo-driver.git", from: "1.0.2"),
+        .package(url: "https://github.com/orlandos-nl/MongoKitten.git", from: "6.7.1")
+    ],
+    targets: [
+        .executableTarget(
+            name: "App",
+            dependencies: [
+                .product(name: "Fluent", package: "fluent"),
+                .product(name: "FluentMongoDriver", package: "fluent-mongo-driver"),
+                .product(name: "Vapor", package: "vapor"),
+                .product(name: "MongoKitten", package: "MongoKitten"),
+            ],
+            path: "Sources"),
+    ]
+)

+ 25 - 0
frameworks/Swift/vapor/vapor-mongo-fluent/Sources/Utilities.swift

@@ -0,0 +1,25 @@
+import Vapor
+
+extension Int {
+    func bounded(to range: ClosedRange<Int>) -> Int {
+        switch self {
+        case ...range.lowerBound:
+            return range.lowerBound
+        case range.upperBound...:
+            return range.upperBound
+        default:
+            return self
+        }
+    }
+}
+
+extension System {
+    // tfb-server (aka, citrine) uses 28 hyper-threaded cores
+    // postgresql.conf specifies max_connections = 2000
+    //
+    // 2000 / (28 * 2) = 35.7 (theoretical max)
+    //
+    // https://github.com/TechEmpower/FrameworkBenchmarks/wiki/Project-Information-Environment#citrine-self-hosted
+    // https://github.com/TechEmpower/FrameworkBenchmarks/blob/master/toolset/databases/postgres/postgresql.conf#L64
+    static var maxConnectionsPerEventLoop: Int { 32 }
+}

+ 14 - 0
frameworks/Swift/vapor/vapor-mongo-fluent/Sources/World.swift

@@ -0,0 +1,14 @@
+import Fluent
+import Vapor
+
+final class World: Model, Content {
+    static let schema = "world"
+
+    @ID(custom: "id")
+    var id: Float?
+
+    @Field(key: "randomNumber")
+    var randomNumber: Float
+
+    init() { }
+}

+ 52 - 0
frameworks/Swift/vapor/vapor-mongo-fluent/Sources/main.swift

@@ -0,0 +1,52 @@
+import Fluent
+import FluentMongoDriver
+import Vapor
+
+var env = try Environment.detect()
+try LoggingSystem.bootstrap(from: &env)
+
+let connectionString = "mongodb://tfb-database:27017/hello_world"
+
+let app = Application(env)
+
+app.http.server.configuration.serverName = "Vapor"
+
+app.logger.notice("💧 VAPOR")
+app.logger.notice("System.coreCount: \(System.coreCount)")
+app.logger.notice("System.maxConnectionsPerEventLoop: \(System.maxConnectionsPerEventLoop)")
+
+try app.databases.use(.mongo(
+    connectionString: connectionString),
+    as: .mongo)
+
+app.get("db") { req async throws -> World in
+    guard let world = try await World.find(Float(.random(in: 1...10_000)), on: req.db) else {
+        throw Abort(.notFound)
+    }
+
+    return world
+}
+
+app.get("queries") { req async throws -> [World] in
+    let queries = (req.query["queries"] ?? 1).bounded(to: 1...500)
+
+    var worlds: [World] = []
+
+    for _ in queries {
+        guard let world = try await World.find(Float(.random(in: 1...10_000)), on: req.db) else {
+            throw Abort(.notFound)
+        }
+
+        worlds.append(world)
+    }
+
+    return worlds
+}
+
+extension Int: Sequence {
+    public func makeIterator() -> CountableRange<Int>.Iterator {
+        return (0..<self).makeIterator()
+    }
+}
+
+try app.run()

+ 35 - 0
frameworks/Swift/vapor/vapor-mongo.dockerfile

@@ -0,0 +1,35 @@
+# ================================
+# Build image
+# ================================
+FROM swift:5.5 as build
+WORKDIR /build
+
+# Copy entire repo into container
+COPY ./vapor-mongo .
+
+RUN apt update
+RUN apt-get -yqq install libssl-dev
+
+# Compile with optimizations
+RUN swift build \
+	-c release \
+	-Xswiftc -enforce-exclusivity=unchecked
+
+# ================================
+# Run image
+# ================================
+FROM swift:5.5-slim
+WORKDIR /run
+
+RUN apt update
+RUN apt-get -yqq install libssl-dev
+
+# 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"]

+ 196 - 0
frameworks/Swift/vapor/vapor-mongo/Package.resolved

@@ -0,0 +1,196 @@
+{
+  "object": {
+    "pins": [
+      {
+        "package": "async-http-client",
+        "repositoryURL": "https://github.com/swift-server/async-http-client.git",
+        "state": {
+          "branch": null,
+          "revision": "170fd536f931c0bffb58f37a53fc238e77f42258",
+          "version": "1.6.4"
+        }
+      },
+      {
+        "package": "async-kit",
+        "repositoryURL": "https://github.com/vapor/async-kit.git",
+        "state": {
+          "branch": null,
+          "revision": "748c026f4dc93c0b9d05fe43a07d3922ca126744",
+          "version": "1.10.0"
+        }
+      },
+      {
+        "package": "console-kit",
+        "repositoryURL": "https://github.com/vapor/console-kit.git",
+        "state": {
+          "branch": null,
+          "revision": "75ea3b627d88221440b878e5dfccc73fd06842ed",
+          "version": "4.2.7"
+        }
+      },
+      {
+        "package": "mongo-swift-driver",
+        "repositoryURL": "https://github.com/mongodb/mongo-swift-driver",
+        "state": {
+          "branch": null,
+          "revision": "bc61d4a743519babd9e93acbbc9404d8eb92f61b",
+          "version": "1.2.0"
+        }
+      },
+      {
+        "package": "mongodb-vapor",
+        "repositoryURL": "https://github.com/mongodb/mongodb-vapor",
+        "state": {
+          "branch": null,
+          "revision": "046a7e00332a83a5eec01d9237179ba0f4ef912a",
+          "version": "1.0.0"
+        }
+      },
+      {
+        "package": "multipart-kit",
+        "repositoryURL": "https://github.com/vapor/multipart-kit.git",
+        "state": {
+          "branch": null,
+          "revision": "2dd9368a3c9580792b77c7ef364f3735909d9996",
+          "version": "4.5.1"
+        }
+      },
+      {
+        "package": "Nimble",
+        "repositoryURL": "https://github.com/Quick/Nimble.git",
+        "state": {
+          "branch": null,
+          "revision": "7a46a5fc86cb917f69e3daf79fcb045283d8f008",
+          "version": "8.1.2"
+        }
+      },
+      {
+        "package": "routing-kit",
+        "repositoryURL": "https://github.com/vapor/routing-kit.git",
+        "state": {
+          "branch": null,
+          "revision": "a0801a36a6ad501d5ad6285cbcd4774de6b0a734",
+          "version": "4.3.0"
+        }
+      },
+      {
+        "package": "swift-backtrace",
+        "repositoryURL": "https://github.com/swift-server/swift-backtrace.git",
+        "state": {
+          "branch": null,
+          "revision": "d3e04a9d4b3833363fb6192065b763310b156d54",
+          "version": "1.3.1"
+        }
+      },
+      {
+        "package": "swift-bson",
+        "repositoryURL": "https://github.com/mongodb/swift-bson",
+        "state": {
+          "branch": null,
+          "revision": "711690b4703ca9f3891591c1012b462aedefef14",
+          "version": "3.0.2"
+        }
+      },
+      {
+        "package": "swift-crypto",
+        "repositoryURL": "https://github.com/apple/swift-crypto.git",
+        "state": {
+          "branch": null,
+          "revision": "9b5ef28601a9c745c9cdb54d3f243e28ac830982",
+          "version": "2.0.1"
+        }
+      },
+      {
+        "package": "swift-extras-base64",
+        "repositoryURL": "https://github.com/swift-extras/swift-extras-base64",
+        "state": {
+          "branch": null,
+          "revision": "778e00dd7cc2b7970742f061cffc87dd570e6bfa",
+          "version": "0.5.0"
+        }
+      },
+      {
+        "package": "swift-extras-json",
+        "repositoryURL": "https://github.com/swift-extras/swift-extras-json",
+        "state": {
+          "branch": null,
+          "revision": "122b9454ef01bf89a4c190b8fd3717ddd0a2fbd0",
+          "version": "0.6.0"
+        }
+      },
+      {
+        "package": "swift-log",
+        "repositoryURL": "https://github.com/apple/swift-log.git",
+        "state": {
+          "branch": null,
+          "revision": "5d66f7ba25daf4f94100e7022febf3c75e37a6c7",
+          "version": "1.4.2"
+        }
+      },
+      {
+        "package": "swift-metrics",
+        "repositoryURL": "https://github.com/apple/swift-metrics.git",
+        "state": {
+          "branch": null,
+          "revision": "3edd2f57afc4e68e23c3e4956bc8b65ca6b5b2ff",
+          "version": "2.2.0"
+        }
+      },
+      {
+        "package": "swift-nio-extras",
+        "repositoryURL": "https://github.com/apple/swift-nio-extras.git",
+        "state": {
+          "branch": null,
+          "revision": "f73ca5ee9c6806800243f1ac415fcf82de9a4c91",
+          "version": "1.10.2"
+        }
+      },
+      {
+        "package": "swift-nio-http2",
+        "repositoryURL": "https://github.com/apple/swift-nio-http2.git",
+        "state": {
+          "branch": null,
+          "revision": "326f7f9a8c8c8402e3691adac04911cac9f9d87f",
+          "version": "1.18.4"
+        }
+      },
+      {
+        "package": "swift-nio-ssl",
+        "repositoryURL": "https://github.com/apple/swift-nio-ssl.git",
+        "state": {
+          "branch": null,
+          "revision": "36f6419f2b1b6490a8c0faa840298e28027cefe9",
+          "version": "2.16.3"
+        }
+      },
+      {
+        "package": "swift-nio-transport-services",
+        "repositoryURL": "https://github.com/apple/swift-nio-transport-services.git",
+        "state": {
+          "branch": null,
+          "revision": "e7f5278a26442dc46783ba7e063643d524e414a0",
+          "version": "1.11.3"
+        }
+      },
+      {
+        "package": "vapor",
+        "repositoryURL": "https://github.com/vapor/vapor.git",
+        "state": {
+          "branch": null,
+          "revision": "80750314e0d9ae11b3886df7f43f495b0661d2dc",
+          "version": "4.52.2"
+        }
+      },
+      {
+        "package": "websocket-kit",
+        "repositoryURL": "https://github.com/vapor/websocket-kit.git",
+        "state": {
+          "branch": null,
+          "revision": "b1c4df8f6c848c2e977726903bbe6578eed723ad",
+          "version": "2.2.0"
+        }
+      }
+    ]
+  },
+  "version": 1
+}

+ 27 - 0
frameworks/Swift/vapor/vapor-mongo/Package.swift

@@ -0,0 +1,27 @@
+// swift-tools-version:5.5
+import PackageDescription
+
+let package = Package(
+    name: "vapor-fluent",
+    platforms: [
+        .macOS(.v12)
+    ],
+    products: [
+        .executable(name: "app", targets: ["App"])
+    ],
+    dependencies: [
+        .package(url: "https://github.com/vapor/vapor.git", from: "4.52.2"),
+        .package(url: "https://github.com/mongodb/mongodb-vapor", from: "1.0.0"),
+        .package(url: "https://github.com/mongodb/mongo-swift-driver", from: "1.1.0")
+    ],
+    targets: [
+        .executableTarget(
+            name: "App",
+            dependencies: [
+                .product(name: "MongoSwift", package: "mongo-swift-driver"),
+                .product(name: "MongoDBVapor", package: "mongodb-vapor"),
+                .product(name: "Vapor", package: "vapor"),
+            ],
+            path: "Sources"),
+    ]
+)

+ 26 - 0
frameworks/Swift/vapor/vapor-mongo/Sources/Utilities.swift

@@ -0,0 +1,26 @@
+import Vapor
+
+extension Int {
+    func bounded(to range: ClosedRange<Int>) -> Int {
+        switch self {
+        case ...range.lowerBound:
+            return range.lowerBound
+        case range.upperBound...:
+            return range.upperBound
+        default:
+            return self
+        }
+    }
+}
+
+
+extension System {
+    // tfb-server (aka, citrine) uses 28 hyper-threaded cores
+    // postgresql.conf specifies max_connections = 2000
+    //
+    // 2000 / (28 * 2) = 35.7 (theoretical max)
+    //
+    // https://github.com/TechEmpower/FrameworkBenchmarks/wiki/Project-Information-Environment#citrine-self-hosted
+    // https://github.com/TechEmpower/FrameworkBenchmarks/blob/master/toolset/databases/postgres/postgresql.conf#L64
+    static var maxConnectionsPerEventLoop: Int { 32 }
+}

+ 8 - 0
frameworks/Swift/vapor/vapor-mongo/Sources/World.swift

@@ -0,0 +1,8 @@
+import MongoDBVapor
+import Vapor
+
+struct World: Content {
+    var id: Float
+
+    var randomNumber: Float
+}

+ 64 - 0
frameworks/Swift/vapor/vapor-mongo/Sources/main.swift

@@ -0,0 +1,64 @@
+import MongoDBVapor
+import MongoSwift
+import Vapor
+
+var env = try Environment.detect()
+try LoggingSystem.bootstrap(from: &env)
+
+let app = Application(env)
+
+defer {
+    // Cleanup the application's MongoDB data.
+    app.mongoDB.cleanup()
+    // Clean up the driver's global state. The driver will no longer be usable from this program after this method is
+    // called.
+    cleanupMongoSwift()
+
+    app.shutdown()
+}
+
+ContentConfiguration.global.use(encoder: ExtendedJSONEncoder(), for: .json)
+ContentConfiguration.global.use(decoder: ExtendedJSONDecoder(), for: .json)
+
+app.http.server.configuration.serverName = "Vapor"
+
+app.logger.notice("💧 VAPOR mongo")
+app.logger.notice("System.coreCount: \(System.coreCount)")
+app.logger.notice("System.maxConnectionsPerEventLoop: \(System.maxConnectionsPerEventLoop)")
+
+let options: MongoClientOptions = MongoClientOptions(maxPoolSize: 56, threadPoolSize: System.maxConnectionsPerEventLoop)
+
+try app.mongoDB.configure("mongodb://tfb-database:27017", options: options)
+
+extension Request {
+    var worldCollection: MongoCollection<World> {
+        self.mongoDB.client.db("hello_world").collection("world", withType: World.self)
+    }
+}
+
+app.get("db") { req -> EventLoopFuture<World> in
+    let queryId = Int32.random(in: 1...10_000)
+    let query: BSONDocument = ["id": .double(Double(queryId))]
+
+    return req.worldCollection.findOne(query)
+        .unwrap(or: Abort(.notFound))
+}
+
+app.get("queries") { req -> EventLoopFuture<[World]> in
+    let queries = (req.query["queries"] ?? 1).bounded(to: 1...500)
+    return (0 ..< queries).map { _ -> EventLoopFuture<World> in
+        let queryId = Int32.random(in: 1...10_000)
+        let query: BSONDocument = ["id": .double(Double(queryId))]
+
+        return req.worldCollection.findOne(query)
+            .unwrap(or: Abort(.notFound))
+    }.flatten(on: req.eventLoop)
+}
+
+extension Int: Sequence {
+    public func makeIterator() -> CountableRange<Int>.Iterator {
+        return (0..<self).makeIterator()
+    }
+}
+
+try app.run()