123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359 |
- import "dart:core";
- import "dart:io";
- import 'dart:async' show Future;
- import 'dart:convert';
- import 'dart:math' show Random;
- import "package:start/start.dart";
- import "package:args/args.dart";
- import 'package:postgresql/postgresql.dart' as pg;
- import 'package:postgresql/postgresql_pool.dart' as pgpool;
- import 'package:yaml/yaml.dart' as yaml;
- import 'package:mustache/mustache.dart' as mustache;
- import 'package:mongo_dart/mongo_dart.dart';
- import 'package:crypto/crypto.dart';
- // Postgres connection pool
- var _connectionPool;
- // Fortunes mustache template
- var _fortunesTemplate;
- // MongoDB connection
- var _mongoDb;
- // World Collection
- var _worldCollection;
- // Fortunes Collection
- var _fortuneCollection;
- // World table size
- const _WORLD_TABLE_SIZE = 10000;
- // Fortune table size used only for generation of data
- const _FORTUNE_TABLE_SIZE = 100;
- final _RANDOM = new Random();
- class Fortune implements Comparable<Fortune> {
- int id;
- String message;
- Fortune(this.id, this.message);
- compareTo(Fortune other) => message.compareTo(other.message);
- }
- class World {
- int id;
- int randomnumber;
- World(this.id, this.randomnumber);
- toJson() => { "id": id, "randomNumber": randomnumber };
- }
- main(List<String> args) {
- var parser = new ArgParser();
- parser.addOption('address', abbr: 'a', defaultsTo: '0.0.0.0');
- parser.addOption('port', abbr: 'p', defaultsTo: '8080');
- parser.addOption('dbconnections', abbr: 'd', defaultsTo: '256');
-
- var arguments = parser.parse(args);
-
- Future.wait([
- new File("postgresql.yaml").readAsString().then((config){
- _connectionPool = new pgpool.Pool(
- new pg.Settings.fromMap(yaml.loadYaml(config)).toUri(),
- min: int.parse(arguments["dbconnections"]),
- max: int.parse(arguments["dbconnections"])
- );
- return _connectionPool.start();
- }),
- new File("mongodb.yaml").readAsString().then((config) {
- var mongoConfig = yaml.loadYaml(config);
- _mongoDb = new Db("mongodb://${mongoConfig["host"]}/${mongoConfig["database"]}");
- return _mongoDb.open().then((_) {
- _worldCollection = _mongoDb.collection("World");
- _fortuneCollection = _mongoDb.collection("Fortune");
- });
- }),
- new File('fortunes.mustache').readAsString().then((template) {
- _fortunesTemplate = mustache.parse(template);
- })
- ]).then((_) {
- start(host: arguments["address"], public: 'web', port: int.parse(arguments["port"]))
- .then((Server app) {
-
- // JSON test
- app.get('/json').listen((request) {
-
- var helloWorld = {
- "message": "Hello, World!"
- };
-
- _setJsonHeaders(request.response);
- request.response.send(JSON.encode(helloWorld));
- });
-
-
- // Query test
- app.get("/db").listen((request) {
-
- _setJsonHeaders(request.response);
-
- _query().then((data) {
- request.response.send(JSON.encode(data));
- });
- });
-
- // Queries test
- app.get("/queries").listen((request) {
-
- var queries = _parseQueriesParam(request.param("queries"));
-
- _setJsonHeaders(request.response);
-
- Future.wait(
- new List.generate(
- queries,
- (_) => _query(),
- growable: false
- )
- )
- .then((response) => request.response.send(JSON.encode(response)));
- });
-
- // Fortunes test
- app.get("/fortunes").listen((request) {
- _setHtmlHeaders(request.response);
-
- _connectionPool.connect().then((connection) {
- return connection.query('SELECT id, message FROM fortune;')
- .map((row) => new Fortune(row[0], row[1]))
- .toList()
- .whenComplete(() { connection.close(); });
- }).then((fortunes) {
- fortunes.add(new Fortune(0, 'Additional fortune added at request time.'));
- fortunes.sort();
- request.response.send(_fortunesTemplate.renderString({
- "fortunes": fortunes.map((fortune) => {
- "id": fortune.id,
- "message": fortune.message
- }).toList()
- }));
- });
- });
-
- // Updates test
- app.get("/updates").listen((request) {
-
- var queries = _parseQueriesParam(request.param("queries"));
-
- _setJsonHeaders(request.response);
-
- Future.wait(new List.generate(queries, (_) {
- return _query()
- .then((world) {
- world.randomnumber = _RANDOM.nextInt(_WORLD_TABLE_SIZE) + 1;
- return _connectionPool.connect()
- .then((connection) {
- return connection.execute(
- 'UPDATE world SET randomnumber = @randomnumber WHERE id = @id;',
- {
- 'randomnumber': world.randomnumber,
- 'id': world.id
- }
- )
- .whenComplete(() { connection.close(); });
- })
- .then((_) => world);
- });
- }, growable: false))
- .then((worlds) => request.response.send(JSON.encode(worlds)));
- });
-
- // Plain text test
- app.get("/plaintext").listen((request) {
- _setPlainHeaders(request.response);
- request.response.send("Hello, World!");
- });
-
- // Mongo World dev data generation
- app.get("/generate-world").listen((request) {
-
- _worldCollection.drop()
- .then((_) {
- var collectionData = new List.generate(_WORLD_TABLE_SIZE, (index) {
- return {
- "_id": index + 1,
- "randomNumber": _RANDOM.nextInt(_WORLD_TABLE_SIZE)
- };
- });
- return _worldCollection.insertAll(collectionData);
- })
- .then((_) {
- request.response.send("Generated");
- });
- });
-
- // Mongo Fortune dev data generation
- app.get("/generate-fortune").listen((request) {
- _fortuneCollection.drop()
- .then((_) {
- var collectionData = new List.generate(_FORTUNE_TABLE_SIZE, (index) {
- var hash = new MD5();
- hash.add(_RANDOM.nextInt(_FORTUNE_TABLE_SIZE).toString().codeUnits);
- return {
- "_id": index + 1,
- "message": CryptoUtils.bytesToHex(hash.close())
- };
- });
- return _fortuneCollection.insertAll(collectionData);
- })
- .then((_) {
- request.response.send("Generated");
- });
-
- });
-
- // Mongo query test
- app.get("/db-mongo").listen((request) {
- _setJsonHeaders(request.response);
- _mongoQuery().then((data) {
- request.response.json({
- "id": data["_id"],
- "randomNumber": data["randomNumber"]
- });
- });
- });
-
- // Mongo queries test
- app.get("/queries-mongo").listen((request) {
-
- var queries = _parseQueriesParam(request.param("queries"));
- _setJsonHeaders(request.response);
-
- Future.wait(
- new List.generate(
- queries,
- (_) => _mongoQuery(),
- growable: false
- )
- )
- .then((response) {
- var results = response.map((world) {
- return {
- "id": world["_id"],
- "randomNumber": world["randomNumber"]
- };
- });
- request.response.send(JSON.encode(results.toList()));
- });
- });
-
- // Mongo updates test
- app.get("/updates-mongo").listen((request) {
- var queries = _parseQueriesParam(request.param("queries"));
- _setJsonHeaders(request.response);
- Future.wait(new List.generate(queries, (index) {
- return _mongoQuery()
- .then((world) {
- world["randomNumber"] = _RANDOM.nextInt(_WORLD_TABLE_SIZE);
- return _worldCollection.update( { "_id": world["_id"] }, world)
- .then((_) => world);
- });
- }, growable: false))
- .then((worlds) {
- var result = worlds.map((world) {
- return {
- "id": world["_id"],
- "randomNumber": world["randomNumber"]
- };
- });
- request.response.send(JSON.encode(result.toList()));
- });
- });
-
-
- // Mongo fortunes test
- app.get("/fortunes-mongo").listen((request) {
-
- _setHtmlHeaders(request.response);
-
- _fortuneCollection.find().toList().then((fortunes) {
- fortunes = fortunes.map((fortune) {
- return new Fortune(fortune["_id"], fortune["message"]);
- }).toList();
- fortunes.add(new Fortune(0, 'Additional fortune added at request time.'));
- fortunes.sort();
- request.response.send(_fortunesTemplate.renderString({
- "fortunes": fortunes.map((fortune) => {
- "id": fortune.id,
- "message": fortune.message
- }).toList()
- }));
- });
- });
-
- });
- });
- }
- // set JSON headers
- _setJsonHeaders(response) {
- _setHeaders(response);
- response
- .header(HttpHeaders.CONTENT_TYPE, 'application/json; charset=UTF-8');
- }
- // set plain text headers
- _setPlainHeaders(response) {
- _setHeaders(response);
- response
- .header(HttpHeaders.CONTENT_TYPE, 'text/plain; charset=UTF-8');
- }
- // set HTML headers
- _setHtmlHeaders(response) {
- _setHeaders(response);
- response
- .header(HttpHeaders.CONTENT_TYPE, 'text/html; charset=UTF-8');
- }
- // set common headers
- _setHeaders(response) {
- // disable gzip encoding
- response.header(HttpHeaders.CONTENT_ENCODING, "")
- ..header(HttpHeaders.DATE, new DateTime.now());
- }
- // parse queries param
- _parseQueriesParam(param) {
- return param.isEmpty ? 1 : int.parse(param, radix: 10, onError: (_) => 1).clamp(1, 500);
- }
- // runs a query and returns a promise
- _query() {
- return _connectionPool.connect().then((connection) {
- return connection
- .query('SELECT id, randomnumber FROM world WHERE id = @id;', { 'id': _RANDOM.nextInt(_WORLD_TABLE_SIZE) + 1 })
- .single
- .then((row) =>new World(row[0], row[1]))
- .whenComplete(() {
- connection.close();
- });
- });
- }
- // runs a mongo query and returns a promise
- _mongoQuery() {
- return _worldCollection.findOne({
- "_id": _RANDOM.nextInt(_WORLD_TABLE_SIZE) + 1
- });
- }
|