improve pinned image reliability

This commit is contained in:
Andrew Brown 2025-07-11 01:18:55 -07:00
parent b045e47307
commit de2feb0122
3 changed files with 19 additions and 37 deletions

View File

@ -492,20 +492,32 @@ class ContentController < ApplicationController
# Are we pinning or unpinning?
new_pin_status = !@image.pinned
# Use update instead of update_column to trigger model callbacks
# The model callbacks will handle unpinning other images automatically
@image.update!(pinned: new_pin_status)
# If we're pinning this image, unpin all other images for this content first
# This prevents database locking issues from the model callbacks
if new_pin_status == true
# Unpin other image uploads for this content
ImageUpload.where(content_type: content.class.name, content_id: content.id, pinned: true)
.where.not(id: @image.id)
.update_all(pinned: false)
# Also unpin any basil commissions for this content
BasilCommission.where(entity_type: content.class.name, entity_id: content.id, pinned: true)
.update_all(pinned: false)
end
# Now update this image's pin status (without triggering callbacks that cause locks)
@image.update_column(:pinned, new_pin_status)
# Clear any cached images to ensure pinned images are shown
content.instance_variable_set(:@random_image_including_private_cache, nil)
content.instance_variable_set(:@pinned_public_image_cache, nil)
content.instance_variable_set(:@first_public_image_cache, nil)
# Return the updated status
# Return the updated status (use new_pin_status since update_column might not refresh the object)
render json: {
id: @image.id,
type: params[:image_type],
pinned: @image.pinned
pinned: new_pin_status
}
end

View File

@ -52,22 +52,7 @@ class BasilCommission < ApplicationRecord
# Use acts_as_list for ordering images
acts_as_list scope: [:entity_type, :entity_id]
# Add callback to ensure only one pinned image per entity
before_save :ensure_single_pinned_image, if: -> { pinned_changed? && pinned? }
# Note: Pin unpinning logic is handled in the controller to prevent database locking issues
private
# Ensures only one basil commission can be pinned per entity
def ensure_single_pinned_image
# Unpin other basil commissions for this entity
BasilCommission.where(entity_type: entity_type, entity_id: entity_id, pinned: true)
.where.not(id: id)
.update_all(pinned: false)
# Also unpin any image uploads for this entity
if entity.respond_to?(:image_uploads)
ImageUpload.where(content_type: entity_type, content_id: entity_id, pinned: true)
.update_all(pinned: false)
end
end
end

View File

@ -38,8 +38,7 @@ class ImageUpload < ApplicationRecord
# Use acts_as_list for ordering images
acts_as_list scope: [:content_type, :content_id]
# Add callback to ensure only one pinned image per content
before_save :ensure_single_pinned_image, if: -> { pinned_changed? && pinned? }
# Note: Pin unpinning logic is handled in the controller to prevent database locking issues
def delete_s3_image
# todo: put this in a task for faster delete response times
@ -47,18 +46,4 @@ class ImageUpload < ApplicationRecord
end
private
# Ensures only one image can be pinned per content item
def ensure_single_pinned_image
# Unpin other image uploads for this content
ImageUpload.where(content_type: content_type, content_id: content_id, pinned: true)
.where.not(id: id)
.update_all(pinned: false)
# Also unpin any basil commissions for this content
if content.respond_to?(:basil_commissions)
BasilCommission.where(entity_type: content_type, entity_id: content_id, pinned: true)
.update_all(pinned: false)
end
end
end