Skip to content

Commit

Permalink
add event listeners to services in configuration
Browse files Browse the repository at this point in the history
By using the "on" attribute, we can add event callbacks to our services
at creation time. The events use the Beam::Emitter class.

Fixes #6
  • Loading branch information
preaction committed Feb 24, 2015
1 parent f23fe7e commit 0a1b453
Show file tree
Hide file tree
Showing 5 changed files with 137 additions and 0 deletions.
1 change: 1 addition & 0 deletions dist.ini
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ Module::Runtime = 0
Config::Any = 0.23
Data::DPath = 0.51 ; Fixes warning on perl 5.20
Throwable = 0
Beam::Emitter = 0

[Prereqs / TestRequires]
Test::More = 0
Expand Down
43 changes: 43 additions & 0 deletions lib/Beam/Wire.pm
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,29 @@ An C<eager> value will be created as soon as the container is created. If you
have an object that registers itself upon instantiation, you can make sure your
object is created as soon as possible by doing C<lifecycle: eager>.
=head4 on
Attach event listeners using L<Beam::Emitter|Beam::Emitter>.
emitter:
class: My::Emitter
on:
before_my_event:
$ref: listener
$method: on_before_my_event
my_event:
- $ref: listener
$method: on_my_event
- $ref: other_listener
$method: on_my_event
listener:
class: My::Listener
other_listener:
class: My::Listener
Now, when the C<emitter> fires off its events, they are dispatched to the
appropriate listeners.
=head3 Inner Containers
Beam::Wire objects can hold other Beam::Wire objects!
Expand Down Expand Up @@ -620,6 +643,26 @@ sub create_service {
my @args = $self->parse_args( @service_info{"class","args"} );
$service = $service_info{class}->$method( @args );
}

if ( $service_info{on} ) {
my %meta = $self->get_meta_names;
for my $event ( keys %{ $service_info{on} } ) {
my @listeners = ref $service_info{on}{$event} eq 'ARRAY'
? @{ $service_info{on}{$event} }
: $service_info{on}{$event}
;

for my $listener ( @listeners ) {
# XXX: Make $class and $extends work here
# XXX: Make $args prepend arguments to the listener
# XXX: Make $args also resolve refs
my $method = $listener->{ $meta{method} };
my $listen_svc = $self->get( $listener->{ $meta{ref} } );
$service->on( $event => sub { $listen_svc->$method( @_ ) } );
}
}
}

return $service;
}

Expand Down
69 changes: 69 additions & 0 deletions t/14_on_event.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@

use Test::More;
use Test::Exception;
use Test::Lib;
use Beam::Wire;

subtest 'single event listener' => sub {
my $wire = Beam::Wire->new(
config => {
emitter => {
class => 'My::Emitter',
on => {
greet => {
'$ref' => 'listener',
'$method' => 'on_greet',
},
},
},
listener => {
class => 'My::Listener',
},
},
);

my $svc;
lives_ok { $svc = $wire->get( 'emitter' ) };
isa_ok $svc, 'My::Emitter';

$svc->emit( 'greet' );
is $wire->get( 'listener' )->events_seen, 1;
};

subtest 'multiple event listeners' => sub {
my $wire = Beam::Wire->new(
config => {
emitter => {
class => 'My::Emitter',
on => {
greet => [
{
'$ref' => 'listener',
'$method' => 'on_greet',
},
{
'$ref' => 'other_listener',
'$method' => 'on_greet',
},
],
},
},
listener => {
class => 'My::Listener',
},
other_listener => {
class => 'My::Listener',
},
},
);

my $svc;
lives_ok { $svc = $wire->get( 'emitter' ) };
isa_ok $svc, 'My::Emitter';

$svc->emit( 'greet' );
is $wire->get( 'listener' )->events_seen, 1;
is $wire->get( 'other_listener' )->events_seen, 1;
};

done_testing;
7 changes: 7 additions & 0 deletions t/lib/My/Emitter.pm
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package
My::Emitter;

use Moo;
with 'Beam::Emitter';

1;
17 changes: 17 additions & 0 deletions t/lib/My/Listener.pm
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package
My::Listener;

use Moo;

has events_seen => (
is => 'rw',
default => sub { 0 },
);

sub on_greet {
my ( $self ) = @_;
$self->events_seen( $self->events_seen + 1 );
return;
}

1;

0 comments on commit 0a1b453

Please sign in to comment.