summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorByron Jones <glob@mozilla.com>2015-03-25 17:02:28 +0100
committerByron Jones <glob@mozilla.com>2015-03-25 17:02:28 +0100
commit0f2b7793d5636996e7ec61206029a293eebbf73e (patch)
tree8040dc1af921d08024cdcebfabf19d973c135ef2
parent03a2eace7ee39b378e1cc308b51b93f34a2e0ede (diff)
downloadbugzilla-0f2b7793d5636996e7ec61206029a293eebbf73e.tar.gz
bugzilla-0f2b7793d5636996e7ec61206029a293eebbf73e.tar.xz
Bug 1138767: retry and/or avoid push_notify deadlocks
-rw-r--r--Bugzilla.pm3
-rw-r--r--extensions/ZPushNotify/Extension.pm44
2 files changed, 42 insertions, 5 deletions
diff --git a/Bugzilla.pm b/Bugzilla.pm
index cd6cc7a37..afaf77395 100644
--- a/Bugzilla.pm
+++ b/Bugzilla.pm
@@ -741,6 +741,9 @@ sub _cleanup {
Bugzilla->metrics->finish();
}
+ # BMO - allow "end of request" processing
+ Bugzilla::Hook::process('request_cleanup');
+
my $main = Bugzilla->request_cache->{dbh_main};
my $shadow = Bugzilla->request_cache->{dbh_shadow};
foreach my $dbh ($main, $shadow) {
diff --git a/extensions/ZPushNotify/Extension.pm b/extensions/ZPushNotify/Extension.pm
index e31380cfe..2b6c1aeaa 100644
--- a/extensions/ZPushNotify/Extension.pm
+++ b/extensions/ZPushNotify/Extension.pm
@@ -20,11 +20,45 @@ use Bugzilla;
sub _notify {
my ($bug_id, $delta_ts) = @_;
- Bugzilla->dbh->do(
- "REPLACE INTO push_notify(bug_id, delta_ts) VALUES(?, ?)",
- undef,
- $bug_id, $delta_ts
- );
+ # beacuse the push_notify table is hot, we defer updating it until the
+ # request has completed. this ensures we are outside the scope of any
+ # transaction blocks.
+
+ my $stash = Bugzilla->request_cache->{ZPushNotify_stash} ||= [];
+ push @$stash, { bug_id => $bug_id, delta_ts => $delta_ts };
+}
+
+sub request_cleanup {
+ my $stash = Bugzilla->request_cache->{ZPushNotify_stash}
+ || return;
+
+ my $dbh = Bugzilla->dbh;
+ foreach my $rh (@$stash) {
+ # using REPLACE INTO or INSERT .. ON DUPLICATE KEY UPDATE results in a
+ # lock on the bugs table due to the FK. this way is more verbose but
+ # only locks the push_notify table.
+ $dbh->bz_start_transaction();
+ my ($id) = $dbh->selectrow_array(
+ "SELECT id FROM push_notify WHERE bug_id=?",
+ undef,
+ $rh->{bug_id}
+ );
+ if ($id) {
+ $dbh->do(
+ "UPDATE push_notify SET delta_ts=? WHERE id=?",
+ undef,
+ $rh->{delta_ts}, $id
+ );
+ }
+ else {
+ $dbh->do(
+ "INSERT INTO push_notify (bug_id, delta_ts) VALUES (?, ?)",
+ undef,
+ $rh->{bug_id}, $rh->{delta_ts}
+ );
+ }
+ $dbh->bz_commit_transaction();
+ }
}
#