From 380adc30ed6b56c4174e6278b9ff7283695c4c1e Mon Sep 17 00:00:00 2001 From: rhymes Date: Mon, 15 Jun 2020 17:46:02 +0200 Subject: [PATCH] [deploy] Remove user_counters table (#8445) --- app/models/user.rb | 11 ------ app/models/user_counter.rb | 11 ------ app/serializers/hash_serializer.rb | 9 ----- .../20200612140153_drop_user_counters.rb | 12 ++++++ db/schema.rb | 12 +----- lib/tasks/counters.rake | 20 ---------- spec/factories/user_counters.rb | 6 --- spec/models/user_counter_spec.rb | 39 ------------------- spec/models/user_spec.rb | 1 - 9 files changed, 13 insertions(+), 108 deletions(-) delete mode 100644 app/models/user_counter.rb delete mode 100644 app/serializers/hash_serializer.rb create mode 100644 db/migrate/20200612140153_drop_user_counters.rb delete mode 100644 lib/tasks/counters.rake delete mode 100644 spec/factories/user_counters.rb delete mode 100644 spec/models/user_counter_spec.rb diff --git a/app/models/user.rb b/app/models/user.rb index fd8824915..9f03c8d9c 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -93,8 +93,6 @@ class User < ApplicationRecord has_many :tweets, dependent: :destroy has_many :webhook_endpoints, class_name: "Webhook::Endpoint", foreign_key: :user_id, inverse_of: :user, dependent: :delete_all - has_one :counters, class_name: "UserCounter", dependent: :destroy - mount_uploader :profile_image, ProfileImageUploader devise :omniauthable, :registerable, :database_authenticatable, :confirmable, :rememberable @@ -148,15 +146,6 @@ class User < ApplicationRecord alias_attribute :public_reactions_count, :reactions_count alias_attribute :subscribed_to_welcome_notifications?, :welcome_notifications - scope :with_this_week_comments, lambda { |number| - includes(:counters).joins(:counters).where("(user_counters.data -> 'comments_these_7_days')::int >= ?", number) - } - scope :with_previous_week_comments, lambda { |number| - includes(:counters).joins(:counters).where("(user_counters.data -> 'comments_prior_7_days')::int >= ?", number) - } - scope :top_commenters, lambda { |number = 10| - includes(:counters).order(Arel.sql("user_counters.data -> 'comments_these_7_days' DESC")).limit(number) - } scope :eager_load_serialized_data, -> { includes(:roles) } after_save :bust_cache diff --git a/app/models/user_counter.rb b/app/models/user_counter.rb deleted file mode 100644 index 05008d0a7..000000000 --- a/app/models/user_counter.rb +++ /dev/null @@ -1,11 +0,0 @@ -class UserCounter < ApplicationRecord - belongs_to :user - - serialize :data, HashSerializer - store_accessor :data, :comments_these_7_days, :comments_prior_7_days - - validates :user, presence: true, uniqueness: true - - validates :comments_these_7_days, numericality: { only_integer: true } - validates :comments_prior_7_days, numericality: { only_integer: true } -end diff --git a/app/serializers/hash_serializer.rb b/app/serializers/hash_serializer.rb deleted file mode 100644 index ee82af608..000000000 --- a/app/serializers/hash_serializer.rb +++ /dev/null @@ -1,9 +0,0 @@ -class HashSerializer - def self.dump(hash) - hash - end - - def self.load(hash) - (hash || {}).with_indifferent_access - end -end diff --git a/db/migrate/20200612140153_drop_user_counters.rb b/db/migrate/20200612140153_drop_user_counters.rb new file mode 100644 index 000000000..db7e26c36 --- /dev/null +++ b/db/migrate/20200612140153_drop_user_counters.rb @@ -0,0 +1,12 @@ +class DropUserCounters < ActiveRecord::Migration[6.0] + def change + drop_table :user_counters do |t| + t.references :user, index: { unique: true } + t.jsonb :data, null: false, default: {} + t.timestamps null: false + + t.foreign_key :users, on_delete: :cascade + t.index :data, using: :gin + end + end +end diff --git a/db/schema.rb b/db/schema.rb index 02d69cd02..70ec762a8 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2020_06_09_192545) do +ActiveRecord::Schema.define(version: 2020_06_12_140153) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -1121,15 +1121,6 @@ ActiveRecord::Schema.define(version: 2020_06_09_192545) do t.index ["blocked_id", "blocker_id"], name: "index_user_blocks_on_blocked_id_and_blocker_id", unique: true end - create_table "user_counters", force: :cascade do |t| - t.datetime "created_at", null: false - t.jsonb "data", default: {}, null: false - t.datetime "updated_at", null: false - t.bigint "user_id" - t.index ["data"], name: "index_user_counters_on_data", using: :gin - t.index ["user_id"], name: "index_user_counters_on_user_id", unique: true - end - create_table "user_optional_fields", force: :cascade do |t| t.datetime "created_at", null: false t.string "label", null: false @@ -1337,7 +1328,6 @@ ActiveRecord::Schema.define(version: 2020_06_09_192545) do add_foreign_key "tag_adjustments", "users", on_delete: :cascade add_foreign_key "user_blocks", "users", column: "blocked_id" add_foreign_key "user_blocks", "users", column: "blocker_id" - add_foreign_key "user_counters", "users", on_delete: :cascade add_foreign_key "user_optional_fields", "users" add_foreign_key "user_subscriptions", "users", column: "author_id" add_foreign_key "user_subscriptions", "users", column: "subscriber_id" diff --git a/lib/tasks/counters.rake b/lib/tasks/counters.rake deleted file mode 100644 index 7f7d0b793..000000000 --- a/lib/tasks/counters.rake +++ /dev/null @@ -1,20 +0,0 @@ -namespace :counters do - desc "Update users counters" - task :update_users, [:batch_size] => :environment do |_t, args| - batch_size = args.fetch(:batch_size, 1000).to_i - - # NOTE: we could bypass Rails by using SQL directly to compute the counts and update these columns - User.includes(:counters).select(:id).find_each(batch_size: batch_size) do |user| - user.build_counters unless user.counters - - relation = user.comments - - user.counters.comments_these_7_days = relation.where("created_at > ?", 7.days.ago).size - user.counters.comments_prior_7_days = relation. - where("created_at > ? AND created_at < ?", 14.days.ago, 7.days.ago). - size - - user.counters.save! - end - end -end diff --git a/spec/factories/user_counters.rb b/spec/factories/user_counters.rb deleted file mode 100644 index ef940fa57..000000000 --- a/spec/factories/user_counters.rb +++ /dev/null @@ -1,6 +0,0 @@ -FactoryBot.define do - factory :user_counter do - user - data { { comments_these_7_days: 0, comments_prior_7_days: 0 } } - end -end diff --git a/spec/models/user_counter_spec.rb b/spec/models/user_counter_spec.rb deleted file mode 100644 index 6cc7c3dbb..000000000 --- a/spec/models/user_counter_spec.rb +++ /dev/null @@ -1,39 +0,0 @@ -require "rails_helper" - -RSpec.describe UserCounter, type: :model do - let(:counters) { build(:user_counter) } - - describe "validations" do - describe "builtin validations" do - subject { build(:user_counter, user: create(:user)) } - - it { is_expected.to belong_to(:user) } - it { is_expected.to validate_presence_of(:user) } - it { is_expected.to validate_uniqueness_of(:user) } - end - - describe "#comments_these_7_days" do - it "is valid if comments_these_7_days is an integer" do - counters.comments_these_7_days = 1 - expect(counters).to be_valid - end - - it "is is not if comments_these_7_days is not an integer" do - counters.comments_these_7_days = 1.2 - expect(counters).not_to be_valid - end - end - - describe "#comments_prior_7_days" do - it "is valid if comments_prior_7_days is an integer" do - counters.comments_prior_7_days = 1 - expect(counters).to be_valid - end - - it "is is not if comments_prior_7_days is not an integer" do - counters.comments_prior_7_days = 1.2 - expect(counters).not_to be_valid - end - end - end -end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index a460f325e..bb38dc8f0 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -140,7 +140,6 @@ RSpec.describe User, type: :model do expect(fourth_field).not_to be_valid end - it { is_expected.to have_one(:counters).class_name("UserCounter").dependent(:destroy) } it { is_expected.not_to allow_value("#xyz").for(:bg_color_hex) } it { is_expected.not_to allow_value("#xyz").for(:text_color_hex) } it { is_expected.not_to allow_value("AcMe_1%").for(:username) }