74
This commit is contained in:
parent
94886bca13
commit
edf1b04f9f
5 changed files with 145 additions and 15 deletions
|
@ -1,6 +1,6 @@
|
|||
# angel_framework
|
||||
|
||||
[![pub 1.0.0-dev.73](https://img.shields.io/badge/pub-1.0.0--dev.73-red.svg)](https://pub.dartlang.org/packages/angel_framework)
|
||||
[![pub 1.0.0-dev.74](https://img.shields.io/badge/pub-1.0.0--dev.74-red.svg)](https://pub.dartlang.org/packages/angel_framework)
|
||||
[![build status](https://travis-ci.org/angel-dart/framework.svg)](https://travis-ci.org/angel-dart/framework)
|
||||
|
||||
A high-powered HTTP server with support for dependency injection, sophisticated routing and more.
|
||||
|
|
|
@ -11,30 +11,34 @@ import 'service.dart';
|
|||
|
||||
/// Wraps another service in a service that broadcasts events on actions.
|
||||
class HookedService extends Service {
|
||||
final List<StreamController<HookedServiceEvent>> _ctrl = [];
|
||||
|
||||
/// Tbe service that is proxied by this hooked one.
|
||||
final Service inner;
|
||||
|
||||
HookedServiceEventDispatcher beforeIndexed =
|
||||
final HookedServiceEventDispatcher beforeIndexed =
|
||||
new HookedServiceEventDispatcher();
|
||||
HookedServiceEventDispatcher beforeRead = new HookedServiceEventDispatcher();
|
||||
HookedServiceEventDispatcher beforeCreated =
|
||||
final HookedServiceEventDispatcher beforeRead =
|
||||
new HookedServiceEventDispatcher();
|
||||
HookedServiceEventDispatcher beforeModified =
|
||||
final HookedServiceEventDispatcher beforeCreated =
|
||||
new HookedServiceEventDispatcher();
|
||||
HookedServiceEventDispatcher beforeUpdated =
|
||||
final HookedServiceEventDispatcher beforeModified =
|
||||
new HookedServiceEventDispatcher();
|
||||
HookedServiceEventDispatcher beforeRemoved =
|
||||
final HookedServiceEventDispatcher beforeUpdated =
|
||||
new HookedServiceEventDispatcher();
|
||||
HookedServiceEventDispatcher afterIndexed =
|
||||
final HookedServiceEventDispatcher beforeRemoved =
|
||||
new HookedServiceEventDispatcher();
|
||||
HookedServiceEventDispatcher afterRead = new HookedServiceEventDispatcher();
|
||||
HookedServiceEventDispatcher afterCreated =
|
||||
final HookedServiceEventDispatcher afterIndexed =
|
||||
new HookedServiceEventDispatcher();
|
||||
HookedServiceEventDispatcher afterModified =
|
||||
final HookedServiceEventDispatcher afterRead =
|
||||
new HookedServiceEventDispatcher();
|
||||
HookedServiceEventDispatcher afterUpdated =
|
||||
final HookedServiceEventDispatcher afterCreated =
|
||||
new HookedServiceEventDispatcher();
|
||||
HookedServiceEventDispatcher afterRemoved =
|
||||
final HookedServiceEventDispatcher afterModified =
|
||||
new HookedServiceEventDispatcher();
|
||||
final HookedServiceEventDispatcher afterUpdated =
|
||||
new HookedServiceEventDispatcher();
|
||||
final HookedServiceEventDispatcher afterRemoved =
|
||||
new HookedServiceEventDispatcher();
|
||||
|
||||
HookedService(Service this.inner) {
|
||||
|
@ -61,6 +65,25 @@ class HookedService extends Service {
|
|||
.fold({}, (map, key) => map..[key] = params[key]);
|
||||
}
|
||||
|
||||
/// Closes any open [StreamController]s on this instance. **Internal use only**.
|
||||
Future close() async {
|
||||
_ctrl.forEach((c) => c.close());
|
||||
beforeIndexed._close();
|
||||
beforeRead._close();
|
||||
beforeCreated._close();
|
||||
beforeModified._close();
|
||||
beforeUpdated._close();
|
||||
beforeRemoved._close();
|
||||
afterIndexed._close();
|
||||
afterRead._close();
|
||||
afterCreated._close();
|
||||
afterModified._close();
|
||||
afterUpdated._close();
|
||||
afterRemoved._close();
|
||||
|
||||
if (inner is HookedService) inner.close();
|
||||
}
|
||||
|
||||
/// Adds hooks to this instance.
|
||||
void addHooks() {
|
||||
Hooks hooks = getAnnotation(inner, Hooks);
|
||||
|
@ -309,6 +332,54 @@ class HookedService extends Service {
|
|||
afterRemoved.listen(listener);
|
||||
}
|
||||
|
||||
/// Returns a [Stream] of all events fired before every service method.
|
||||
///
|
||||
/// *NOTE*: Only use this if you do not plan to modify events. There is no guarantee
|
||||
/// that events coming out of this [Stream] will see changes you make within the [Stream]
|
||||
/// callback.
|
||||
Stream<HookedServiceEvent> beforeAllStream() {
|
||||
var ctrl = new StreamController<HookedServiceEvent>();
|
||||
_ctrl.add(ctrl);
|
||||
before(HookedServiceEvent.ALL, ctrl.add);
|
||||
return ctrl.stream;
|
||||
}
|
||||
|
||||
/// Returns a [Stream] of all events fired after every service method.
|
||||
///
|
||||
/// *NOTE*: Only use this if you do not plan to modify events. There is no guarantee
|
||||
/// that events coming out of this [Stream] will see changes you make within the [Stream]
|
||||
/// callback.
|
||||
Stream<HookedServiceEvent> afterAllStream() {
|
||||
var ctrl = new StreamController<HookedServiceEvent>();
|
||||
_ctrl.add(ctrl);
|
||||
before(HookedServiceEvent.ALL, ctrl.add);
|
||||
return ctrl.stream;
|
||||
}
|
||||
|
||||
/// Returns a [Stream] of all events fired before every service method specified.
|
||||
///
|
||||
/// *NOTE*: Only use this if you do not plan to modify events. There is no guarantee
|
||||
/// that events coming out of this [Stream] will see changes you make within the [Stream]
|
||||
/// callback.
|
||||
Stream<HookedServiceEvent> beforeStream(Iterable<String> eventNames) {
|
||||
var ctrl = new StreamController<HookedServiceEvent>();
|
||||
_ctrl.add(ctrl);
|
||||
before(eventNames, ctrl.add);
|
||||
return ctrl.stream;
|
||||
}
|
||||
|
||||
/// Returns a [Stream] of all events fired AFTER every service method specified.
|
||||
///
|
||||
/// *NOTE*: Only use this if you do not plan to modify events. There is no guarantee
|
||||
/// that events coming out of this [Stream] will see changes you make within the [Stream]
|
||||
/// callback.
|
||||
Stream<HookedServiceEvent> afterStream(Iterable<String> eventNames) {
|
||||
var ctrl = new StreamController<HookedServiceEvent>();
|
||||
_ctrl.add(ctrl);
|
||||
after(eventNames, ctrl.add);
|
||||
return ctrl.stream;
|
||||
}
|
||||
|
||||
/// Runs the [listener] before [create], [modify] and [update].
|
||||
void beforeModify(HookedServiceEventListener listener) {
|
||||
beforeCreated.listen(listener);
|
||||
|
@ -549,6 +620,14 @@ class HookedServiceEvent {
|
|||
static const String MODIFIED = "modified";
|
||||
static const String UPDATED = "updated";
|
||||
static const String REMOVED = "removed";
|
||||
static const List<String> ALL = const [
|
||||
INDEXED,
|
||||
READ,
|
||||
CREATED,
|
||||
MODIFIED,
|
||||
UPDATED,
|
||||
REMOVED
|
||||
];
|
||||
|
||||
/// Use this to end processing of an event.
|
||||
void cancel([result]) {
|
||||
|
@ -601,7 +680,12 @@ typedef HookedServiceEventListener(HookedServiceEvent event);
|
|||
|
||||
/// Can be listened to, but events may be canceled.
|
||||
class HookedServiceEventDispatcher {
|
||||
List<HookedServiceEventListener> listeners = [];
|
||||
final List<StreamController<HookedServiceEvent>> _ctrl = [];
|
||||
final List<HookedServiceEventListener> listeners = [];
|
||||
|
||||
void _close() {
|
||||
_ctrl.forEach((c) => c.close());
|
||||
}
|
||||
|
||||
/// Fires an event, and returns it once it is either canceled, or all listeners have run.
|
||||
Future<HookedServiceEvent> _emit(HookedServiceEvent event) async {
|
||||
|
@ -616,6 +700,17 @@ class HookedServiceEventDispatcher {
|
|||
return event;
|
||||
}
|
||||
|
||||
/// Returns a [Stream] containing all events fired by this dispatcher.
|
||||
///
|
||||
/// *NOTE*: Callbacks on the returned [Stream] cannot be guaranteed to run before other [listeners].
|
||||
/// Use this only if you need a read-only stream of events.
|
||||
Stream<HookedServiceEvent> asStream() {
|
||||
var ctrl = new StreamController<HookedServiceEvent>();
|
||||
_ctrl.add(ctrl);
|
||||
listen(ctrl.add);
|
||||
return ctrl.stream;
|
||||
}
|
||||
|
||||
/// Registers the listener to be called whenever an event is triggered.
|
||||
void listen(HookedServiceEventListener listener) {
|
||||
listeners.add(listener);
|
||||
|
|
|
@ -11,6 +11,7 @@ import 'angel_base.dart';
|
|||
import 'angel_http_exception.dart';
|
||||
import 'controller.dart';
|
||||
import 'fatal_error.dart';
|
||||
import 'hooked_service.dart';
|
||||
import 'request_context.dart';
|
||||
import 'response_context.dart';
|
||||
import 'routable.dart';
|
||||
|
@ -93,6 +94,11 @@ class Angel extends AngelBase {
|
|||
/// If the server is never started, they will never be called.
|
||||
final List<AngelConfigurer> justBeforeStart = [];
|
||||
|
||||
/// Plug-ins to be called right before server shutdown
|
||||
///
|
||||
/// If the server is never [close]d, they will never be called.
|
||||
final List<AngelConfigurer> justBeforeStop = [];
|
||||
|
||||
/// Always run before responses are sent.
|
||||
///
|
||||
/// These will only not run if an [AngelFatalError] occurs,
|
||||
|
@ -180,6 +186,31 @@ class Angel extends AngelBase {
|
|||
container.singleton(this);
|
||||
}
|
||||
|
||||
/// Shuts down the server, and closes any open [StreamController]s.
|
||||
Future<HttpServer> close() async {
|
||||
HttpServer server;
|
||||
|
||||
if (httpServer != null) {
|
||||
server = httpServer;
|
||||
await httpServer.close(force: true);
|
||||
}
|
||||
|
||||
_afterProcessed.close();
|
||||
_beforeProcessed.close();
|
||||
_fatalErrorStream.close();
|
||||
_onController.close();
|
||||
|
||||
await Future.forEach(services.keys, (Service service) async {
|
||||
if (service is HookedService) {
|
||||
await service.close();
|
||||
}
|
||||
});
|
||||
|
||||
for (var plugin in justBeforeStop) await plugin(this);
|
||||
|
||||
return server;
|
||||
}
|
||||
|
||||
@override
|
||||
void dumpTree(
|
||||
{callback(String tree),
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
name: angel_framework
|
||||
version: 1.0.0-dev.73
|
||||
version: 1.0.0-dev.74
|
||||
description: A high-powered HTTP server with DI, routing and more.
|
||||
author: Tobe O <thosakwe@gmail.com>
|
||||
homepage: https://github.com/angel-dart/angel_framework
|
||||
|
|
|
@ -24,6 +24,10 @@ main() {
|
|||
app.use('/books', new BookService());
|
||||
Todos = app.service("todos");
|
||||
|
||||
Todos.beforeAllStream().listen((e) {
|
||||
print('Fired ${e.eventName}! Data: ${e.data}; Params: ${e.params}');
|
||||
});
|
||||
|
||||
app.fatalErrorStream.listen((e) => throw e.error);
|
||||
|
||||
server = await app.startServer();
|
||||
|
|
Loading…
Reference in a new issue