ソースを参照

New(JavaScript): Add Polkadot candidate (#4580)

* init: basic polkadot endpoints

* feat: add mysql driver

* feat: add postgres driver

* feat: add mongodb driver

* chore: attach readme

* chore: lock versions
Luke Edwards 6 年 前
コミット
56af6061d0

+ 1 - 0
frameworks/JavaScript/polkadot/.npmrc

@@ -0,0 +1 @@
+package-lock=false

+ 49 - 0
frameworks/JavaScript/polkadot/README.md

@@ -0,0 +1,49 @@
+# Polkadot Benchmarking Test
+
+This is the [`polkadot`](https://github.com/lukeed/polkadot) portion of a [benchmarking test suite](../) comparing a variety of web development platforms.
+
+Information about Polkadot can be found at https://github.com/lukeed/polkadot
+
+## Database Drivers
+
+There are individual handlers for each DB approach. The logic for each of them are found here:
+
+* [MySQL](drivers/mysql.js)
+* [MongoDB](drivers/mongodb.js)
+* [PostgreSQL](drivers/postgres.js)
+
+There are **no database endpoints** or drivers attached by default.<br>
+To initialize the application with one of these, run any _one_ of the following commands:
+
+```sh
+$ DATABASE=mysql node app.js
+$ DATABASE=mongodb node app.js
+$ DATABASE=postgres node app.js
+```
+
+## Test Endpoints
+
+> Visit the test requirements [here](https://github.com/TechEmpower/FrameworkBenchmarks/wiki/Project-Information-Framework-Tests-Overview)
+
+```sh
+$ curl localhost:8080/json
+$ curl localhost:8080/plaintext
+
+# The following are only available w/ DATABASE
+# ---
+
+$ curl localhost:8080/db
+$ curl localhost:8080/fortunes
+
+$ curl localhost:8080/updates?queries=
+$ curl localhost:8080/updates?queries=2
+$ curl localhost:8080/updates?queries=1000
+$ curl localhost:8080/updates?queries=foo
+$ curl localhost:8080/updates?queries=0
+
+$ curl localhost:8080/queries?queries=
+$ curl localhost:8080/queries?queries=2
+$ curl localhost:8080/queries?queries=1000
+$ curl localhost:8080/queries?queries=foo
+$ curl localhost:8080/queries?queries=0
+```

+ 18 - 0
frameworks/JavaScript/polkadot/app.js

@@ -0,0 +1,18 @@
+const cluster = require('cluster');
+const numCPUs = require('os').cpus().length;
+
+if (cluster.isMaster) {
+	// Fork workers.
+	for (let i = 0; i < numCPUs; i++) {
+		cluster.fork();
+	}
+
+	console.log('Master starting ' + new Date().toISOString());
+
+	cluster.on('exit', () => {
+		process.exit(1);
+	});
+} else {
+	// worker task
+	require('./init');
+}

+ 90 - 0
frameworks/JavaScript/polkadot/benchmark_config.json

@@ -0,0 +1,90 @@
+{
+  "framework": "polkadot",
+  "tests": [
+    {
+      "default": {
+        "json_url": "/json",
+        "plaintext_url": "/plaintext",
+        "port": 8080,
+        "approach": "Realistic",
+        "classification": "Platform",
+        "database": "None",
+        "framework": "polkadot",
+        "language": "JavaScript",
+        "flavor": "NodeJS",
+        "orm": "Raw",
+        "platform": "None",
+        "webserver": "None",
+        "os": "Linux",
+        "database_os": "Linux",
+        "display_name": "polkadot",
+        "notes": "",
+        "versus": "nodejs"
+      },
+      "mysql": {
+        "dockerfile": "polkadot-mysql.dockerfile",
+        "db_url": "/db",
+        "query_url": "/queries?queries=",
+        "fortune_url": "/fortunes",
+        "update_url": "/updates?queries=",
+        "port": 8080,
+        "approach": "Realistic",
+        "classification": "Platform",
+        "database": "MySQL",
+        "framework": "polkadot",
+        "language": "JavaScript",
+        "flavor": "NodeJS",
+        "orm": "Raw",
+        "platform": "None",
+        "webserver": "None",
+        "os": "Linux",
+        "database_os": "Linux",
+        "display_name": "polkadot",
+        "notes": "",
+        "versus": "nodejs"
+      },
+      "postgres": {
+        "db_url": "/db",
+        "query_url": "/queries?queries=",
+        "fortune_url": "/fortunes",
+        "update_url": "/updates?queries=",
+        "port": 8080,
+        "approach": "Realistic",
+        "classification": "Platform",
+        "database": "Postgres",
+        "framework": "polkadot",
+        "language": "JavaScript",
+        "flavor": "NodeJS",
+        "orm": "Raw",
+        "platform": "None",
+        "webserver": "None",
+        "os": "Linux",
+        "database_os": "Linux",
+        "display_name": "polkadot",
+        "notes": "",
+        "versus": "nodejs"
+      },
+      "mongodb": {
+        "db_url": "/db",
+        "query_url": "/queries?queries=",
+        "fortune_url": "/fortunes",
+        "update_url": "/updates?queries=",
+        "port": 8080,
+        "approach": "Realistic",
+        "classification": "Platform",
+        "database": "MongoDB",
+        "framework": "polkadot",
+        "language": "JavaScript",
+        "flavor": "NodeJS",
+        "orm": "Raw",
+        "platform": "None",
+        "webserver": "None",
+        "os": "Linux",
+        "database_os": "Linux",
+        "display_name": "polkadot",
+        "notes": "",
+        "versus": "nodejs"
+      }
+    }
+  ]
+}

+ 16 - 0
frameworks/JavaScript/polkadot/drivers/mongodb.js

@@ -0,0 +1,16 @@
+const { MongoClient } = require('mongodb');
+
+let World, Fortune;
+const projection = { _id:0 };
+
+MongoClient.connect('mongodb://tfb-database:27017', { useNewUrlParser:true }, (err, ctx) => {
+	const DB = ctx.db('hello_world');
+	Fortune = DB.collection('fortune');
+	World = DB.collection('world');
+});
+
+exports.fortunes = () => Fortune.find({}, { projection }).toArray();
+
+exports.find = id => World.findOne({ id }, { projection });
+
+exports.update = obj => World.replaceOne({ id:obj.id }, obj);

+ 24 - 0
frameworks/JavaScript/polkadot/drivers/mysql.js

@@ -0,0 +1,24 @@
+const { createConnection } = require('mysql');
+
+const connection = createConnection({
+	host: 'tfb-database',
+	user: 'benchmarkdbuser',
+	password: 'benchmarkdbpass',
+	database: 'hello_world'
+});
+
+connection.connect();
+
+function query(text, values) {
+	return new Promise((res, rej) => {
+		connection.query(text, values || [], (err, results) => {
+			return err ? rej(err) : res(results);
+		});
+	});
+}
+
+exports.fortunes = () => query('SELECT * FROM fortune');
+
+exports.find = id => query('SELECT * FROM world WHERE id = ?', [id]).then(arr => arr[0]);
+
+exports.update = obj => query('UPDATE world SET randomNumber = ? WHERE id = ?', [obj.randomNumber, obj.id]);

+ 20 - 0
frameworks/JavaScript/polkadot/drivers/postgres.js

@@ -0,0 +1,20 @@
+const { Client } = require('pg');
+
+const client = new Client({
+	host: 'tfb-database',
+  user: 'benchmarkdbuser',
+  password: 'benchmarkdbpass',
+  database: 'hello_world'
+});
+
+client.connect();
+
+function query(text, values) {
+	return client.query(text, values || []).then(r => r.rows);
+}
+
+exports.fortunes = () => query('SELECT * FROM fortune');
+
+exports.find = id => query('SELECT * FROM world WHERE id = $1', [id]).then(arr => arr[0]);
+
+exports.update = obj => query('UPDATE world SET randomNumber = $1 WHERE id = $2', [obj.randomNumber, obj.id]);

+ 8 - 0
frameworks/JavaScript/polkadot/helper.js

@@ -0,0 +1,8 @@
+exports.random = () => Math.floor(Math.random() * 1e4) + 1;
+
+exports.parse = queries => Math.min(Math.max(parseInt(queries, 10) || 1, 1), 500);
+
+exports.fortune = {
+	id: 0,
+	message: 'Additional fortune added at request time.'
+};

+ 66 - 0
frameworks/JavaScript/polkadot/init.js

@@ -0,0 +1,66 @@
+const polkadot = require('polkadot');
+const XSS = require('html-escaper');
+const helper = require('./helper');
+
+const { DATABASE } = process.env;
+const DRIVER = DATABASE && require(`./drivers/${DATABASE}`);
+
+polkadot(async (req, res) => {
+	res.setHeader('Server', 'Polkadot');
+
+	if (req.path === '/json') {
+		res.setHeader('Content-Type', 'application/json');
+		return { message: 'Hello, World!' };
+	}
+
+	if (req.path === '/plaintext') {
+		return 'Hello, World!';
+	}
+
+	if (DRIVER) {
+		if (req.path === '/db') {
+			res.setHeader('Content-Type', 'application/json');
+			return DRIVER.find(helper.random());
+		}
+
+		if (req.path === '/queries') {
+			let arr=[], num=helper.parse(req.query.queries);
+			while (num-- > 0) arr.push(DRIVER.find(helper.random()));
+			res.setHeader('Content-Type', 'application/json');
+			return Promise.all(arr);
+		}
+
+		if (req.path === '/fortunes') {
+			const items = await DRIVER.fortunes();
+			items.push(helper.fortune);
+
+			items.sort((a, b) => a.message.localeCompare(b.message));
+
+			let i=0, html='<!DOCTYPE html><html><head><title>Fortunes</title></head><body><table><tr><th>id</th><th>message</th></tr>';
+			for (; i < items.length; i++) html += `<tr><td>${items[i].id}</td><td>${XSS.escape(items[i].message)}</td></tr>`;
+			html += '</table></body></html>';
+
+			res.setHeader('Content-Type', 'text/html; charset=utf-8');
+			return html;
+		}
+
+		if (req.path === '/updates') {
+			let reads=[], num=helper.parse(req.query.queries);
+			while (num-- > 0) reads.push(DRIVER.find(helper.random()));
+			const rows = await Promise.all(reads);
+
+			let i=0, writes=[];
+			for (; i < rows.length; i++) {
+				rows[i].randomNumber = helper.random();
+				writes.push(DRIVER.update(rows[i]));
+			}
+
+			await Promise.all(writes);
+			res.setHeader('Content-Type', 'application/json');
+			return rows;
+		}
+	}
+}).listen(8080, '0.0.0.0', err => {
+	if (err) throw err;
+	console.log(`Worker started and listening on http://0.0.0.0:8080 ${new Date().toISOString()}`);
+});

+ 13 - 0
frameworks/JavaScript/polkadot/package.json

@@ -0,0 +1,13 @@
+{
+  "private": true,
+  "name": "polkadot-tfb",
+  "version": "0.0.0",
+  "main": "app.js",
+  "dependencies": {
+    "html-escaper": "1.0.1",
+    "mongodb": "3.2.2",
+    "mysql": "2.16.0",
+    "pg": "7.9.0",
+    "polkadot": "1.0.0"
+  }
+}

+ 10 - 0
frameworks/JavaScript/polkadot/polkadot-mongodb.dockerfile

@@ -0,0 +1,10 @@
+FROM node:11.6.0
+
+COPY ./ ./
+
+RUN npm install
+
+ENV NODE_ENV production
+ENV DATABASE mongodb
+
+CMD ["node", "app.js"]

+ 10 - 0
frameworks/JavaScript/polkadot/polkadot-mysql.dockerfile

@@ -0,0 +1,10 @@
+FROM node:11.6.0
+
+COPY ./ ./
+
+RUN npm install
+
+ENV NODE_ENV production
+ENV DATABASE mysql
+
+CMD ["node", "app.js"]

+ 10 - 0
frameworks/JavaScript/polkadot/polkadot-postgres.dockerfile

@@ -0,0 +1,10 @@
+FROM node:11.6.0
+
+COPY ./ ./
+
+RUN npm install
+
+ENV NODE_ENV production
+ENV DATABASE postgres
+
+CMD ["node", "app.js"]

+ 9 - 0
frameworks/JavaScript/polkadot/polkadot.dockerfile

@@ -0,0 +1,9 @@
+FROM node:11.6.0
+
+COPY ./ ./
+
+RUN npm install
+
+ENV NODE_ENV production
+
+CMD ["node", "app.js"]