rails6 Action Text의 비연관 이미지 데이터를 삭제합니다.

개시하다


Rails6의 새로운 기능 중 하나인 ActionText (풍부한 텍스트 내용과 편집을 간단하게 가져올 수 있음) 의 연결되지 않은 이미지 데이터는sidekiq를 통해 배경을 삭제합니다.
job 삭제를 실행하는 포스트 모델(후)과 실행하지 않는 아티컬 모델(글)을 비교합니다.

웹 페이지


GitHub


컨디션

  • Ruby 2.6.3
  • Rails 6.0.2
  • gem aws-sdk-s3 1.60.2
  • 문제점


    이것은 Action Text의 Post 모델과 Article 모델이 설치된 ER 그림입니다.

    active_storage_블로그에 업로드된 이미지가 저장됩니다. 발언이 끝났을 때 activestorage_actitachmentstext_rich_text와 관련된 정보를 저장합니다.
    하지만 그림을 올릴 때activestorage_블로그에 새로운 기록이 만들어졌고 관련이 없는 경우에도 계속 저장됩니다.
    다음은 sidekiq에서 job이 실행되지 않은 Artical 모델의 gif입니다.
    ↓화면상단에서activestorage_attachments, active_storage_블로그 표시

    이미지 Active Storage 추가 중지: Blob 수: 2 증가

    메시지


    관련이 없는 데이터를 삭제하는job을 만듭니다.
    app/jobs/delete_unreferenced_blob_job.rb
    class DeleteUnreferencedBlobJob < ApplicationJob
      sidekiq_options queue: :default, retry: 3
      require 'aws-sdk-s3' 
    
      def perform(*args)
        # 全Blobのidを取得
        blob_ids = ActiveStorage::Blob.pluck(:id)
        # 関連付けされているBlobの取得
        _blob_ids = ActiveStorage::Attachment.pluck(:blob_id).uniq
        # 関連付けされていないBlobの割り出し
        unreferenced_blob_ids = blob_ids - _blob_ids
        # 関連付けされていないBlobの画像ファイルを削除
        if Rails.env.production?
          s3 = Aws::S3::Resource.new(
            region: 'ap-northeast-1',
            credentials: Aws::Credentials.new(
              Rails.application.credentials.dig(:aws, :access_key_id),  # S3用アクセスキー
              Rails.application.credentials.dig(:aws, :secret_access_key)  # S3用シークレットアクセスキー
            )
          )
          bucket = s3.bucket('aws-on-rails6')
          unreferenced_blob_ids.each do |id|
            s3_file_key = ActiveStorage::Blob.find(id).key
            bucket.object(s3_file_key).delete
            bucket.objects({prefix: "variants/#{s3_file_key}"}).batch_delete!
          end
        end
        # 関連付けされていないBlobの削除
        ActiveStorage::Blob.where(id: unreferenced_blob_ids).delete_all
      end
    end
    
    공식 환경에서만 s3 이미지 파일을 삭제했습니다.
    이것은 Post 모형의save, update, delete에서 실행됩니다.
    posts_controller.rb
    def create
        if @post.save
                DeleteUnreferencedBlobJob.perform_later
                        .
                        .
    def update                                   
        if @post.update
                DeleteUnreferencedBlobJob.perform_later
                        .
                        .
    def destroy
        DeleteUndreferencedBlobJob.perform_later if @post.destroy
                        .
                        .
    
    
    나는 포스트 모델로 아까와 같은 일을 한다.

    ActiveStorage: Blob 수: 1, 삭제되었는지 확인!

    주의점


    만약 이것이 실현된다면 사용자 A가 이미지 첨부파일을 제작할 때 사용자 Bsave와 업데이트가 다른 위치를 차지한 경우 사용자 A의save 앞에 관련되지 않은 이미지 데이터도 사라지기 때문에 여러 사용자가 사용하는 서비스는 유지보수할 때 실행하는 것이 좋다.

    좋은 웹페이지 즐겨찾기