diff --git a/app/models/notification/bundle.rb b/app/models/notification/bundle.rb index 74a681888..84e1058cb 100644 --- a/app/models/notification/bundle.rb +++ b/app/models/notification/bundle.rb @@ -6,6 +6,7 @@ class Notification::Bundle < ApplicationRecord before_create :set_default_window scope :due, -> { pending.where("ends_at <= ?", Time.current) } + scope :containing, -> (notification) { where("starts_at <= ? AND ends_at >= ?", notification.created_at, notification.created_at) } class << self def deliver_all @@ -19,10 +20,6 @@ class Notification::Bundle < ApplicationRecord end end - def add(notification) - update! ends_at: [ ends_at, notification.created_at ].max - end - def notifications user.notifications.where(created_at: window) end diff --git a/app/models/user/notifiable.rb b/app/models/user/notifiable.rb index 0f6cf3b94..015186d15 100644 --- a/app/models/user/notifiable.rb +++ b/app/models/user/notifiable.rb @@ -8,12 +8,20 @@ module User::Notifiable def bundle(notification) transaction do - find_or_create_pending_bundle_for(notification).add(notification) + find_or_create_bundle_for(notification) end end private - def find_or_create_pending_bundle_for(notification) - notification_bundles.pending.last || notification_bundles.create!(starts_at: notification.created_at) + def find_or_create_bundle_for(notification) + find_bundle_for(notification) || create_bundle_for(notification) + end + + def find_bundle_for(notification) + notification_bundles.pending.containing(notification).last + end + + def create_bundle_for(notification) + notification_bundles.create!(starts_at: notification.created_at) end end diff --git a/db/migrate/20250826131458_remove_unique_constraint_from_notification_bundles_user_id.rb b/db/migrate/20250826131458_remove_unique_constraint_from_notification_bundles_user_id.rb new file mode 100644 index 000000000..d5c83236c --- /dev/null +++ b/db/migrate/20250826131458_remove_unique_constraint_from_notification_bundles_user_id.rb @@ -0,0 +1,6 @@ +class RemoveUniqueConstraintFromNotificationBundlesUserId < ActiveRecord::Migration[8.1] + def change + remove_index :notification_bundles, :user_id, unique: true + add_index :notification_bundles, %i[ ends_at status ] + end +end diff --git a/db/schema.rb b/db/schema.rb index c27e4b231..234dc517a 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[8.1].define(version: 2025_08_26_084559) do +ActiveRecord::Schema[8.1].define(version: 2025_08_26_131458) do create_table "accesses", force: :cascade do |t| t.datetime "accessed_at" t.integer "collection_id", null: false @@ -302,9 +302,9 @@ ActiveRecord::Schema[8.1].define(version: 2025_08_26_084559) do t.integer "status", default: 0, null: false t.datetime "updated_at", null: false t.integer "user_id", null: false + t.index ["ends_at", "status"], name: "index_notification_bundles_on_ends_at_and_status" t.index ["user_id", "starts_at", "ends_at"], name: "idx_on_user_id_starts_at_ends_at_7eae5d3ac5" t.index ["user_id", "status"], name: "index_notification_bundles_on_user_id_and_status" - t.index ["user_id"], name: "index_notification_bundles_on_user_id", unique: true end create_table "notifications", force: :cascade do |t| diff --git a/db/schema_cache.yml b/db/schema_cache.yml index 811f78807..434e9ad75 100644 --- a/db/schema_cache.yml +++ b/db/schema_cache.yml @@ -2352,10 +2352,11 @@ indexes: valid: true - !ruby/object:ActiveRecord::ConnectionAdapters::IndexDefinition table: notification_bundles - name: index_notification_bundles_on_user_id - unique: true + name: index_notification_bundles_on_ends_at_and_status + unique: false columns: - - user_id + - ends_at + - status lengths: {} orders: {} opclasses: {} @@ -2860,4 +2861,4 @@ indexes: comment: valid: true workflows: [] -version: 20250826084559 +version: 20250826131458