File Coverage

blib/lib/Alice/MessageStore.pm
Criterion Covered Total %
statement 17 44 38.6
branch 0 6 0.0
condition n/a
subroutine 6 16 37.5
pod 1 6 16.6
total 24 72 33.3


line stmt bran cond sub pod time code
1             package Alice::MessageStore;
2              
3 2     2   1758 use AnyEvent::DBI;
  2         50024  
  2         79  
4 2     2   25 use List::Util qw/min/;
  2         6  
  2         199  
5 2     2   13 use Any::Moose;
  2         4  
  2         25  
6 2     2   1287 use JSON;
  2         6  
  2         19  
7              
8             has insert => (
9             is => 'rw',
10             default => sub {[]},
11             );
12              
13             has trim => (
14             is => 'rw',
15             default => sub {{}},
16             );
17              
18             has backlog => (
19             is => 'ro',
20             default => 5000,
21             );
22              
23             has 'trim_timer' => (
24             is => 'ro',
25             default => sub {
26             my $self = shift;
27             AE::timer 60, 60, sub{$self->do_trim};
28             }
29             );
30              
31             has dsn => (
32             is => 'ro',
33             required => 1,
34             );
35              
36             has dbi => (
37             is => 'ro',
38             lazy => 1,
39             default => sub {
40             my $self = shift;
41             AnyEvent::DBI->new(@{$self->dsn});
42             }
43             );
44              
45             has msgid => (
46             is => 'rw',
47             default => 0,
48             );
49              
50             sub BUILD {
51 1     1 1 82 my $self = shift;
52             $self->dbi->exec("SELECT msgid FROM window_buffer ORDER BY msgid DESC LIMIT 1", sub {
53 0     0   0 my (undef, $row) = @_;
54 0 0       0 $self->msgid( @$row ? $row->[0][0] : 0);
55 1         8 });
56             }
57              
58             sub clear {
59 0     0 0 0 my ($self, $id) = @_;
60 0     0   0 $self->dbi->exec("DELETE FROM window_buffer WHERE window_id = ?", $id, sub {});
  0         0  
61             }
62              
63             sub messages {
64 0     0 0 0 my ($self, $id, $max, $min, $limit, $cb) = @_;
65              
66             $self->dbi->exec(
67             "SELECT message FROM window_buffer WHERE window_id=? " .
68             "AND msgid <= ? AND msgid >= ? ORDER BY msgid DESC LIMIT ?",
69             $id, $max, $min, $limit,
70 0     0   0 sub { $cb->([map {decode_json $_->[0]} reverse @{$_[1]}]) }
  0         0  
  0         0  
71 0         0 );
72             }
73              
74             sub add {
75 1     1 0 3 my ($self, $id, $message) = @_;
76              
77             $self->dbi->exec(
78             "INSERT INTO window_buffer (window_id,msgid,message) VALUES (?,?,?)",
79 1     0   84 $id, $message->{msgid}, encode_json($message), sub {});
  0         0  
80              
81 1         116 $self->trim->{$id} = 1;
82             }
83              
84             sub do_trim {
85 0     0 0   my $self = shift;
86              
87 0           my @trim = keys %{$self->trim};
  0            
88 0           $self->trim({});
89              
90 0           my $idle_w; $idle_w = AE::idle sub {
91 0 0   0     if (my $window_id = shift @trim) {
92 0           $self->trim_id($window_id);
93             }
94             else {
95 0           undef $idle_w;
96             }
97 0           };
98             }
99              
100             sub trim_id {
101 0     0 0   my ($self, $window_id) = @_;
102             $self->dbi->exec(
103             "SELECT msgid FROM window_buffer WHERE window_id=? ORDER BY msgid DESC LIMIT ?,1",
104             $window_id, $self->backlog, sub {
105 0     0     my $rows = $_[1];
106 0 0         if (@$rows) {
107 0           my $minid = $rows->[0][0];
108             $self->dbi->exec(
109             "DELETE FROM window_buffer WHERE window_id=? AND msgid < ?",
110 0           $window_id, $minid, sub{}
111 0           );
112             }
113             }
114 0           );
115             }
116              
117             __PACKAGE__->meta->make_immutable;
118             1;