|
@@ -0,0 +1,179 @@
|
|
|
|
+package benchmark;
|
|
|
|
+
|
|
|
|
+import benchmark.model.Fortune;
|
|
|
|
+import benchmark.model.World;
|
|
|
|
+import benchmark.repository.DbFactory;
|
|
|
|
+import benchmark.repository.DbService;
|
|
|
|
+import com.fasterxml.jackson.databind.ObjectMapper;
|
|
|
|
+import com.fasterxml.jackson.jakarta.rs.json.JacksonJsonProvider;
|
|
|
|
+import io.muserver.Method;
|
|
|
|
+import io.muserver.MuResponse;
|
|
|
|
+import io.muserver.MuServerBuilder;
|
|
|
|
+import io.muserver.Mutils;
|
|
|
|
+import io.muserver.rest.RestHandlerBuilder;
|
|
|
|
+import io.pebbletemplates.pebble.PebbleEngine;
|
|
|
|
+import io.pebbletemplates.pebble.template.PebbleTemplate;
|
|
|
|
+import jakarta.ws.rs.GET;
|
|
|
|
+import jakarta.ws.rs.Path;
|
|
|
|
+import jakarta.ws.rs.Produces;
|
|
|
|
+import jakarta.ws.rs.QueryParam;
|
|
|
|
+import jakarta.ws.rs.core.Context;
|
|
|
|
+import org.slf4j.Logger;
|
|
|
|
+import org.slf4j.LoggerFactory;
|
|
|
|
+
|
|
|
|
+import java.io.IOException;
|
|
|
|
+import java.util.List;
|
|
|
|
+import java.util.Map;
|
|
|
|
+
|
|
|
|
+import static jakarta.ws.rs.core.MediaType.*;
|
|
|
|
+
|
|
|
|
+public class TFBBase {
|
|
|
|
+ public static final Logger LOGGER = LoggerFactory.getLogger(TFBBase.class);
|
|
|
|
+ public static PebbleEngine engine = new PebbleEngine.Builder().build();
|
|
|
|
+ public static PebbleTemplate compiledTemplate = engine.getTemplate("templates/fortune.peb");
|
|
|
|
+
|
|
|
|
+ public static MuServerBuilder commonBuilderWithMuHandler() {
|
|
|
|
+ var jackson = new ObjectMapper();
|
|
|
|
+ var dbService = DbFactory.INSTANCE.getDbService(DbFactory.DbType.POSTGRES);
|
|
|
|
+ return MuServerBuilder.httpServer()
|
|
|
|
+ .addHandler((ignore, res) -> {
|
|
|
|
+ res.headers().add("Server", "muserver");
|
|
|
|
+ return false;
|
|
|
|
+ })
|
|
|
|
+ .addHandler(Method.GET, "/plaintext", (req, res, pp) -> {
|
|
|
|
+ var ah = req.handleAsync();
|
|
|
|
+ res.headers().add("content-type", "text/plain");
|
|
|
|
+ ah.write(Mutils.toByteBuffer("Hello, World!"), (optEx) -> ah.complete());
|
|
|
|
+ })
|
|
|
|
+ .addHandler(Method.GET, "/json", (req, res, pp) -> {
|
|
|
|
+ res.headers().add("content-type", "application/json");
|
|
|
|
+ jackson.writeValue(res.writer(), Map.of("message", "Hello, World!"));
|
|
|
|
+ })
|
|
|
|
+ .addHandler(Method.GET, "/db", (req, res, pp) -> {
|
|
|
|
+ res.headers().add("content-type", "application/json");
|
|
|
|
+ jackson.writeValue(res.writer(), dbService.getWorld(1).get(0));
|
|
|
|
+ })
|
|
|
|
+ .addHandler(Method.GET, "/queries", (req, res, pp) -> {
|
|
|
|
+ res.headers().add("content-type", "application/json");
|
|
|
|
+ jackson.writeValue(
|
|
|
|
+ res.writer(),
|
|
|
|
+ dbService.getWorld(getBoundedRowNumber(req.query().get("queries", "")))
|
|
|
|
+ );
|
|
|
|
+ })
|
|
|
|
+ .addHandler(Method.GET, "/fortunes", (req, res, pp) -> {
|
|
|
|
+ res.headers().set("content-type", "text/html;charset=utf-8");
|
|
|
|
+ compiledTemplate.evaluate(
|
|
|
|
+ res.writer(),
|
|
|
|
+ Map.of("fortunes", dbService.getFortune().stream().map(Fortune::toMap).toList()));
|
|
|
|
+ })
|
|
|
|
+ .addHandler(Method.GET, "/updates", (req, res, pp) -> {
|
|
|
|
+ res.headers().add("content-type", "application/json");
|
|
|
|
+ jackson.writeValue(
|
|
|
|
+ res.writer(),
|
|
|
|
+ dbService.updateWorld(getBoundedRowNumber(req.query().get("queries", "")))
|
|
|
|
+ );
|
|
|
|
+ })
|
|
|
|
+ .withInterface("0.0.0.0")
|
|
|
|
+ .withHttpPort(8080)
|
|
|
|
+ .addShutdownHook(true);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public static MuServerBuilder commonBuilderWithRestHandler() {
|
|
|
|
+ return MuServerBuilder.httpServer()
|
|
|
|
+ .addHandler((req, res) -> {
|
|
|
|
+ res.headers().add("Server", "muserver");
|
|
|
|
+ return false;
|
|
|
|
+ })
|
|
|
|
+ .addHandler(RestHandlerBuilder.restHandler(new TFBResource(
|
|
|
|
+ DbFactory.INSTANCE.getDbService(DbFactory.DbType.POSTGRES),
|
|
|
|
+ compiledTemplate
|
|
|
|
+ )).addCustomWriter(new JacksonJsonProvider()))
|
|
|
|
+ .withInterface("0.0.0.0")
|
|
|
|
+ .withHttpPort(8080)
|
|
|
|
+ .addShutdownHook(true);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Path("/rest")
|
|
|
|
+ public static class TFBResource {
|
|
|
|
+ public final DbService dbService;
|
|
|
|
+ public final PebbleTemplate template;
|
|
|
|
+
|
|
|
|
+ public TFBResource(
|
|
|
|
+ DbService dbService,
|
|
|
|
+ PebbleTemplate template
|
|
|
|
+ ) {
|
|
|
|
+ this.dbService = dbService;
|
|
|
|
+ this.template = template;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @GET
|
|
|
|
+ @Path("/plaintext")
|
|
|
|
+ @Produces(TEXT_PLAIN)
|
|
|
|
+ public String plaintext() {
|
|
|
|
+ return "Hello, World!";
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @GET
|
|
|
|
+ @Path("/json")
|
|
|
|
+ @Produces(APPLICATION_JSON)
|
|
|
|
+ public Map<String, String> json() {
|
|
|
|
+ return Map.of("message", "Hello, World!");
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @GET
|
|
|
|
+ @Path("/db")
|
|
|
|
+ @Produces(APPLICATION_JSON)
|
|
|
|
+ public World db() {
|
|
|
|
+ return dbService.getWorld(1).get(0);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @GET
|
|
|
|
+ @Path("/queries")
|
|
|
|
+ @Produces(APPLICATION_JSON)
|
|
|
|
+ public List<World> queries(
|
|
|
|
+ @QueryParam("queries")
|
|
|
|
+ String queries
|
|
|
|
+ ) {
|
|
|
|
+ int num = getBoundedRowNumber(queries);
|
|
|
|
+ return dbService.getWorld(num);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ @GET
|
|
|
|
+ @Path("/fortunes")
|
|
|
|
+ @Produces(TEXT_HTML)
|
|
|
|
+ public void fortunes(
|
|
|
|
+ @Context MuResponse res
|
|
|
|
+ ) throws IOException {
|
|
|
|
+ res.headers().set("content-type", "text/html;charset=utf-8");
|
|
|
|
+ List<Fortune> fortuneList = dbService.getFortune();
|
|
|
|
+ var writer = res.writer();
|
|
|
|
+ // writer will be flushed
|
|
|
|
+ template.evaluate(writer, Map.of("fortunes", fortuneList.stream().map(Fortune::toMap).toList()));
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @GET
|
|
|
|
+ @Path("/updates")
|
|
|
|
+ @Produces(APPLICATION_JSON)
|
|
|
|
+ public List<World> updates(
|
|
|
|
+ @QueryParam("queries")
|
|
|
|
+ String queries
|
|
|
|
+ ) {
|
|
|
|
+ return dbService.updateWorld(getBoundedRowNumber(queries));
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ private static final int MIN_QUERIES = 1;
|
|
|
|
+ private static final int MAX_QUERIES = 500;
|
|
|
|
+
|
|
|
|
+ private static int getBoundedRowNumber(String number) {
|
|
|
|
+ int num;
|
|
|
|
+ try {
|
|
|
|
+ num = Integer.parseInt(number);
|
|
|
|
+ } catch (NumberFormatException e) {
|
|
|
|
+ num = MIN_QUERIES;
|
|
|
|
+ }
|
|
|
|
+ return Math.max(MIN_QUERIES, Math.min(num, MAX_QUERIES));
|
|
|
|
+ }
|
|
|
|
+}
|