|
@@ -1,93 +1,121 @@
|
|
const h = require('../helper');
|
|
const h = require('../helper');
|
|
-const async = require('async');
|
|
|
|
const MongoClient = require('mongodb').MongoClient;
|
|
const MongoClient = require('mongodb').MongoClient;
|
|
-const collections = {
|
|
|
|
- World: null,
|
|
|
|
- Fortune: null
|
|
|
|
-};
|
|
|
|
|
|
+let collectionsMaybe = null, connecting = false, connectionCallbacks = [];
|
|
|
|
|
|
const mongoUrl = 'mongodb://tfb-database:27017';
|
|
const mongoUrl = 'mongodb://tfb-database:27017';
|
|
const dbName = 'hello_world';
|
|
const dbName = 'hello_world';
|
|
|
|
|
|
-MongoClient.connect(mongoUrl, (err, database) => {
|
|
|
|
- // do nothing if there is err connecting to db
|
|
|
|
-
|
|
|
|
- collections.World = database.db(dbName).collection('world');
|
|
|
|
- collections.Fortune = database.db(dbName).collection('fortune');
|
|
|
|
-});
|
|
|
|
|
|
+/**
|
|
|
|
+ * Note! The benchmarks say we should use "id" as a property name.
|
|
|
|
+ * However, Mongo provides a default index on "_id", so to be equivalent to the other tests, we use
|
|
|
|
+ * the same, default index provided by the database.
|
|
|
|
+ *
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+const getCollections = async () => {
|
|
|
|
+ // mongoose creates a queue of requests during connection, so we don't have to wait.
|
|
|
|
+ // however, with the raw driver we need to connect first, or sometimes the test will fail randomly
|
|
|
|
+ if (collectionsMaybe) {
|
|
|
|
+ return collectionsMaybe;
|
|
|
|
+ }
|
|
|
|
+ if (connecting) {
|
|
|
|
+ const promise = new Promise((resolve) => {
|
|
|
|
+ connectionCallbacks.push(resolve);
|
|
|
|
+ });
|
|
|
|
+ return await promise;
|
|
|
|
+ }
|
|
|
|
+ connecting = true;
|
|
|
|
+ const client = await MongoClient.connect(mongoUrl);
|
|
|
|
+ collectionsMaybe = {
|
|
|
|
+ World: null,
|
|
|
|
+ Fortune: null
|
|
|
|
+ };
|
|
|
|
+ collectionsMaybe.World = client.db(dbName).collection('world');
|
|
|
|
+ collectionsMaybe.Fortune = client.db(dbName).collection('fortune');
|
|
|
|
+
|
|
|
|
+ // resolve pending requests in buffer
|
|
|
|
+ for (const callback of connectionCallbacks) {
|
|
|
|
+ callback(collectionsMaybe);
|
|
|
|
+ }
|
|
|
|
|
|
|
|
+ return collectionsMaybe;
|
|
|
|
+}
|
|
|
|
|
|
-const mongodbRandomWorld = (callback) => {
|
|
|
|
- collections.World.findOne({
|
|
|
|
- id: h.randomTfbNumber()
|
|
|
|
- }, (err, world) => {
|
|
|
|
- world._id = undefined; // remove _id from query response
|
|
|
|
- callback(err, world);
|
|
|
|
- });
|
|
|
|
|
|
+const toClientWorld = (world) => {
|
|
|
|
+ if (world) {
|
|
|
|
+ world.id = world._id;
|
|
|
|
+ delete world._id;
|
|
|
|
+ }
|
|
|
|
+ return world;
|
|
};
|
|
};
|
|
|
|
|
|
-const mongodbGetAllFortunes = (callback) => {
|
|
|
|
- collections.Fortune.find().toArray((err, fortunes) => {
|
|
|
|
- callback(err, fortunes);
|
|
|
|
- })
|
|
|
|
|
|
+
|
|
|
|
+const mongodbRandomWorld = async () => {
|
|
|
|
+ const collections = await getCollections();
|
|
|
|
+ return toClientWorld(await collections.World.findOne({
|
|
|
|
+ _id: h.randomTfbNumber()
|
|
|
|
+ }));
|
|
};
|
|
};
|
|
|
|
|
|
-const mongodbDriverUpdateQuery = (callback) => {
|
|
|
|
- collections.World.findOne({ id: h.randomTfbNumber() }, (err, world) => {
|
|
|
|
- world.randomNumber = h.randomTfbNumber();
|
|
|
|
- collections.World.update({ id: world.id }, world, (err, updated) => {
|
|
|
|
- callback(err, { id: world.id, randomNumber: world.randomNumber });
|
|
|
|
- });
|
|
|
|
- });
|
|
|
|
|
|
+const mongodbGetAllFortunes = async () => {
|
|
|
|
+ const collections = await getCollections();
|
|
|
|
+ return (await collections.Fortune.find({}).toArray()).map(toClientWorld);
|
|
};
|
|
};
|
|
|
|
|
|
|
|
+async function getUpdateRandomWorld() {
|
|
|
|
+ const collections = await getCollections();
|
|
|
|
+ const world = await collections.World.findOne({
|
|
|
|
+ _id: h.randomTfbNumber()
|
|
|
|
+ });
|
|
|
|
+ world.randomNumber = h.randomTfbNumber();
|
|
|
|
+ await collections.World.updateOne({
|
|
|
|
+ _id: world._id
|
|
|
|
+ }, {
|
|
|
|
+ $set: {
|
|
|
|
+ randomNumber: world.randomNumber
|
|
|
|
+ }
|
|
|
|
+ })
|
|
|
|
+ return toClientWorld(world);
|
|
|
|
+}
|
|
|
|
|
|
module.exports = {
|
|
module.exports = {
|
|
|
|
|
|
- SingleQuery: (req, res) => {
|
|
|
|
- mongodbRandomWorld((err, result) => {
|
|
|
|
- if (err) { return process.exit(1) }
|
|
|
|
-
|
|
|
|
- h.addTfbHeaders(res, 'json');
|
|
|
|
- res.end(JSON.stringify(result));
|
|
|
|
- });
|
|
|
|
|
|
+ SingleQuery: async (req, res) => {
|
|
|
|
+ const result = await mongodbRandomWorld();
|
|
|
|
+ h.addTfbHeaders(res, 'json');
|
|
|
|
+ res.end(JSON.stringify(result));
|
|
},
|
|
},
|
|
|
|
|
|
- MultipleQueries: (queries, req, res) => {
|
|
|
|
- const queryFunctions = h.fillArray(mongodbRandomWorld, queries);
|
|
|
|
-
|
|
|
|
- async.parallel(queryFunctions, (err, results) => {
|
|
|
|
- if (err) { return process.exit(1) }
|
|
|
|
|
|
+ MultipleQueries: async (queryCount, req, res) => {
|
|
|
|
+ const queryFunctions = [];
|
|
|
|
+ for (let i = 0; i < queryCount; i++) {
|
|
|
|
+ queryFunctions.push(mongodbRandomWorld());
|
|
|
|
+ }
|
|
|
|
+ const results = await Promise.all(queryFunctions);
|
|
|
|
|
|
- h.addTfbHeaders(res, 'json');
|
|
|
|
- res.end(JSON.stringify(results));
|
|
|
|
- });
|
|
|
|
|
|
+ h.addTfbHeaders(res, 'json');
|
|
|
|
+ res.end(JSON.stringify(results));
|
|
},
|
|
},
|
|
|
|
|
|
- Fortunes: (req, res) => {
|
|
|
|
- mongodbGetAllFortunes((err, fortunes) => {
|
|
|
|
- if (err) { return process.exit(1) }
|
|
|
|
-
|
|
|
|
- fortunes.push(h.additionalFortune());
|
|
|
|
- fortunes.sort(function (a, b) {
|
|
|
|
- return a.message.localeCompare(b.message);
|
|
|
|
- });
|
|
|
|
- h.addTfbHeaders(res, 'html');
|
|
|
|
- res.end(h.fortunesTemplate({
|
|
|
|
- fortunes: fortunes
|
|
|
|
- }));
|
|
|
|
|
|
+ Fortunes: async (req, res) => {
|
|
|
|
+ const fortunes = await mongodbGetAllFortunes();
|
|
|
|
+ fortunes.push(h.additionalFortune());
|
|
|
|
+ fortunes.sort(function (a, b) {
|
|
|
|
+ return a.message.localeCompare(b.message);
|
|
});
|
|
});
|
|
|
|
+ h.addTfbHeaders(res, 'html');
|
|
|
|
+ res.end(h.fortunesTemplate({fortunes}));
|
|
},
|
|
},
|
|
|
|
|
|
- Updates: (queries, req, res) => {
|
|
|
|
- const queryFunctions = h.fillArray(mongodbDriverUpdateQuery, queries);
|
|
|
|
|
|
+ Updates: async (queryCount, req, res) => {
|
|
|
|
+ const promises = [];
|
|
|
|
|
|
- async.parallel(queryFunctions, (err, results) => {
|
|
|
|
- if (err) { return process.exit(1) }
|
|
|
|
|
|
+ for (let i = 1; i <= queryCount; i++) {
|
|
|
|
+ promises.push(getUpdateRandomWorld());
|
|
|
|
+ }
|
|
|
|
|
|
- h.addTfbHeaders(res, 'json');
|
|
|
|
- res.end(JSON.stringify(results));
|
|
|
|
- });
|
|
|
|
|
|
+ h.addTfbHeaders(res, 'json');
|
|
|
|
+ res.end(JSON.stringify(await Promise.all(promises)));
|
|
}
|
|
}
|
|
|
|
|
|
};
|
|
};
|