Browse Source

New JS framework ChubbaJS (#5351)

* chubbajs

* babel compile for production

* turn on multi process

* add fortune test
Nate 5 năm trước cách đây
mục cha
commit
968971a960

+ 10 - 0
frameworks/JavaScript/chubbajs/.babelrc

@@ -0,0 +1,10 @@
+{
+  "plugins": [
+    ["@babel/plugin-proposal-decorators", {
+      "legacy": true
+    }],
+    ["@babel/plugin-proposal-class-properties", {
+      "loose": true
+    }]
+  ]
+}

+ 25 - 0
frameworks/JavaScript/chubbajs/README.md

@@ -0,0 +1,25 @@
+# [ChubbaJS](https://github.com/nbrady-techempower/chubbajs) Benchmarking Test
+
+This is the [ChubbaJS](https://github.com/nbrady-techempower/chubbajs) portion of a [benchmarking test suite](../) comparing a variety of web development platforms.
+
+## Test URLs
+
+### Plaintext Test
+
+http://localhost:8080/plaintext
+
+### JSON Encoding Test
+
+http://localhost:8080/json
+
+### DB Test
+
+http://localhost:8080/db
+
+### Query Test
+
+http://localhost:8080/query?queries=2
+
+### Update Test
+
+http://localhost:8080/update?queries=2

+ 26 - 0
frameworks/JavaScript/chubbajs/benchmark_config.json

@@ -0,0 +1,26 @@
+{
+  "framework": "chubbajs",
+  "tests": [{
+    "default": {
+      "plaintext_url": "/plaintext",
+      "json_url": "/json",
+      "db_url": "/db",
+      "query_url": "/query?queries=",
+      "update_url": "/update?queries=",
+      "fortune_url": "/fortune",
+      "port": 8080,
+      "approach": "Realistic",
+      "classification": "Micro",
+      "database": "Postgres",
+      "framework": "chubbajs",
+      "language": "JavaScript",
+      "flavor": "NodeJS",
+      "orm": "Micro",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "chubbajs",
+      "notes": "",
+      "versus": "express"
+    }
+  }]
+}

+ 17 - 0
frameworks/JavaScript/chubbajs/chubbajs.dockerfile

@@ -0,0 +1,17 @@
+FROM node:12.3.1-slim
+
+ENV NODE_ENV production
+
+RUN apt-get update -yqq
+RUN apt-get install -yqq git
+
+COPY ./package.json ./package.json
+
+RUN npm install
+
+COPY ./server ./server
+COPY ./.babelrc ./.babelrc
+
+RUN npm run build
+
+CMD ["npm", "run", "start:prod"]

+ 21 - 0
frameworks/JavaScript/chubbajs/package.json

@@ -0,0 +1,21 @@
+{
+  "name": "chubbajs",
+  "version": "0.1.0",
+  "description": "A chunky js framework",
+  "main": "index.js",
+  "scripts": {
+    "start:prod": "node ./build/index.js",
+    "build": "babel -d ./build ./server -s"
+  },
+  "author": "[email protected]",
+  "dependencies": {
+    "chubbajs": "https://github.com/nbrady-techempower/chubbajs#94b5d91",
+    "@babel/cli": "7.7.7",
+    "@babel/core": "7.7.7",
+    "@babel/node": "7.7.7",
+    "@babel/plugin-proposal-decorators": "7.7.4",
+    "@babel/plugin-proposal-class-properties": "7.7.4",
+    "regenerator-runtime": "0.13.3",
+    "html-entities": "1.2.1"
+  }
+}

+ 14 - 0
frameworks/JavaScript/chubbajs/server/config/config.production.js

@@ -0,0 +1,14 @@
+module.exports = {
+  port: 8080,
+  projectRoot: "/build",
+  database: {
+    engine: "postgres",
+    host: "TFB-database",
+    user: "benchmarkdbuser",
+    password: "benchmarkdbpass",
+    database: "hello_world",
+    port: 5432,
+    // Will check models against current scheme and perform migrations
+    migrations: false
+  }
+};

+ 13 - 0
frameworks/JavaScript/chubbajs/server/config/index.js

@@ -0,0 +1,13 @@
+/**
+ * Passes the proper config object to the application
+ */
+
+let config = {};
+
+try {
+  config = require(`./config.${process.env.NODE_ENV}.js`);
+} catch(e) {
+  console.log('No config for this environment exists.');
+}
+
+module.exports = config;

+ 107 - 0
frameworks/JavaScript/chubbajs/server/controllers/HelloWorld.js

@@ -0,0 +1,107 @@
+const {
+    GET,
+    validateParams
+} = require("chubbajs").routes.annotations;
+const Entities = require("html-entities").AllHtmlEntities;
+const World = require("../models/World");
+const Fortune = require("../models/Fortune");
+
+const entities = new Entities();
+
+function rando() {
+    return Math.floor(Math.random() * 10000) + 1;
+}
+
+function sanitizeQueries(q) {
+    if (!parseInt(q) || q < 1) return 1;
+    if (q > 500) return 500;
+    return q;
+}
+
+class HelloWorldController {
+    @GET("*")
+    async setServer(ctx) {
+        ctx.res.set('Server', 'Express');
+    }
+
+    @GET("/plaintext")
+    async plaintext(ctx) {
+        ctx.res.set('Content-Type', 'text/plain');
+        ctx.res.send("Hello, World!");
+    }
+
+    @GET("/json")
+    async json(ctx) {
+        ctx.res.json({ message: "Hello, World!"});
+    }
+
+    @GET("/db")
+    async db(ctx) {
+        const world = await new World(rando());
+        ctx.res.json({ id: world.id, randomnumber: world.randomnumber });
+    }
+
+    @GET("/query")
+    @validateParams({
+        query: "queries",
+        sanitize: sanitizeQueries
+    })
+    async query(ctx, { queries }) {
+        const ret = [];
+        for (let i = 0; i < queries; i++) {
+            const world = await new World(rando());
+            ret.push({ id: world.id, randomnumber: world.randomnumber });
+        }
+        ctx.res.json(ret);
+    }
+
+    @GET("/update")
+    @validateParams({
+        query: "queries",
+        sanitize: sanitizeQueries
+    })
+    async update(ctx, { queries }) {
+        const ret = [];
+        for (let i = 0; i < queries; i++) {
+            const world = await new World(rando());
+            world.randomnumber = rando();
+            await world.save();
+            ret.push({ id: world.id, randomnumber: world.randomnumber });
+        }
+        ctx.res.json(ret);
+    }
+
+    @GET("/fortune")
+    async fortune(ctx) {
+        let fortunes = (await ctx.db.query(`SELECT * FROM "Fortune"`)).rows;
+        const newFortune = new Fortune();
+        newFortune.message = "Additional fortune added at request time.";
+        newFortune.id = 0;
+        fortunes.push(newFortune);
+        fortunes.sort((a, b) => (a.message < b.message) ? -1 : 1);
+
+        ctx.res.send(`<!DOCTYPE html>
+<html>
+<head>
+<title>Fortunes</title>
+</head>
+<body>
+<table>
+<tr>
+<th>id</th>
+<th>message</th>
+</tr>
+${fortunes.map(f => `
+<tr>
+<td>${f.id}</td>
+<td>${entities.encode(f.message)}</td>
+</tr>
+`).join('')}
+</table>
+</body>
+</html>`);
+    }
+
+}
+
+module.exports = HelloWorldController;

+ 26 - 0
frameworks/JavaScript/chubbajs/server/index.js

@@ -0,0 +1,26 @@
+const { configure } = require("chubbajs");
+const config = require("./config");
+require("regenerator-runtime");
+
+const cluster = require('cluster');
+const numCPUs = require('os').cpus().length;
+
+if (cluster.isMaster) {
+    // Fork workers.
+    for (let i = 0; i < numCPUs; i++) {
+        cluster.fork();
+    }
+
+    cluster.on('exit', (worker, code, signal) =>
+        console.log('worker ' + worker.pid + ' died'));
+} else {
+    let context;
+    async function startServer() {
+        context = await configure(config);
+        context.app.listen(config.port, () => {
+            console.log(`Server is running on port ${config.port}.`);
+        });
+    }
+    startServer();
+}
+

+ 18 - 0
frameworks/JavaScript/chubbajs/server/models/Fortune.js

@@ -0,0 +1,18 @@
+const { primaryKey, varChar } = require("chubbajs").database.annotations;
+const Model = require("chubbajs").database.Model;
+
+class Fortune extends Model {
+
+    constructor(id) {
+        super(id);
+    }
+
+    @primaryKey
+    id;
+
+    @varChar(200)
+    message;
+
+}
+
+module.exports = Fortune;

+ 18 - 0
frameworks/JavaScript/chubbajs/server/models/World.js

@@ -0,0 +1,18 @@
+const { primaryKey, int } = require("chubbajs").database.annotations;
+const Model = require("chubbajs").database.Model;
+
+class World extends Model {
+
+    constructor(id) {
+        super(id);
+    }
+
+    @primaryKey
+    id;
+
+    @int
+    randomnumber;
+
+}
+
+module.exports = World;