Skip to content

Commit

Permalink
Fix account deletion sometimes failing because of optimistic locks (m…
Browse files Browse the repository at this point in the history
…astodon#16317)

* Fix account deletion sometimes failing because of optimistic locks

In some rare occasions[1], deleting accounts would fail with a
`StaleObjectError` exception.

Indeed, account deletion manually sets the `AccountStat` values without
handling cases where the optimistic locking on `AccountStat` would fail.

To my knowledge, with the rewrite of account counters in mastodon#15913, the
`DeleteAccountService` is now the only place that changes the counters in
a way that is not atomic.

Since in this specific case, we do not care about the previous values of the
account counters, it appears we don't need locking at all for this table
anymore.

[1]: https://discourse.joinmastodon.org/t/account-cant-be-deleted/3602

* Bump MAX_SUPPORTED_VERSION in maintenance script
  • Loading branch information
ClearlyClaire authored and chrisguida committed Feb 26, 2022
1 parent 055290d commit 1febf92
Show file tree
Hide file tree
Showing 5 changed files with 13 additions and 6 deletions.
3 changes: 2 additions & 1 deletion app/models/account_stat.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,11 @@
# created_at :datetime not null
# updated_at :datetime not null
# last_status_at :datetime
# lock_version :integer default(0), not null
#

class AccountStat < ApplicationRecord
self.locking_column = nil

belongs_to :account, inverse_of: :account_stat

update_index('accounts#account', :account)
Expand Down
2 changes: 0 additions & 2 deletions app/models/concerns/account_counters.rb
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ def update_count!(key, value)
ON CONFLICT (account_id) DO UPDATE
SET #{key} = account_stats.#{key} + :value,
last_status_at = now(),
lock_version = account_stats.lock_version + 1,
updated_at = now()
RETURNING id;
SQL
Expand All @@ -59,7 +58,6 @@ def update_count!(key, value)
VALUES (:account_id, :default_value, now(), now())
ON CONFLICT (account_id) DO UPDATE
SET #{key} = account_stats.#{key} + :value,
lock_version = account_stats.lock_version + 1,
updated_at = now()
RETURNING id;
SQL
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# frozen_string_literal: true

class RemoveLockVersionFromAccountStats < ActiveRecord::Migration[5.2]
def change
safety_assured do
remove_column :account_stats, :lock_version, :integer, null: false, default: 0
end
end
end
3 changes: 1 addition & 2 deletions db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema.define(version: 2021_05_07_001928) do
ActiveRecord::Schema.define(version: 2021_05_26_193025) do

# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
Expand Down Expand Up @@ -111,7 +111,6 @@
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.datetime "last_status_at"
t.integer "lock_version", default: 0, null: false
t.index ["account_id"], name: "index_account_stats_on_account_id", unique: true
end

Expand Down
2 changes: 1 addition & 1 deletion lib/mastodon/maintenance_cli.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def self.exit_on_failure?
end

MIN_SUPPORTED_VERSION = 2019_10_01_213028
MAX_SUPPORTED_VERSION = 2021_05_07_001928
MAX_SUPPORTED_VERSION = 2021_05_26_193025

# Stubs to enjoy ActiveRecord queries while not depending on a particular
# version of the code/database
Expand Down

0 comments on commit 1febf92

Please sign in to comment.