From 2c354e17694da744c6dc1ab19c14af3d456b28bb Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Thu, 21 Oct 2021 21:10:31 +0000 Subject: [PATCH] lei_mail_sync: mv_src: use transaction, check UNIQUE We need a transaction across two SQL statements so readers (which don't use flock) will see the result as atomic. This may help against some occasional test failures I'm seeing from t/lei-auto-watch.t and t/lei-watch.t, or make the problem more apparent. --- lib/PublicInbox/LeiMailSync.pm | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/PublicInbox/LeiMailSync.pm b/lib/PublicInbox/LeiMailSync.pm index e70cb5de..124eb969 100644 --- a/lib/PublicInbox/LeiMailSync.pm +++ b/lib/PublicInbox/LeiMailSync.pm @@ -182,16 +182,20 @@ sub mv_src { my ($self, $folder, $oidbin, $id, $newbn) = @_; my $lk = $self->lock_for_scope; my $fid = $self->{fmap}->{$folder} //= fid_for($self, $folder, 1); + $self->{dbh}->begin_work; my $sth = $self->{dbh}->prepare_cached(<<''); UPDATE blob2name SET name = ? WHERE fid = ? AND oidbin = ? AND name = ? - my $nr = $sth->execute($newbn, $fid, $oidbin, $$id); - if ($nr == 0) { # may race with a clear_src, ensure new value exists + # eval since unique constraint may fail due to race + my $nr = eval { $sth->execute($newbn, $fid, $oidbin, $$id) }; + if (!defined($nr) || $nr == 0) { # $nr may be `0E0' + # may race with a clear_src, ensure new value exists $sth = $self->{dbh}->prepare_cached(<<''); INSERT OR IGNORE INTO blob2name (oidbin, fid, name) VALUES (?, ?, ?) $sth->execute($oidbin, $fid, $newbn); } + $self->{dbh}->commit; } # read-only, iterates every oidbin + UID or name for a given folder -- 2.44.0