1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
|
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# This Source Code Form is "Incompatible With Secondary Licenses", as
# defined by the Mozilla Public License, v. 2.0.
package Bugzilla::Extension::Push::Backoff;
use 5.10.1;
use strict;
use warnings;
use base 'Bugzilla::Object';
use constant AUDIT_CREATES => 0;
use constant AUDIT_UPDATES => 0;
use constant AUDIT_REMOVES => 0;
use constant USE_MEMCACHED => 0;
use Bugzilla;
use Bugzilla::Logging;
use Bugzilla::Util;
#
# initialisation
#
use constant DB_TABLE => 'push_backoff';
use constant DB_COLUMNS => qw(
id
connector
next_attempt_ts
attempts
);
use constant UPDATE_COLUMNS => qw(
next_attempt_ts
attempts
);
use constant VALIDATORS => {
connector => \&_check_connector,
next_attempt_ts => \&_check_next_attempt_ts,
attempts => \&_check_attempts,
};
use constant LIST_ORDER => 'next_attempt_ts';
#
# accessors
#
sub connector { return $_[0]->{'connector'}; }
sub next_attempt_ts { return $_[0]->{'next_attempt_ts'}; }
sub attempts { return $_[0]->{'attempts'}; }
sub next_attempt_time {
my ($self) = @_;
if (!exists $self->{'next_attempt_time'}) {
$self->{'next_attempt_time'} = datetime_from($self->next_attempt_ts)->epoch;
}
return $self->{'next_attempt_time'};
}
#
# mutators
#
sub reset {
my ($self) = @_;
$self->{next_attempt_ts} = Bugzilla->dbh->selectrow_array('SELECT NOW()');
$self->{attempts} = 0;
INFO( sprintf 'resetting backoff for %s', $self->connector );
}
sub inc {
my ($self) = @_;
my $dbh = Bugzilla->dbh;
my $attempts = $self->attempts + 1;
my $seconds = $attempts <= 4 ? 5 ** $attempts : 15 * 60;
my ($date) = $dbh->selectrow_array("SELECT " . $dbh->sql_date_math('NOW()', '+', $seconds, 'SECOND'));
$self->{next_attempt_ts} = $date;
$self->{attempts} = $attempts;
INFO(
sprintf 'setting next attempt for %s to %s (attempt %s)', $self->connector, $date, $attempts
);
}
#
# validators
#
sub _check_connector {
my ($invocant, $value) = @_;
Bugzilla->push_ext->connectors->exists($value) || ThrowCodeError('push_invalid_connector');
return $value;
}
sub _check_next_attempt_ts {
my ($invocant, $value) = @_;
return $value || Bugzilla->dbh->selectrow_array('SELECT NOW()');
}
sub _check_attempts {
my ($invocant, $value) = @_;
return $value || 0;
}
1;
|