diff options
author | Byron Jones <glob@mozilla.com> | 2015-03-25 17:02:28 +0100 |
---|---|---|
committer | Byron Jones <glob@mozilla.com> | 2015-03-25 17:02:28 +0100 |
commit | 0f2b7793d5636996e7ec61206029a293eebbf73e (patch) | |
tree | 8040dc1af921d08024cdcebfabf19d973c135ef2 | |
parent | 03a2eace7ee39b378e1cc308b51b93f34a2e0ede (diff) | |
download | bugzilla-0f2b7793d5636996e7ec61206029a293eebbf73e.tar.gz bugzilla-0f2b7793d5636996e7ec61206029a293eebbf73e.tar.xz |
Bug 1138767: retry and/or avoid push_notify deadlocks
-rw-r--r-- | Bugzilla.pm | 3 | ||||
-rw-r--r-- | extensions/ZPushNotify/Extension.pm | 44 |
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(); + } } # |