Add a new join model to link summaries with users
So that changing the set of events does not result in not being able to find a generated highlight summary
This commit is contained in:
@@ -3,6 +3,8 @@
|
||||
# so that we reuse the same summary for users with different time zones or different accesses as long as the activity
|
||||
# is the same. This is important to keep AI costs down.
|
||||
class PeriodHighlights < ApplicationRecord
|
||||
has_many :weekly_highlights, class_name: "User::WeeklyHighlights", dependent: :destroy
|
||||
|
||||
class << self
|
||||
def create_or_find_for(collections, starts_at:, duration: 1.week)
|
||||
self.for(collections, starts_at:, duration:) || create_for(collections, starts_at:, duration:)
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
module User::Highlights
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
has_many :weekly_highlights, class_name: "User::WeeklyHighlights", dependent: :destroy
|
||||
end
|
||||
|
||||
class_methods do
|
||||
def generate_all_weekly_highlights_later
|
||||
User::Highlights::GenerateAllJob.perform_later
|
||||
@@ -15,20 +19,31 @@ module User::Highlights
|
||||
|
||||
def generate_weekly_highlights(date = Time.current)
|
||||
in_time_zone do
|
||||
date = date - 1.day if date.sunday?
|
||||
PeriodHighlights.create_or_find_for collections, starts_at: highlights_starts_at(date), duration: 1.week
|
||||
weekly_highlights_for(date) || create_weekly_highlights_for(date)
|
||||
end
|
||||
end
|
||||
|
||||
def weekly_highlights_for(date)
|
||||
in_time_zone do
|
||||
PeriodHighlights.for(collections, starts_at: highlights_starts_at(date), duration: 1.week)
|
||||
weekly_highlights.find_by(starts_at: highlights_starts_at(date))&.period_highlights
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def create_weekly_highlights_for(date)
|
||||
date = date - 1.day if date.sunday?
|
||||
|
||||
# Outside of transaction as generating highlights can be a slow operation
|
||||
PeriodHighlights.create_or_find_for(collections, starts_at: highlights_starts_at(date), duration: 1.week).tap do |period_highlights|
|
||||
if period_highlights
|
||||
puts "Generating highlights for #{date}: #{period_highlights.inspect}"
|
||||
weekly_highlights.create! period_highlights: period_highlights, starts_at: highlights_starts_at(date)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def highlights_starts_at(date = Time.current)
|
||||
date = date.in_time_zone(timezone)
|
||||
date.beginning_of_week(:sunday)
|
||||
date.beginning_of_week(:sunday).to_date
|
||||
end
|
||||
end
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
# This acts as a join table between users and period_highlights so that we can reuse the
|
||||
# same highlights for different users.
|
||||
class User::WeeklyHighlights < ApplicationRecord
|
||||
belongs_to :user
|
||||
belongs_to :period_highlights
|
||||
end
|
||||
@@ -1,3 +1,4 @@
|
||||
<p>REQUESTING WEEKLY HIGHLIGHTS FOR <%= day_timeline.week_starts_at %>: <%= day_timeline.week_starts_at - 1.week%></p>
|
||||
<% if day_timeline.has_weekly_highlights? %>
|
||||
<h2 class="events__day-header">
|
||||
<span class="events__day-time min-width max-width">
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
class CreateUserHighlights < ActiveRecord::Migration[8.1]
|
||||
def change
|
||||
create_table :user_weekly_highlights do |t|
|
||||
t.references :user, null: false, foreign_key: true
|
||||
t.references :period_highlights, null: false, foreign_key: true
|
||||
t.date :starts_at, null: false
|
||||
|
||||
t.timestamps
|
||||
|
||||
t.index %i[ user_id starts_at ], unique: true
|
||||
end
|
||||
end
|
||||
end
|
||||
Generated
+14
-1
@@ -10,7 +10,7 @@
|
||||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema[8.1].define(version: 2025_10_03_205559) do
|
||||
ActiveRecord::Schema[8.1].define(version: 2025_10_06_091442) do
|
||||
create_table "accesses", force: :cascade do |t|
|
||||
t.datetime "accessed_at"
|
||||
t.integer "collection_id", null: false
|
||||
@@ -447,6 +447,17 @@ ActiveRecord::Schema[8.1].define(version: 2025_10_03_205559) do
|
||||
t.index ["user_id"], name: "index_user_settings_on_user_id"
|
||||
end
|
||||
|
||||
create_table "user_weekly_highlights", force: :cascade do |t|
|
||||
t.datetime "created_at", null: false
|
||||
t.integer "period_highlights_id", null: false
|
||||
t.date "starts_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.integer "user_id", null: false
|
||||
t.index ["period_highlights_id"], name: "index_user_weekly_highlights_on_period_highlights_id"
|
||||
t.index ["user_id", "starts_at"], name: "index_user_weekly_highlights_on_user_id_and_starts_at", unique: true
|
||||
t.index ["user_id"], name: "index_user_weekly_highlights_on_user_id"
|
||||
end
|
||||
|
||||
create_table "users", force: :cascade do |t|
|
||||
t.boolean "active", default: true, null: false
|
||||
t.datetime "created_at", null: false
|
||||
@@ -548,6 +559,8 @@ ActiveRecord::Schema[8.1].define(version: 2025_10_03_205559) do
|
||||
add_foreign_key "taggings", "cards"
|
||||
add_foreign_key "taggings", "tags"
|
||||
add_foreign_key "user_settings", "users"
|
||||
add_foreign_key "user_weekly_highlights", "period_highlights", column: "period_highlights_id"
|
||||
add_foreign_key "user_weekly_highlights", "users"
|
||||
add_foreign_key "watches", "cards"
|
||||
add_foreign_key "watches", "users"
|
||||
add_foreign_key "webhook_delinquency_trackers", "webhooks"
|
||||
|
||||
+84
-7
@@ -464,12 +464,12 @@ columns:
|
||||
- !ruby/object:ActiveRecord::ConnectionAdapters::SQLite3::Column
|
||||
auto_increment:
|
||||
name: due_on
|
||||
cast_type: !ruby/object:ActiveRecord::Type::Date
|
||||
cast_type: &37 !ruby/object:ActiveRecord::Type::Date
|
||||
precision:
|
||||
scale:
|
||||
limit:
|
||||
timezone:
|
||||
sql_type_metadata: !ruby/object:ActiveRecord::ConnectionAdapters::SqlTypeMetadata
|
||||
sql_type_metadata: &38 !ruby/object:ActiveRecord::ConnectionAdapters::SqlTypeMetadata
|
||||
sql_type: date
|
||||
type: :date
|
||||
limit:
|
||||
@@ -1268,8 +1268,33 @@ columns:
|
||||
comment:
|
||||
- *9
|
||||
- *18
|
||||
user_weekly_highlights:
|
||||
- *5
|
||||
- *6
|
||||
- !ruby/object:ActiveRecord::ConnectionAdapters::SQLite3::Column
|
||||
auto_increment:
|
||||
name: period_highlights_id
|
||||
cast_type: *3
|
||||
sql_type_metadata: *4
|
||||
'null': false
|
||||
default:
|
||||
default_function:
|
||||
collation:
|
||||
comment:
|
||||
- !ruby/object:ActiveRecord::ConnectionAdapters::SQLite3::Column
|
||||
auto_increment:
|
||||
name: starts_at
|
||||
cast_type: *37
|
||||
sql_type_metadata: *38
|
||||
'null': false
|
||||
default:
|
||||
default_function:
|
||||
collation:
|
||||
comment:
|
||||
- *9
|
||||
- *18
|
||||
users:
|
||||
- &38 !ruby/object:ActiveRecord::ConnectionAdapters::SQLite3::Column
|
||||
- &40 !ruby/object:ActiveRecord::ConnectionAdapters::SQLite3::Column
|
||||
auto_increment:
|
||||
name: active
|
||||
cast_type: *32
|
||||
@@ -1353,7 +1378,7 @@ columns:
|
||||
comment:
|
||||
- *6
|
||||
- *9
|
||||
- &37 !ruby/object:ActiveRecord::ConnectionAdapters::SQLite3::Column
|
||||
- &39 !ruby/object:ActiveRecord::ConnectionAdapters::SQLite3::Column
|
||||
auto_increment:
|
||||
name: webhook_id
|
||||
cast_type: *3
|
||||
@@ -1407,9 +1432,9 @@ columns:
|
||||
collation:
|
||||
comment:
|
||||
- *9
|
||||
- *37
|
||||
- *39
|
||||
webhooks:
|
||||
- *38
|
||||
- *40
|
||||
- *24
|
||||
- *5
|
||||
- *6
|
||||
@@ -1533,6 +1558,7 @@ primary_keys:
|
||||
taggings: id
|
||||
tags: id
|
||||
user_settings: id
|
||||
user_weekly_highlights: id
|
||||
users: id
|
||||
watches: id
|
||||
webhook_delinquency_trackers: id
|
||||
@@ -1589,6 +1615,7 @@ data_sources:
|
||||
taggings: true
|
||||
tags: true
|
||||
user_settings: true
|
||||
user_weekly_highlights: true
|
||||
users: true
|
||||
watches: true
|
||||
webhook_delinquency_trackers: true
|
||||
@@ -3071,6 +3098,56 @@ indexes:
|
||||
nulls_not_distinct:
|
||||
comment:
|
||||
valid: true
|
||||
user_weekly_highlights:
|
||||
- !ruby/object:ActiveRecord::ConnectionAdapters::IndexDefinition
|
||||
table: user_weekly_highlights
|
||||
name: index_user_weekly_highlights_on_period_highlights_id
|
||||
unique: false
|
||||
columns:
|
||||
- period_highlights_id
|
||||
lengths: {}
|
||||
orders: {}
|
||||
opclasses: {}
|
||||
where:
|
||||
type:
|
||||
using:
|
||||
include:
|
||||
nulls_not_distinct:
|
||||
comment:
|
||||
valid: true
|
||||
- !ruby/object:ActiveRecord::ConnectionAdapters::IndexDefinition
|
||||
table: user_weekly_highlights
|
||||
name: index_user_weekly_highlights_on_user_id
|
||||
unique: false
|
||||
columns:
|
||||
- user_id
|
||||
lengths: {}
|
||||
orders: {}
|
||||
opclasses: {}
|
||||
where:
|
||||
type:
|
||||
using:
|
||||
include:
|
||||
nulls_not_distinct:
|
||||
comment:
|
||||
valid: true
|
||||
- !ruby/object:ActiveRecord::ConnectionAdapters::IndexDefinition
|
||||
table: user_weekly_highlights
|
||||
name: index_user_weekly_highlights_on_user_id_and_starts_at
|
||||
unique: true
|
||||
columns:
|
||||
- user_id
|
||||
- starts_at
|
||||
lengths: {}
|
||||
orders: {}
|
||||
opclasses: {}
|
||||
where:
|
||||
type:
|
||||
using:
|
||||
include:
|
||||
nulls_not_distinct:
|
||||
comment:
|
||||
valid: true
|
||||
users:
|
||||
- !ruby/object:ActiveRecord::ConnectionAdapters::IndexDefinition
|
||||
table: users
|
||||
@@ -3222,4 +3299,4 @@ indexes:
|
||||
comment:
|
||||
valid: true
|
||||
workflows: []
|
||||
version: 20251003205559
|
||||
version: 20251006091442
|
||||
|
||||
@@ -2,11 +2,12 @@
|
||||
|
||||
require_relative "../config/environment"
|
||||
|
||||
WEEKS_TO_BACKFILL = 10
|
||||
WEEKS_TO_BACKFILL = 3
|
||||
|
||||
ActiveRecord::Base.logger = Logger.new(File::NULL)
|
||||
|
||||
ApplicationRecord.with_each_tenant do |tenant|
|
||||
PeriodHighlights.destroy_all
|
||||
WEEKS_TO_BACKFILL.times do |index|
|
||||
User.active.find_each do |user|
|
||||
user.generate_weekly_highlights(Time.current - index.weeks)
|
||||
|
||||
Reference in New Issue
Block a user