Browse Source

Add a version of the vertx-web postgres test that uses the com.github.susom:database library and standard JDBC driver (#2805)

Garrick Olson 8 years ago
parent
commit
cc9695da57

+ 22 - 0
frameworks/Java/vertx-web/benchmark_config.json

@@ -86,6 +86,28 @@
       "display_name": "vertx-webs",
       "notes": "",
       "versus": ""
+    },
+    "database-postgres": {
+      "setup_file": "setup_postgresql",
+      "db_url": "/dbpsql/db",
+      "query_url": "/dbpsql/queries?queries=",
+      "fortune_url": "/dbpsql/fortunes",
+      "update_url": "/dbpsql/update?queries=",
+      "port": 8080,
+      "approach": "Realistic",
+      "classification": "Micro",
+      "database": "Postgres",
+      "framework": "vertx-web",
+      "language": "Java",
+      "flavor": "None",
+      "orm": "Raw",
+      "platform": "vertx",
+      "webserver": "None",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "vertx-webs",
+      "notes": "",
+      "versus": ""
     }
   }]
 }

+ 12 - 0
frameworks/Java/vertx-web/pom.xml

@@ -46,6 +46,18 @@
       <version>${vertx.version}</version>
     </dependency>
 
+    <dependency>
+      <groupId>com.github.susom</groupId>
+      <artifactId>database</artifactId>
+      <version>2.1</version>
+    </dependency>
+
+    <dependency>
+      <groupId>org.postgresql</groupId>
+      <artifactId>postgresql</artifactId>
+      <version>42.1.1</version>
+    </dependency>
+
   </dependencies>
 
   <build>

+ 153 - 0
frameworks/Java/vertx-web/src/main/java/io/vertx/benchmark/App.java

@@ -1,5 +1,11 @@
 package io.vertx.benchmark;
 
+import com.github.susom.database.Config;
+import com.github.susom.database.ConfigFrom;
+import com.github.susom.database.DatabaseProviderVertx;
+import com.github.susom.database.DatabaseProviderVertx.Builder;
+import com.github.susom.database.Sql;
+import com.github.susom.database.SqlInsert;
 import io.vertx.benchmark.model.Fortune;
 import io.vertx.benchmark.model.Message;
 import io.vertx.benchmark.model.World;
@@ -452,6 +458,148 @@ public class App extends AbstractVerticle {
     }
   }
 
+  /**
+   * Implementation using com.github.susom:database library and standard JDBC driver.
+   */
+  private final class DatabaseSql {
+    private final Builder dbBuilder;
+
+    // In order to use a template we first need to create an engine
+    private final HandlebarsTemplateEngine engine;
+
+    DatabaseSql(Vertx vertx, JsonObject jsonConfig) {
+      Config config = ConfigFrom.firstOf().custom(jsonConfig::getString)
+          .rename("username", "database.user")
+          .rename("password", "database.password")
+          .rename("maxPoolSize", "database.pool.size")
+          .value("database.url", "jdbc:postgresql://" + jsonConfig.getString("host") + "/" + jsonConfig.getString("database"))
+          .get();
+      dbBuilder = DatabaseProviderVertx.pooledBuilder(vertx, config);
+      engine = HandlebarsTemplateEngine.create();
+    }
+
+    void dbHandler(final RoutingContext ctx) {
+      dbBuilder.transactAsync(dbs ->
+        dbs.get().toSelect("SELECT id, randomnumber from WORLD where id = ?")
+            .argInteger(Helper.randomWorld())
+            .queryFirstOrNull(row -> new World(row.getIntegerOrZero(), row.getIntegerOrZero()).encode())
+      , call -> {
+        if (call.succeeded()) {
+          if (call.result() == null) {
+            ctx.fail(404);
+          } else {
+            ctx.response()
+                .putHeader(HttpHeaders.SERVER, SERVER)
+                .putHeader(HttpHeaders.DATE, date)
+                .putHeader(HttpHeaders.CONTENT_TYPE, "application/json")
+                .end(call.result());
+          }
+        } else {
+          ctx.fail(call.cause());
+        }
+      });
+    }
+
+    void queriesHandler(final RoutingContext ctx) {
+      int queries = Helper.getQueries(ctx.request());
+
+      dbBuilder.transactAsync(dbs -> {
+        JsonArray worlds = new JsonArray();
+        for (int i = 1; i <= queries; i++) {
+          dbs.get()
+              .toSelect("SELECT id, randomnumber from WORLD where id = ?")
+              .argInteger(Helper.randomWorld())
+              .queryFirstOrNull(row -> worlds.add(new World(row.getIntegerOrZero(), row.getIntegerOrZero())));
+        }
+        return worlds.encode();
+      }, call -> {
+        if (call.succeeded()) {
+          if (call.result() == null) {
+            ctx.fail(404);
+          } else {
+            ctx.response()
+                .putHeader(HttpHeaders.SERVER, SERVER)
+                .putHeader(HttpHeaders.DATE, date)
+                .putHeader(HttpHeaders.CONTENT_TYPE, "application/json")
+                .end(call.result());
+          }
+        } else {
+          ctx.fail(call.cause());
+        }
+      });
+    }
+
+    final void fortunesHandler(final RoutingContext ctx) {
+      dbBuilder.transactAsync(dbs -> {
+        List<Fortune> fortunes = dbs.get()
+            .toSelect("SELECT id, message from FORTUNE")
+            .queryMany(row -> new Fortune(row.getIntegerOrZero(), row.getStringOrEmpty()));
+        fortunes.add(new Fortune(0, "Additional fortune added at request time."));
+        Collections.sort(fortunes);
+        return fortunes;
+      }, call -> {
+        if (call.succeeded()) {
+          if (call.result() == null || call.result().isEmpty()) {
+            ctx.fail(404);
+          } else {
+            ctx.put("fortunes", call.result());
+            engine.render(ctx, "templates/fortunes.hbs", res -> {
+              if (res.succeeded()) {
+                ctx.response()
+                    .putHeader(HttpHeaders.SERVER, SERVER)
+                    .putHeader(HttpHeaders.DATE, date)
+                    .putHeader(HttpHeaders.CONTENT_TYPE, "text/html; charset=UTF-8")
+                    .end(res.result());
+              } else {
+                ctx.fail(res.cause());
+              }
+            });
+          }
+        } else {
+          ctx.fail(call.cause());
+        }
+      });
+    }
+
+    void updateHandler(final RoutingContext ctx) {
+      int queries = Helper.getQueries(ctx.request());
+
+      dbBuilder.transactAsync(dbs -> {
+        JsonArray worlds = new JsonArray();
+        // Haven't implemented batching yet on toUpdate(), so hijack toInsert() as work-around
+        SqlInsert batchUpdate = dbs.get().toInsert("UPDATE WORLD SET randomnumber = ? WHERE id = ?");
+        for (int i = 1; i <= queries; i++) {
+          World oldWorld = dbs.get()
+              .toSelect("SELECT id, randomnumber from WORLD where id = ?")
+              .argInteger(Helper.randomWorld())
+              .queryFirstOrNull(row -> new World(row.getIntegerOrZero(), row.getIntegerOrZero()));
+          if (oldWorld == null) {
+            return null;
+          }
+          World newWorld = new World(oldWorld.getId(), Helper.randomWorld());
+          worlds.add(newWorld);
+          batchUpdate.argInteger(newWorld.getRandomNumber()).argInteger(newWorld.getId()).batch();
+        }
+        batchUpdate.insertBatchUnchecked();
+        return worlds.encode();
+      }, call -> {
+        if (call.succeeded()) {
+          if (call.result() == null) {
+            ctx.fail(404);
+          } else {
+            ctx.response()
+                .putHeader(HttpHeaders.SERVER, SERVER)
+                .putHeader(HttpHeaders.DATE, date)
+                .putHeader(HttpHeaders.CONTENT_TYPE, "application/json")
+                .end(call.result());
+          }
+        } else {
+          ctx.fail(call.cause());
+        }
+      });
+    }
+  }
+
   private static final String SERVER = "vertx-web";
   private String date;
 
