Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Clear minio s3 bucket #612

Merged
merged 9 commits into from
Nov 13, 2024
39 changes: 39 additions & 0 deletions app/jobs/active_storage_clear_orphans_job.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# frozen_string_literal: true

class ActiveStorageClearOrphansJob < ApplicationJob
include ActionView::Helpers::NumberHelper
queue_as :default

def perform(**args)
limit = args[:limit] || 10_000
Rails.logger.info "Looking for orphan blobs in S3... (limit: #{limit})"
objects = ActiveStorage::Blob.service.bucket.objects
Rails.logger.info "Total files: #{objects.size}"

current_iteration = 0
sum = 0
orphans_count = 0
objects.each do |obj|
break if current_iteration >= limit

current_iteration += 1
next if ActiveStorage::Blob.exists?(key: obj.key)

sum += delete_object(obj)
orphans_count += 1
end

Rails.logger.info "Size: #{number_to_human_size(sum)} in #{orphans_count} files"
Rails.logger.info "Configuration limit is #{limit} files"
Rails.logger.info "Terminated task... "
end

private

def delete_object(obj)
Rails.logger.info "Removing orphan: #{obj.key}"
size = obj.size
obj.delete
size
end
end
4 changes: 4 additions & 0 deletions config/sidekiq.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,7 @@
cron: '0 1 * * *'
class: NotifyProgressInitiatives
queue: initiatives
ActiveStorageClearOrphans:
cron: '30 6 1 9 0' # Run at 06:30AM on 1st September
class: ActiveStorageClearOrphansJob
queue: default
2 changes: 1 addition & 1 deletion config/storage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ local:

scaleway:
service: S3
endpoint: https://<%= Rails.application.secrets.dig(:scaleway, :endpoint) %>
endpoint: <%= Rails.application.secrets.dig(:scaleway, :bucket_name) == "localhost" ? "http" : "https" %>://<%= Rails.application.secrets.dig(:scaleway, :endpoint) %>
access_key_id: <%= Rails.application.secrets.dig(:scaleway, :id) %>
secret_access_key: <%= Rails.application.secrets.dig(:scaleway, :token) %>
region: fr-par
Expand Down
43 changes: 42 additions & 1 deletion docker-compose.local.yml
Original file line number Diff line number Diff line change
@@ -1,20 +1,41 @@
services:
minio:
container_name: minio
image: "bitnami/minio:latest"
ports:
- "9000:9000"
- "9001:9001"
environment:
- MINIO_DEFAULT_BUCKETS=localhost
- MINIO_ROOT_USER=minioadmin
- MINIO_ROOT_PASSWORD=minioadmin
networks:
- minio_network
volumes:
- 'minio:/bitnami/minio/data'

database:
image: postgres
volumes:
- pg-data:/var/lib/postgresql/data
environment:
- POSTGRES_HOST_AUTH_METHOD=trust
networks:
- minio_network
memcached:
image: memcached
ports:
- "11211:11211"
networks:
- minio_network
redis:
image: redis
ports:
- "6379:6379"
volumes:
- redis-data:/var/lib/redis/data
networks:
- minio_network
sidekiq:
image: decidim-app:latest
command: [ "bundle", "exec", "sidekiq", "-C", "config/sidekiq.yml" ]
Expand All @@ -26,6 +47,7 @@ services:
- MEMCACHE_SERVERS=memcached:11211
- RAILS_SERVE_STATIC_FILES=true
- RAILS_LOG_TO_STDOUT=true
- RAILS_LOG_LEVEL=debug
- ASSET_HOST=localhost:3000
- FORCE_SSL=1
- ENABLE_LETTER_OPENER=1
Expand All @@ -41,13 +63,19 @@ services:
- GEOCODER_LOOKUP_API_KEY=${GEOCODER_LOOKUP_API_KEY}
- DEFAULT_LOCALE=${DEFAULT_LOCALE}
- AVAILABLE_LOCALES=${AVAILABLE_LOCALES}
- OBJECTSTORE_S3_HOST=minio:9000
- SCALEWAY_BUCKET_NAME=localhost
- SCALEWAY_ID=minioadmin
- SCALEWAY_TOKEN=minioadmin
depends_on:
- app
volumes:
- shared-volume:/app
links:
- database
- redis
networks:
- minio_network
app:
image: decidim-app:latest
environment:
Expand All @@ -58,6 +86,7 @@ services:
- MEMCACHE_SERVERS=memcached:11211
- RAILS_SERVE_STATIC_FILES=true
- RAILS_LOG_TO_STDOUT=true
- RAILS_LOG_LEVEL=debug
- ASSET_HOST=localhost:3000
- FORCE_SSL=1
- ENABLE_LETTER_OPENER=1
Expand All @@ -73,6 +102,10 @@ services:
- GEOCODER_LOOKUP_API_KEY=${GEOCODER_LOOKUP_API_KEY}
- DEFAULT_LOCALE=${DEFAULT_LOCALE}
- AVAILABLE_LOCALES=${AVAILABLE_LOCALES}
- OBJECTSTORE_S3_HOST=minio:9000
- SCALEWAY_BUCKET_NAME=localhost
- SCALEWAY_ID=minioadmin
- SCALEWAY_TOKEN=minioadmin
volumes:
- shared-volume:/app
ports:
Expand All @@ -81,8 +114,16 @@ services:
- database
- redis
- memcached
networks:
- minio_network

networks:
minio_network:
driver: bridge

volumes:
shared-volume: { }
pg-data: { }
redis-data: { }
redis-data: { }
minio:
driver: local
28 changes: 28 additions & 0 deletions lib/tasks/active_storage.rake
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# frozen_string_literal: true

namespace :active_storage do
namespace :purge do
desc "Purge orphan blobs in databa"
task blobs: :environment do
Rails.logger.info "Looking for blobs without attachments in database..."
blobs = ActiveStorage::Blob.where.not(id: ActiveStorage::Attachment.select(:blob_id))

if blobs.count.zero?
Rails.logger.info "Database is clean !"
Rails.logger.info "Terminating task..."
else
Rails.logger.info "Found #{blobs.count} orphan blobs !"

ActiveStorage::Blob.where.not(id: ActiveStorage::Attachment.select(:blob_id)).find_each(&:purge)
Quentinchampenois marked this conversation as resolved.
Show resolved Hide resolved

Rails.logger.info "Task terminated !"
end
end

desc "Purge orphan blobs in S3"
task s3: :environment do
limit = ENV.fetch("S3_LIMIT", "10000").to_i
ActiveStorageClearOrphansJob.perform_later(limit: limit)
end
end
end
Loading