diff --git a/.idea/libraries/Dart_Packages.xml b/.idea/libraries/Dart_Packages.xml index 6be5cc17..c7ee0131 100644 --- a/.idea/libraries/Dart_Packages.xml +++ b/.idea/libraries/Dart_Packages.xml @@ -26,14 +26,14 @@ - + - + @@ -145,7 +145,7 @@ - + @@ -170,6 +170,13 @@ + + + + + + + @@ -229,7 +236,7 @@ - + @@ -264,7 +271,7 @@ - + @@ -306,7 +313,7 @@ - + @@ -320,7 +327,7 @@ - + @@ -355,7 +362,7 @@ - + @@ -383,7 +390,7 @@ - + @@ -435,8 +442,8 @@ - - + + @@ -452,10 +459,11 @@ - + + @@ -464,29 +472,29 @@ - + - + - + - + - + - + diff --git a/.idea/workspace.xml b/.idea/workspace.xml index 830e9bea..cf8b969f 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -2,21 +2,17 @@ - - - - - - - - - - + + + + + + @@ -42,10 +38,32 @@ - - + + - + + + + + + + + + + + + + + + + + + + + + + + @@ -54,8 +72,8 @@ - - + + @@ -63,44 +81,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - + + @@ -108,48 +137,19 @@ - - - - - - - - - - - + - - + + + - - - - - - - - - - - - - - - - - - - - @@ -161,10 +161,6 @@ - crea - run( - /* - runG query value == n handleCont @@ -191,6 +187,10 @@ _sub?.c pipe pipeline + <BR> + extend( + handleReq + STARTS _isClosed @@ -230,8 +230,6 @@ - - @@ -249,7 +247,6 @@ - @@ -257,8 +254,6 @@ - - @@ -268,19 +263,24 @@ - - - + + + + + + + + @@ -291,9 +291,9 @@ DEFINITION_ORDER - - - + + + @@ -314,6 +314,9 @@ + + + @@ -339,26 +342,11 @@ - - - - - - - - - - - - - - - @@ -379,6 +367,12 @@ + + + + + + @@ -391,7 +385,7 @@ - + @@ -517,6 +511,11 @@ + + + + + @@ -571,42 +570,43 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -665,7 +665,8 @@ - + + 1481237183504 @@ -944,23 +945,23 @@ - + - - + + - - + + - - + + - - + + - - + + @@ -976,7 +977,7 @@ - + @@ -988,39 +989,39 @@ - + + + - - + + - + + - + - - - @@ -1065,29 +1066,7 @@ - - - - - - - - - - - - - - - - - - - - - - @@ -1163,16 +1142,6 @@ - - - - - - - - - - @@ -1198,7 +1167,6 @@ - @@ -1287,20 +1255,7 @@ - - - - - - - - - - - - - - + @@ -1322,18 +1277,10 @@ - - - - - - - - @@ -1341,26 +1288,12 @@ - - - - - - - - - - - - - - - + @@ -1370,64 +1303,126 @@ + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + - - + + - + - - + + - + - - - - - - - - - - - - - + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/CHANGELOG.md b/CHANGELOG.md index a8acd86f..dfad1d05 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# 1.1.0-alpha+8 +* Added an `autoIdAndDateFields` flag to `MapService`. Finally. + +# 1.1.0-alpha+7 +* Made `handlerCache` public. +* Added `AngelMetrics`. + # 1.1.0-alpha+6 * Added `@Parameter()` annotations, with support for pattern matching. diff --git a/lib/src/http/map_service.dart b/lib/src/http/map_service.dart index 8e539f5e..be6e2f26 100644 --- a/lib/src/http/map_service.dart +++ b/lib/src/http/map_service.dart @@ -12,9 +12,16 @@ class MapService extends Service { /// If set to `true`, parameters in `req.query` are applied to the database query. final bool allowQuery; + /// If set to `true` (default), then the service will manage an `id` string and `createdAt` and `updatedAt` fields. + final bool autoIdAndDateFields; + final List> items = []; - MapService({this.allowRemoveAll: false, this.allowQuery: true}) : super(); + MapService( + {this.allowRemoveAll: false, + this.allowQuery: true, + this.autoIdAndDateFields: true}) + : super(); _matchesId(id) { return (Map item) => item['id'] != null && item['id'] == id?.toString(); @@ -53,10 +60,14 @@ class MapService extends Service { message: 'MapService does not support `create` with ${data.runtimeType}.'); var now = new DateTime.now(); - var result = data - ..['id'] = items.length.toString() - ..['createdAt'] = now - ..['updatedAt'] = now; + var result = data; + + if (autoIdAndDateFields == true) { + result + ..['id'] = items.length.toString() + ..['createdAt'] = now + ..['updatedAt'] = now; + } items.add(result); return result; } @@ -70,9 +81,10 @@ class MapService extends Service { if (!items.any(_matchesId(id))) return await create(data, params); var item = await read(id); - return item - ..addAll(data) - ..['updatedAt'] = new DateTime.now(); + var result = item..addAll(data); + + if (autoIdAndDateFields == true) result..['updatedAt'] = new DateTime.now(); + return result; } @override @@ -89,10 +101,13 @@ class MapService extends Service { throw new AngelHttpException.notFound( message: 'No record found for ID $id'); - var result = data - ..['id'] = id?.toString() - ..['createdAt'] = old['createdAt'] - ..['updatedAt'] = new DateTime.now(); + var result = data; + if (autoIdAndDateFields == true) { + result + ..['id'] = id?.toString() + ..['createdAt'] = old['createdAt'] + ..['updatedAt'] = new DateTime.now(); + } items.add(result); return result; } diff --git a/lib/src/http/server.dart b/lib/src/http/server.dart index 30489a89..75975441 100644 --- a/lib/src/http/server.dart +++ b/lib/src/http/server.dart @@ -30,7 +30,7 @@ typedef Future AngelConfigurer(Angel app); /// A powerful real-time/REST/MVC server class. class Angel extends AngelBase { final List _children = []; - final Map> _handlerCache = {}; + final Map> handlerCache = {}; Router _flattened; bool _isProduction = false; @@ -215,7 +215,7 @@ class Angel extends AngelBase { await super.close(); _preContained.clear(); - _handlerCache.clear(); + handlerCache.clear(); _injections.clear(); encoders.clear(); _serializer = god.serialize; @@ -417,7 +417,7 @@ class Angel extends AngelBase { } var tuple = isProduction - ? _handlerCache.putIfAbsent( + ? handlerCache.putIfAbsent( '${req.method}:$requestedUrl', resolveTuple) : resolveTuple(); @@ -696,4 +696,4 @@ class Angel extends AngelBase { return new Angel.fromSecurityContext(serverContext); } -} +} \ No newline at end of file diff --git a/lib/src/stats/metric_server.dart b/lib/src/stats/metric_server.dart index 69b7f472..0af63505 100644 --- a/lib/src/stats/metric_server.dart +++ b/lib/src/stats/metric_server.dart @@ -1,6 +1,5 @@ import 'dart:async'; import 'dart:io'; -import 'package:logging/logging.dart'; import '../http/http.dart'; import 'stats.dart'; @@ -16,42 +15,51 @@ class AngelMetrics extends Angel { var spec = await zoneBuilder(request, req, res); return new ZoneSpecification.from( spec, - run: (Zone self, ZoneDelegate parent, Zone zone, f()) { - var sw = new Stopwatch(); - //print('--- ${req.method} ${req.uri}: $f'); - sw.start(); - - void whenDone() { - sw.stop(); - var ms = sw.elapsedMilliseconds; - parent.print( - zone, '--- ${req.method} ${req.uri} DONE after ${ms}ms: $f'); - } - - var r = parent.run(zone, f); - - if (r is Future) { - return r.then((x) { - whenDone(); - return x; - }); - } - - whenDone(); - return r; - }, ); }; - logger = new Logger('angel_metrics') - ..onRecord.listen((rec) { - print(rec); + get('/metrics', (req, res) { + res.contentType = ContentType.HTML; - if (rec.error != null) { - print(rec.error); - print(rec.stackTrace); - } - }); + var rows = stats.all.map((stat) { + return ''' + ${stat.name} + ${stat.iterations} + ${stat.sum}ms + ${stat.average.toStringAsFixed(2)}ms + '''; + }).join(); + + res.write(''' + + + + + Metrics + + + Metrics + Updated every 5 seconds + + + + Stat + # Iterations + Total (ms) + Average (ms) + + + $rows + + + + + '''); + }); } factory AngelMetrics.custom(ServerGenerator serverGenerator) { @@ -101,7 +109,9 @@ class AngelMetrics extends Angel { @override Future handleRequest(HttpRequest request) { - return stats.handleRequest.run(() => super.handleRequest(request)); + return stats.handleRequest.run(() async { + await super.handleRequest(request); + }); } @override @@ -136,6 +146,11 @@ class AngelMetricsStats { all = [ createRequestContext, createResponseContext, + executeHandler, + getHandlerResult, + runContained, + sendResponse, + handleRequest, ]; } @@ -149,6 +164,10 @@ class AngelMetricsStats { List all; + void add(Stats stats) { + all.add(stats); + } + void log() { all.forEach((s) => s.log()); } diff --git a/lib/src/stats/stats.dart b/lib/src/stats/stats.dart index c13125cd..0d7730bb 100644 --- a/lib/src/stats/stats.dart +++ b/lib/src/stats/stats.dart @@ -12,6 +12,10 @@ class Stats { double get average => _average ?? (_total / _count); + int get iterations => _count; + + int get sum => _total; + void log() { print('$name: $average avg.'); } @@ -31,7 +35,7 @@ class Stats { sw.stop(); var ms = sw.elapsedMilliseconds; add(ms); - print('--- $name DONE after ${ms}ms'); + //print('--- $name DONE after ${ms}ms'); } var r = f(); diff --git a/performance/hello/main.dart b/performance/hello/main.dart index e8d8bff4..33e6ba40 100644 --- a/performance/hello/main.dart +++ b/performance/hello/main.dart @@ -1,13 +1,14 @@ /// A basic server that prints "Hello, world!" library performance.hello; +import 'dart:async'; import 'dart:io'; import 'dart:isolate'; import 'package:angel_framework/angel_framework.dart'; import 'package:angel_framework/metrics.dart'; main() { - for (int i = 0; i < Platform.numberOfProcessors - 1; i++) { + for (int i = 0; i < Platform.numberOfProcessors; i++) { Isolate.spawn(start, i + 1); } diff --git a/pubspec.yaml b/pubspec.yaml index 13c0d258..f7a3c714 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,5 +1,5 @@ name: angel_framework -version: 1.1.0-alpha+6 +version: 1.1.0-alpha+7 description: A high-powered HTTP server with DI, routing and more. author: Tobe O homepage: https://github.com/angel-dart/angel_framework diff --git a/test/controller_test.dart b/test/controller_test.dart index e8cace1a..e24a81fd 100644 --- a/test/controller_test.dart +++ b/test/controller_test.dart @@ -43,8 +43,14 @@ main() { setUp(() async { app = new Angel(); - app.requestMiddleware["foo"] = (req, res) async => res.write("Hello, "); - app.requestMiddleware["bar"] = (req, res) async => res.write("world!"); + app.requestMiddleware["foo"] = (req, res) async { + res.write("Hello, "); + return true; + }; + app.requestMiddleware["bar"] = (req, res) async { + res.write("world!"); + return true; + }; app.get( "/redirect", (req, ResponseContext res) async => @@ -102,7 +108,7 @@ main() { var response = await client.get("$url/todos/0"); print('Response: ${response.body}'); - expect(rgx.firstMatch(response.body).start, equals(0)); + expect(rgx.firstMatch(response.body)?.start, equals(0)); Map todo = JSON.decode(response.body.replaceAll(rgx, "")); print("Todo: $todo"); diff --git a/test/di_test.dart b/test/di_test.dart index 179e890f..56c0d469 100644 --- a/test/di_test.dart +++ b/test/di_test.dart @@ -78,8 +78,7 @@ class SingletonController extends Controller { @Expose("/errands4") class ErrandController extends Controller { @Expose("/") - errand(Errand errand, MiddlewarePipeline pipeline) { - expect(pipeline, isNotNull); + errand(Errand errand) { return errand.text; } }