File Coverage

blib/lib/EventStore/Tiny/EventStream.pm
Criterion Covered Total %
statement 56 56 100.0
branch 18 18 100.0
condition n/a
subroutine 12 12 100.0
pod 8 8 100.0
total 94 94 100.0


line stmt bran cond sub pod time code
1             package EventStore::Tiny::EventStream;
2              
3 7     7   585 use strict;
  7         11  
  7         148  
4 7     7   26 use warnings;
  7         11  
  7         212  
5              
6             use Class::Tiny {
7 22         341 events => sub {[]},
8 7     7   26 };
  7         45  
  7         59  
9              
10             sub add_event {
11 249     249 1 1121 my ($self, $event) = @_;
12              
13             # Append event to internal list
14 249         253 push @{$self->events}, $event;
  249         2713  
15              
16             # Done
17 249         1003 return $event;
18             }
19              
20             sub size {
21 239     239 1 16432 my $self = shift;
22 239         255 return scalar @{$self->events};
  239         2909  
23             }
24              
25             sub first_timestamp {
26 42     42 1 4170 my $self = shift;
27 42 100       45 return unless @{$self->events};
  42         503  
28 41         604 return $self->events->[0]->timestamp;
29             }
30              
31             sub last_timestamp {
32 121     121 1 5461 my $self = shift;
33 121 100       131 return unless @{$self->events};
  121         1617  
34 118         1753 return $self->events->[$self->size - 1]->timestamp;
35             }
36              
37             sub apply_to {
38 37     37 1 5604 my ($self, $state, $logger) = @_;
39              
40             # Start with empty state by default
41 37 100       79 $state = {} unless defined $state;
42              
43             # Apply all events
44 37         47 $_->apply_to($state, $logger) for @{$self->events};
  37         513  
45              
46             # Done
47 37         122 return $state;
48             }
49              
50             sub substream {
51 4     4 1 6285 my ($self, $selector) = @_;
52              
53             # Default selector: take everything
54 4 100   3   11 $selector = sub {1} unless defined $selector;
  3         6  
55              
56             # Filter events
57 4         6 my @filtered = grep {$selector->($_)} @{$self->events};
  12         38  
  4         72  
58              
59             # Build new sub stream
60 4         15 return EventStore::Tiny::EventStream->new(events => \@filtered);
61             }
62              
63             sub before {
64 41     41 1 11090 my ($self, $timestamp) = @_;
65              
66             # Shorthand: stream is empty
67 41 100       77 return $self if $self->size == 0;
68              
69             # Shorthand: timestamp is earlier than our first timestamp
70 39 100       214 return EventStore::Tiny::EventStream->new
71             if $self->first_timestamp > $timestamp;
72              
73             # Shorthand: timestamp is our last timestamp
74 38 100       728 return $self if $timestamp == $self->last_timestamp;
75              
76             # Go left until the condition is true, then it's true for all earlier events
77 7         118 my $i = $#{$self->events};
  7         83  
78 7         99 $i-- while $self->events->[$i]->timestamp > $timestamp;
79              
80             # Create a new sliced event stream
81 7         349 my @before_events = @{$self->events}[0 .. $i];
  7         78  
82 7         48 return EventStore::Tiny::EventStream->new(events => \@before_events);
83             }
84              
85             sub after {
86 26     26 1 6006 my ($self, $timestamp) = @_;
87              
88             # Shorthand: stream is empty
89 26 100       52 return $self if $self->size == 0;
90              
91             # Shorthand: timestamp is later or equal to our last timestamp
92 25 100       148 return EventStore::Tiny::EventStream->new
93             if $self->last_timestamp <= $timestamp;
94              
95             # Go right until the condition is true, then it's true for all later events
96 14         254 my $i = 0;
97 14         167 $i++ while $self->events->[$i]->timestamp <= $timestamp;
98              
99             # Create a new sliced event stream
100 14         6040 my @after_events = @{$self->events}[$i .. $#{$self->events}];
  14         202  
  14         157  
101 14         127 return EventStore::Tiny::EventStream->new(events => \@after_events);
102             }
103              
104             1;
105              
106             =pod
107              
108             =encoding utf-8
109              
110             =head1 NAME
111              
112             EventStore::Tiny::EventStream
113              
114             =head1 REFERENCE
115              
116             EventStore::Tiny::Stream implements the following attributes and methods.
117              
118             =head2 events
119              
120             my $event17 = $stream->events->[16];
121              
122             Internal list representation (arrayref) of all events of this stream.
123              
124             =head2 add_event
125              
126             $stream->add_event($event);
127              
128             Adds an event to the stream.
129              
130             =head2 size
131              
132             my $event_count = $stream->size;
133              
134             Returns the number of events in this stream.
135              
136             =head2 first_timestamp
137              
138             my $start_ts = $stream->first_timestamp;
139              
140             Returns the timestamp of the first event of this stream.
141              
142             =head2 last_timestamp
143              
144             my $end_ts = $stream->last_timestamp;
145              
146             Returns the timestamp of the last event of this stream.
147              
148             =head2 apply_to
149              
150             my $state = $stream->apply_to(\%state);
151              
152             Applies the whole stream (all events one after another) to a given state (by default an empty hash). The state is changed by side-effect but is also returned.
153              
154             =head2 substream
155              
156             my $filtered = $stream->substream(sub {
157             my $event = shift;
158             return we_want($event);
159             });
160              
161             Creates a substream using a given filter. All events the given subref returns true for are selected for this substream.
162              
163             =head2 before
164              
165             my $pre_stream = $stream->before($timestamp);
166              
167             Returns a substream with all events before or at the same time of a given timestamp.
168              
169             =head2 after
170              
171             my $post_stream = $stream->after($timestamp);
172              
173             Returns a substream with all events after a given timestamp.
174              
175             =head1 SEE ALSO
176              
177             L
178              
179             =head1 COPYRIGHT AND LICENSE
180              
181             Copyright (c) 2018 Mirko Westermeier (mail: mirko@westermeier.de)
182              
183             Released under the MIT License (see LICENSE.txt for details).
184              
185             =cut