Filename | /usr/local/libexec/sympa/Sympa/Spool/Listmaster.pm |
Statements | Executed 1382 statements in 1.50ms |
Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
---|---|---|---|---|---|
230 | 2 | 2 | 1.53ms | 1.83ms | flush | Sympa::Spool::Listmaster::
1 | 1 | 1 | 21µs | 21µs | _new_instance | Sympa::Spool::Listmaster::
0 | 0 | 0 | 0s | 0s | BEGIN@26 | Sympa::Spool::Listmaster::
0 | 0 | 0 | 0s | 0s | BEGIN@27 | Sympa::Spool::Listmaster::
0 | 0 | 0 | 0s | 0s | BEGIN@29 | Sympa::Spool::Listmaster::
0 | 0 | 0 | 0s | 0s | BEGIN@30 | Sympa::Spool::Listmaster::
0 | 0 | 0 | 0s | 0s | BEGIN@31 | Sympa::Spool::Listmaster::
0 | 0 | 0 | 0s | 0s | BEGIN@32 | Sympa::Spool::Listmaster::
0 | 0 | 0 | 0s | 0s | BEGIN@33 | Sympa::Spool::Listmaster::
0 | 0 | 0 | 0s | 0s | BEGIN@34 | Sympa::Spool::Listmaster::
0 | 0 | 0 | 0s | 0s | BEGIN@36 | Sympa::Spool::Listmaster::
0 | 0 | 0 | 0s | 0s | __ANON__ (xsub) | Sympa::Spool::Listmaster::
0 | 0 | 0 | 0s | 0s | store | Sympa::Spool::Listmaster::
Line | State ments |
Time on line |
Calls | Time in subs |
Code |
---|---|---|---|---|---|
1 | # -*- indent-tabs-mode: nil; -*- | ||||
2 | # vim:ft=perl:et:sw=4 | ||||
3 | # $Id$ | ||||
4 | |||||
5 | # Sympa - SYsteme de Multi-Postage Automatique | ||||
6 | # | ||||
7 | # Copyright 2019 The Sympa Community. See the AUTHORS.md file at | ||||
8 | # the top-level directory of this distribution and at | ||||
9 | # <https://github.com/sympa-community/sympa.git>. | ||||
10 | # | ||||
11 | # This program is free software; you can redistribute it and/or modify | ||||
12 | # it under the terms of the GNU General Public License as published by | ||||
13 | # the Free Software Foundation; either version 2 of the License, or | ||||
14 | # (at your option) any later version. | ||||
15 | # | ||||
16 | # This program is distributed in the hope that it will be useful, | ||||
17 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||
19 | # GNU General Public License for more details. | ||||
20 | # | ||||
21 | # You should have received a copy of the GNU General Public License | ||||
22 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | ||||
23 | |||||
24 | package Sympa::Spool::Listmaster; | ||||
25 | |||||
26 | use strict; | ||||
27 | use warnings; | ||||
28 | |||||
29 | use Sympa; | ||||
30 | use Conf; | ||||
31 | use Sympa::Log; | ||||
32 | use Sympa::Mailer; | ||||
33 | use Sympa::Message::Template; | ||||
34 | use Sympa::Spool::Outgoing; | ||||
35 | |||||
36 | use base qw(Class::Singleton); | ||||
37 | |||||
38 | my $log = Sympa::Log->instance; | ||||
39 | |||||
40 | # Constructor for Class::Singleton. | ||||
41 | # spent 21µs within Sympa::Spool::Listmaster::_new_instance which was called:
# once (21µs+0s) by Class::Singleton::instance at line 61 of Class/Singleton.pm | ||||
42 | 1 | 1µs | my $class = shift; | ||
43 | |||||
44 | 1 | 17µs | bless { | ||
45 | use_bulk => undef, | ||||
46 | _stack => {}, | ||||
47 | } => $class; | ||||
48 | } | ||||
49 | |||||
50 | sub store { | ||||
51 | my $self = shift; | ||||
52 | my $message = shift; | ||||
53 | my $rcpt = shift; | ||||
54 | my %options = @_; | ||||
55 | |||||
56 | my $mailer = | ||||
57 | $self->{use_bulk} | ||||
58 | ? Sympa::Spool::Outgoing->new | ||||
59 | : Sympa::Mailer->instance; | ||||
60 | my $operation = $options{operation}; | ||||
61 | |||||
62 | my $robot_id; | ||||
63 | if (ref $message->{context} eq 'Sympa::List') { | ||||
64 | $robot_id = $message->{context}->{'domain'}; | ||||
65 | } elsif ($message->{context} and $message->{context} ne '*') { | ||||
66 | $robot_id = $message->{context}; | ||||
67 | } else { | ||||
68 | $robot_id = '*'; | ||||
69 | } | ||||
70 | |||||
71 | $self->{_stack}->{$robot_id}{$operation}{'first'} = time | ||||
72 | unless $self->{_stack}->{$robot_id}{$operation}{'first'}; | ||||
73 | $self->{_stack}->{$robot_id}{$operation}{'counter'}++; | ||||
74 | $self->{_stack}->{$robot_id}{$operation}{'last'} = time; | ||||
75 | |||||
76 | if ($self->{_stack}->{$robot_id}{$operation}{'counter'} > 3) { | ||||
77 | my @rcpts = ref $rcpt ? @$rcpt : ($rcpt); | ||||
78 | |||||
79 | # stack if too much messages w/ same code | ||||
80 | $log->syslog('info', 'Stacking message about "%s" for %s (%s)', | ||||
81 | $operation, join(', ', @rcpts), $robot_id) | ||||
82 | unless $operation eq 'logs_failed'; | ||||
83 | foreach my $rcpt (@rcpts) { | ||||
84 | push @{$self->{_stack}->{$robot_id}{$operation}{'messages'}{$rcpt} | ||||
85 | }, | ||||
86 | $message->as_string; | ||||
87 | } | ||||
88 | return 1; | ||||
89 | } else { | ||||
90 | # Overwrite envelope sender | ||||
91 | $message->{envelope_sender} = Sympa::get_address($robot_id, 'owner'); | ||||
92 | #FIXME: Priority would better to be '0', isn't it? | ||||
93 | $message->{priority} = | ||||
94 | Conf::get_robot_conf($robot_id, 'sympa_priority'); | ||||
95 | |||||
96 | return $mailer->store($message, $rcpt); | ||||
97 | } | ||||
98 | } | ||||
99 | |||||
100 | # spent 1.83ms (1.53+295µs) within Sympa::Spool::Listmaster::flush which was called 230 times, avg 8µs/call:
# 229 times (1.52ms+293µs) by Sympa::Spindle::ProcessTask::_init at line 56 of /usr/local/libexec/sympa/Sympa/Spindle/ProcessTask.pm, avg 8µs/call
# once (12µs+2µs) by main::RUNTIME at line 157 of /usr/local/libexec/sympa/task_manager-debug.pl | ||||
101 | 230 | 43µs | my $self = shift; | ||
102 | 230 | 82µs | my %options = @_; | ||
103 | |||||
104 | my $mailer = | ||||
105 | $self->{use_bulk} | ||||
106 | 230 | 539µs | 230 | 295µs | ? Sympa::Spool::Outgoing->new # spent 295µs making 230 calls to Class::Singleton::instance, avg 1µs/call |
107 | : Sympa::Mailer->instance; | ||||
108 | 230 | 87µs | my $purge = $options{purge}; | ||
109 | |||||
110 | 230 | 266µs | foreach my $robot_id (keys %{$self->{_stack}}) { | ||
111 | foreach my $operation (keys %{$self->{_stack}->{$robot_id}}) { | ||||
112 | my $first_age = | ||||
113 | time - $self->{_stack}->{$robot_id}{$operation}{'first'}; | ||||
114 | my $last_age = | ||||
115 | time - $self->{_stack}->{$robot_id}{$operation}{'last'}; | ||||
116 | # not old enough to send and first not too old | ||||
117 | next | ||||
118 | unless $purge | ||||
119 | or $last_age > 30 | ||||
120 | or $first_age > 60; | ||||
121 | next | ||||
122 | unless $self->{_stack}->{$robot_id}{$operation}{'messages'}; | ||||
123 | |||||
124 | my %messages = | ||||
125 | %{$self->{_stack}->{$robot_id}{$operation}{'messages'}}; | ||||
126 | $log->syslog( | ||||
127 | 'info', 'Got messages about "%s" (%s)', | ||||
128 | $operation, join(', ', keys %messages) | ||||
129 | ); | ||||
130 | |||||
131 | ##### bulk send | ||||
132 | foreach my $rcpt (keys %messages) { | ||||
133 | my $param = { | ||||
134 | to => $rcpt, | ||||
135 | auto_submitted => 'auto-generated', | ||||
136 | operation => $operation, | ||||
137 | notification_messages => $messages{$rcpt}, | ||||
138 | boundary => '----------=_' | ||||
139 | . Sympa::unique_message_id($robot_id) | ||||
140 | }; | ||||
141 | |||||
142 | $log->syslog('info', 'Send messages to %s', $rcpt); | ||||
143 | |||||
144 | # Skip DB access because DB is not accessible | ||||
145 | $rcpt = [$rcpt] | ||||
146 | if $operation eq 'missing_dbd' | ||||
147 | or $operation eq 'no_db' | ||||
148 | or $operation eq 'db_restored'; | ||||
149 | |||||
150 | my $message = Sympa::Message::Template->new( | ||||
151 | context => $robot_id, | ||||
152 | template => 'listmaster_groupednotifications', | ||||
153 | rcpt => $rcpt, | ||||
154 | data => $param | ||||
155 | ); | ||||
156 | unless ($message) { | ||||
157 | $log->syslog( | ||||
158 | 'notice', | ||||
159 | 'Unable to send template "listmaster_groupnotification" to %s listmaster %s', | ||||
160 | $robot_id, | ||||
161 | $rcpt | ||||
162 | ) unless $operation eq 'logs_failed'; | ||||
163 | return undef; | ||||
164 | } | ||||
165 | unless (defined $mailer->store($message, $rcpt)) { | ||||
166 | $log->syslog( | ||||
167 | 'notice', | ||||
168 | 'Unable to send template "listmaster_groupnotification" to %s listmaster %s', | ||||
169 | $robot_id, | ||||
170 | $rcpt | ||||
171 | ) unless $operation eq 'logs_failed'; | ||||
172 | return undef; | ||||
173 | } | ||||
174 | } | ||||
175 | |||||
176 | $log->syslog('info', 'Cleaning stacked notifications'); | ||||
177 | delete $self->{_stack}->{$robot_id}{$operation}; | ||||
178 | } | ||||
179 | } | ||||
180 | 230 | 467µs | return 1; | ||
181 | } | ||||
182 | |||||
183 | 1; | ||||
184 | |||||
185 | __END__ |