dawarich/app/services/users/import_data/notifications.rb

168 lines
4.9 KiB
Ruby
Raw Normal View History

2025-06-28 06:22:56 -04:00
# frozen_string_literal: true
class Users::ImportData::Notifications
2025-06-30 14:29:47 -04:00
BATCH_SIZE = 1000
2025-06-28 06:22:56 -04:00
def initialize(user, notifications_data)
@user = user
@notifications_data = notifications_data
end
def call
return 0 unless notifications_data.is_a?(Array)
Rails.logger.info "Importing #{notifications_data.size} notifications for user: #{user.email}"
2025-06-30 14:29:47 -04:00
valid_notifications = filter_and_prepare_notifications
if valid_notifications.empty?
2025-06-30 16:51:25 -04:00
Rails.logger.info 'Notifications import completed. Created: 0'
2025-06-30 14:29:47 -04:00
return 0
end
deduplicated_notifications = filter_existing_notifications(valid_notifications)
if deduplicated_notifications.size < valid_notifications.size
Rails.logger.debug "Skipped #{valid_notifications.size - deduplicated_notifications.size} duplicate notifications"
end
total_created = bulk_import_notifications(deduplicated_notifications)
Rails.logger.info "Notifications import completed. Created: #{total_created}"
total_created
end
private
attr_reader :user, :notifications_data
def filter_and_prepare_notifications
valid_notifications = []
skipped_count = 0
2025-06-28 06:22:56 -04:00
notifications_data.each do |notification_data|
next unless notification_data.is_a?(Hash)
2025-06-30 14:29:47 -04:00
unless valid_notification_data?(notification_data)
skipped_count += 1
2025-06-28 06:22:56 -04:00
next
end
2025-06-30 14:29:47 -04:00
prepared_attributes = prepare_notification_attributes(notification_data)
valid_notifications << prepared_attributes if prepared_attributes
end
2025-06-28 06:22:56 -04:00
2025-06-30 14:29:47 -04:00
if skipped_count > 0
Rails.logger.warn "Skipped #{skipped_count} notifications with invalid or missing required data"
2025-06-28 06:22:56 -04:00
end
2025-06-30 14:29:47 -04:00
valid_notifications
2025-06-28 06:22:56 -04:00
end
2025-06-30 14:29:47 -04:00
def prepare_notification_attributes(notification_data)
attributes = notification_data.except('updated_at')
2025-06-28 06:22:56 -04:00
2025-06-30 14:29:47 -04:00
attributes['user_id'] = user.id
unless attributes['created_at'].present?
attributes['created_at'] = Time.current
end
attributes['updated_at'] = Time.current
attributes.symbolize_keys
rescue StandardError => e
Rails.logger.error "Failed to prepare notification attributes: #{e.message}"
Rails.logger.error "Notification data: #{notification_data.inspect}"
nil
end
def filter_existing_notifications(notifications)
return notifications if notifications.empty?
existing_notifications_lookup = {}
user.notifications.select(:title, :content, :created_at, :kind).each do |notification|
primary_key = [notification.title.strip, notification.content.strip]
exact_key = [notification.title.strip, notification.content.strip, normalize_timestamp(notification.created_at)]
existing_notifications_lookup[primary_key] = true
existing_notifications_lookup[exact_key] = true
end
filtered_notifications = notifications.reject do |notification|
title = notification[:title]&.strip
content = notification[:content]&.strip
primary_key = [title, content]
exact_key = [title, content, normalize_timestamp(notification[:created_at])]
if existing_notifications_lookup[primary_key] || existing_notifications_lookup[exact_key]
Rails.logger.debug "Notification already exists: #{notification[:title]}"
true
else
false
end
end
filtered_notifications
end
def normalize_timestamp(timestamp)
case timestamp
2025-06-30 16:51:25 -04:00
when String then Time.parse(timestamp).to_i
when Time, DateTime then timestamp.to_i
2025-06-30 14:29:47 -04:00
else
timestamp.to_s
end
rescue StandardError => e
Rails.logger.debug "Failed to normalize timestamp #{timestamp}: #{e.message}"
timestamp.to_s
end
def bulk_import_notifications(notifications)
total_created = 0
notifications.each_slice(BATCH_SIZE) do |batch|
begin
result = Notification.upsert_all(
batch,
returning: %w[id],
on_duplicate: :skip
)
batch_created = result.count
total_created += batch_created
Rails.logger.debug "Processed batch of #{batch.size} notifications, created #{batch_created}, total created: #{total_created}"
rescue StandardError => e
Rails.logger.error "Failed to process notification batch: #{e.message}"
Rails.logger.error "Batch size: #{batch.size}"
Rails.logger.error "Backtrace: #{e.backtrace.first(3).join('\n')}"
end
end
total_created
end
def valid_notification_data?(notification_data)
return false unless notification_data.is_a?(Hash)
unless notification_data['title'].present?
Rails.logger.error "Failed to create notification: Validation failed: Title can't be blank"
return false
end
unless notification_data['content'].present?
Rails.logger.error "Failed to create notification: Validation failed: Content can't be blank"
return false
end
true
rescue StandardError => e
Rails.logger.debug "Notification validation failed: #{e.message} for data: #{notification_data.inspect}"
false
end
2025-06-28 06:22:56 -04:00
end