summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--app/models/status.rb1
-rw-r--r--app/models/status_trend.rb1
-rw-r--r--app/models/status_trend_highlight.rb27
-rw-r--r--app/models/trends/statuses.rb15
-rw-r--r--db/migrate/20230605085712_create_status_trend_highlights.rb13
-rw-r--r--db/schema.rb12
6 files changed, 68 insertions, 1 deletions
diff --git a/app/models/status.rb b/app/models/status.rb
index 67463b140b4..91a3249ff55 100644
--- a/app/models/status.rb
+++ b/app/models/status.rb
@@ -77,6 +77,7 @@ class Status < ApplicationRecord
has_one :status_stat, inverse_of: :status
has_one :poll, inverse_of: :status, dependent: :destroy
has_one :trend, class_name: 'StatusTrend', inverse_of: :status
+ has_one :trend_highlight, class_name: 'StatusTrendHighlight', inverse_of: :status
validates :uri, uniqueness: true, presence: true, unless: :local?
validates :text, presence: true, unless: -> { with_media? || reblog? }
diff --git a/app/models/status_trend.rb b/app/models/status_trend.rb
index b0f1b6942dd..ef9e861a718 100644
--- a/app/models/status_trend.rb
+++ b/app/models/status_trend.rb
@@ -18,4 +18,5 @@ class StatusTrend < ApplicationRecord
belongs_to :account
scope :allowed, -> { joins('INNER JOIN (SELECT account_id, MAX(score) AS max_score FROM status_trends GROUP BY account_id) AS grouped_status_trends ON status_trends.account_id = grouped_status_trends.account_id AND status_trends.score = grouped_status_trends.max_score').where(allowed: true) }
+ scope :below_rank, ->(rank) { where(arel_table[:rank].lteq(rank)) }
end
diff --git a/app/models/status_trend_highlight.rb b/app/models/status_trend_highlight.rb
new file mode 100644
index 00000000000..3c31a6e0b02
--- /dev/null
+++ b/app/models/status_trend_highlight.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+# == Schema Information
+#
+# Table name: status_trend_highlights
+#
+# id :bigint(8) not null, primary key
+# period :datetime not null
+# status_id :bigint(8) not null
+# account_id :bigint(8) not null
+# score :float default(0.0), not null
+# language :string
+#
+
+class StatusTrendHighlight < ApplicationRecord
+ belongs_to :status
+ belongs_to :account
+
+ def self.weekly(account)
+ Status.joins(:trend_highlight, :account)
+ .merge(Account.discoverable)
+ .where(arel_table[:period].gteq(1.week.ago))
+ .not_excluded_by_account(account)
+ .not_domain_blocked_by_account(account)
+ .reorder(Arel::Nodes::Case.new.when(arel_table[:language].in(account.chosen_languages || account.user_locale)).then(1).else(0).desc, score: :desc)
+ end
+end
diff --git a/app/models/trends/statuses.rb b/app/models/trends/statuses.rb
index 84bff9c0278..a186d90907f 100644
--- a/app/models/trends/statuses.rb
+++ b/app/models/trends/statuses.rb
@@ -60,6 +60,7 @@ class Trends::Statuses < Trends::Base
def refresh(at_time = Time.now.utc)
statuses = Status.where(id: (recently_used_ids(at_time) + StatusTrend.pluck(:status_id)).uniq).includes(:status_stat, :account)
calculate_scores(statuses, at_time)
+ store_highlights(at_time)
end
def request_review
@@ -123,4 +124,18 @@ class Trends::Statuses < Trends::Base
StatusTrend.connection.exec_update('UPDATE status_trends SET rank = t0.calculated_rank FROM (SELECT id, row_number() OVER w AS calculated_rank FROM status_trends WINDOW w AS (PARTITION BY language ORDER BY score DESC)) t0 WHERE status_trends.id = t0.id')
end
end
+
+ def store_highlights(at_time)
+ highlights = StatusTrend.allowed.below_rank(20)
+
+ highlights.find_each do |trend|
+ # Forced to resort to this monstrosity because upsert_all's on_duplicate option is only
+ # available starting with Rails 7...
+ StatusTrendHighlight.connection.exec_insert(<<~SQL.squish, nil, [[nil, at_time.beginning_of_day], [nil, trend.status_id], [nil, trend.account_id], [nil, trend.score], [nil, trend.language]])
+ INSERT INTO status_trend_highlights(period, status_id, account_id, score, language)
+ VALUES ($1, $2, $3, $4, $5)
+ ON CONFLICT (status_id) DO UPDATE SET score = GREATEST(status_trend_highlights.score, EXCLUDED.score)
+ SQL
+ end
+ end
end
diff --git a/db/migrate/20230605085712_create_status_trend_highlights.rb b/db/migrate/20230605085712_create_status_trend_highlights.rb
new file mode 100644
index 00000000000..09e55183ff6
--- /dev/null
+++ b/db/migrate/20230605085712_create_status_trend_highlights.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+class CreateStatusTrendHighlights < ActiveRecord::Migration[6.1]
+ def change
+ create_table :status_trend_highlights do |t| # rubocop:disable Rails/CreateTableWithTimestamps
+ t.datetime :period, null: false
+ t.bigint :status_id, null: false, index: { unique: true }
+ t.bigint :account_id, null: false, index: true
+ t.float :score, null: false, default: 0.0
+ t.string :language
+ end
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 9866b101495..1cd11d5c435 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: 2023_06_05_085711) do
+ActiveRecord::Schema.define(version: 2023_06_05_085712) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -934,6 +934,16 @@ ActiveRecord::Schema.define(version: 2023_06_05_085711) do
t.index ["status_id"], name: "index_status_stats_on_status_id", unique: true
end
+ create_table "status_trend_highlights", force: :cascade do |t|
+ t.datetime "period", null: false
+ t.bigint "status_id", null: false
+ t.bigint "account_id", null: false
+ t.float "score", default: 0.0, null: false
+ t.string "language"
+ t.index ["account_id"], name: "index_status_trend_highlights_on_account_id"
+ t.index ["status_id"], name: "index_status_trend_highlights_on_status_id", unique: true
+ end
+
create_table "status_trends", force: :cascade do |t|
t.bigint "status_id", null: false
t.bigint "account_id", null: false