@@ -464,6 +612,7 @@ public class App extends AbstractVerticle {
     final MongoDB mongoDB = new MongoDB(vertx, config());
     final AsyncSQL psql = new AsyncSQL(vertx, AsyncSQL.POSTGRES, config());
     final AsyncSQL mysql = new AsyncSQL(vertx, AsyncSQL.MYSQL, config());
+    final DatabaseSql dbpsql = new DatabaseSql(vertx, config());
 
     /**
      * This test exercises the framework fundamentals including keep-alive support, request routing, request header
@@ -484,6 +633,7 @@ public class App extends AbstractVerticle {
     app.get("/mongo/db").handler(mongoDB::dbHandler);
     app.get("/psql/db").handler(psql::dbHandler);
     app.get("/mysql/db").handler(mysql::dbHandler);
+    app.get("/dbpsql/db").handler(dbpsql::dbHandler);
 
     /**
      * This test is a variation of Test #2 and also uses the World table. Multiple rows are fetched to more dramatically
@@ -493,6 +643,7 @@ public class App extends AbstractVerticle {
     app.get("/mongo/queries").handler(mongoDB::queriesHandler);
     app.get("/psql/queries").handler(psql::queriesHandler);
     app.get("/mysql/queries").handler(mysql::queriesHandler);
+    app.get("/dbpsql/queries").handler(dbpsql::queriesHandler);
 
     /**
      * This test exercises the ORM, database connectivity, dynamic-size collections, sorting, server-side templates,
@@ -501,6 +652,7 @@ public class App extends AbstractVerticle {
     app.get("/mongo/fortunes").handler(mongoDB::fortunesHandler);
     app.get("/psql/fortunes").handler(psql::fortunesHandler);
     app.get("/mysql/fortunes").handler(mysql::fortunesHandler);
+    app.get("/dbpsql/fortunes").handler(dbpsql::fortunesHandler);
 
     /**
      * This test is a variation of Test #3 that exercises the ORM's persistence of objects and the database driver's
@@ -510,6 +662,7 @@ public class App extends AbstractVerticle {
     app.route("/mongo/update").handler(mongoDB::updateHandler);
     app.route("/psql/update").handler(psql::updateHandler);
     app.route("/mysql/update").handler(mysql::updateHandler);
+    app.route("/dbpsql/update").handler(dbpsql::updateHandler);
 
     /**
      * This test is an exercise of the request-routing fundamentals only, designed to demonstrate the capacity of