El directorio de Tombstone no se limpia para las imágenes

No estoy seguro de haber entendido correctamente cómo funciona el proceso de limpieza de marcadores de eliminación. Es algo urgente, ya que mi disco se está llenando rápidamente mientras volvemos a procesar todas nuestras imágenes. Tenemos muchas, por lo que esto genera muchos archivos de marcadores de eliminación.

Aquí está mi configuración:

  • limpiar subidas está habilitado
  • período de gracia en horas para limpiar subidas huérfanas está configurado en 48 horas
  • período de gracia en días para eliminar subidas eliminadas está temporalmente configurado en 2 días (comencé el reprocesamiento hace 4 días)

Ejecuté el trabajo Jobs::CleanUpUploads en el programador de Sidekiq, pero no sucede nada. ¿Qué estoy pasando por alto?

I think that you could just rm -r tombstone and the directories will get created as needed when more tombstoned files get moved over. A slightly more paranoid solution would be something like

find tombstone -type f -exec rm \{\} \;

Still more paranoid would be to first rsync the tombstone stuff elsewhere for a while (just in case something got tomestoned by mistake).

The most robust (but scary nonetheless) solution would be to move images to S3 (AWS, or Digital Ocean). It looks like it’d be $5/month for 250GB on Digital Ocean. It’s probably a good long term solution and will reduce load on your server.

Thanks Jay! Interesting, I always believed the tombstone would be cleaned up automatically.

And yep, I’m one of the paranoid types and have everything, included my tombstone backed up - twice :slight_smile:

I have considered S3 or DO storage (S3 is quite expensive by the way because they charge for traffic - a terabyte of traffic/month adds up), but as you say, I’ve always beens scared of that route. I don’t fully understand those platforms and the migration would probably keep me awake at night…

I’m hosting at Hetzner and they just plugged in an additional SSD drive for me this morning, so I have plenty of space again (kudos for the Hetzner team by the way - everything went very smoothly).

The tombstone files are cleaned up automatically, but your queue is full of the rebake processes, so it’s not getting to the cleanup tasks. (I’m not sure, but the cleanup tasks may be in the low priority queue, so they may never get called until all of the rebaked are finished.)

Getting more disk is the easier solution!

Oh? My queue is pretty empty, so I don’t think that’s it.

N. B. I have no idea.

Do you see the cleanup task in the queue?

I think I looked for a cleanup rake task and didn’t see one.

@vinothkannans I am somewhat concerned here, can you spot check that tombstone is working … as designed in our non S3 setups?

This is working fine on my local dev environment.

I think you forgot to trigger the Jobs::PurgeDeletedUploads job. CleanUpUploads job will move the unwanted uploads to tombstone directory. After the grace period PurgeDeletedUploads job will delete the tombstone files.

Brilliant, thanks Vinoth!

Just need to add that you aren’t supposed to serve anything from S3 directly. You need to put a CDN front of the files there. On Digital Ocean you get a CDN for spaces included too.

Ah! Thanks for that. (and so obvious now that I hear it!) Keycdn is pretty affordable.

You can even use Cloudflare, since it’s a different domain only for uploads you will not find the javascript problems, and get a good CDN for free.

En /logs tengo el siguiente error por el cual Jobs::CleanUpUploads falla.

Excepción del trabajo: PG::ForeignKeyViolation: ERROR:  la actualización o eliminación en la tabla "uploads" viola la restricción de clave externa "fk_rails_1d362f2e97" en la tabla "user_profiles"
DETALLE:  La clave (id)=(169100) todavía está referenciada desde la tabla "user_profiles".

Parece que probablemente hay alguna carga que fue eliminada del disco pero que aún existe en la base de datos. Estoy 100% seguro de que no he realizado cambios manuales en la base de datos, por lo que debe ser algún subproducto de las migraciones de versiones.

¿Podría preguntarle si debo solucionarlo manualmente desde la consola o si puede recomendarme algún script incluido en el paquete?

Rastreo
rack-mini-profiler-1.1.6/lib/patches/db/pg.rb:69:in `exec_params'
rack-mini-profiler-1.1.6/lib/patches/db/pg.rb:69:in `exec_params'
activerecord-6.0.1/lib/active_record/connection_adapters/postgresql_adapter.rb:672:in `block (2 levels) in exec_no_cache'
activesupport-6.0.1/lib/active_support/dependencies/interlock.rb:48:in `block in permit_concurrent_loads'
activesupport-6.0.1/lib/active_support/concurrency/share_lock.rb:187:in `yield_shares'
activesupport-6.0.1/lib/active_support/dependencies/interlock.rb:47:in `permit_concurrent_loads'
activerecord-6.0.1/lib/active_record/connection_adapters/postgresql_adapter.rb:671:in `block in exec_no_cache'
activerecord-6.0.1/lib/active_record/connection_adapters/abstract_adapter.rb:718:in `block (2 levels) in log'
/usr/local/lib/ruby/2.6.0/monitor.rb:235:in `mon_synchronize'
activerecord-6.0.1/lib/active_record/connection_adapters/abstract_adapter.rb:717:in `block in log'
activesupport-6.0.1/lib/active_support/notifications/instrumenter.rb:24:in `instrument'
activerecord-6.0.1/lib/active_record/connection_adapters/abstract_adapter.rb:708:in `log'
activerecord-6.0.1/lib/active_record/connection_adapters/postgresql_adapter.rb:670:in `exec_no_cache'
activerecord-6.0.1/lib/active_record/connection_adapters/postgresql_adapter.rb:651:in `execute_and_clear'
activerecord-6.0.1/lib/active_record/connection_adapters/postgresql/database_statements.rb:111:in `exec_delete'
activerecord-6.0.1/lib/active_record/connection_adapters/abstract/database_statements.rb:180:in `delete'
activerecord-6.0.1/lib/active_record/connection_adapters/abstract/query_cache.rb:22:in `delete'
activerecord-6.0.1/lib/active_record/persistence.rb:395:in `_delete_record'
activerecord-6.0.1/lib/active_record/persistence.rb:883:in `_delete_row'
activerecord-6.0.1/lib/active_record/persistence.rb:879:in `destroy_row'
activerecord-6.0.1/lib/active_record/counter_cache.rb:173:in `destroy_row'
activerecord-6.0.1/lib/active_record/locking/optimistic.rb:108:in `destroy_row'
activerecord-6.0.1/lib/active_record/persistence.rb:535:in `destroy'
activerecord-6.0.1/lib/active_record/callbacks.rb:309:in `block in destroy'
activesupport-6.0.1/lib/active_support/callbacks.rb:135:in `run_callbacks'
activesupport-6.0.1/lib/active_support/callbacks.rb:827:in `_run_destroy_callbacks'
activerecord-6.0.1/lib/active_record/callbacks.rb:309:in `destroy'
activerecord-6.0.1/lib/active_record/transactions.rb:311:in `block in destroy'
activerecord-6.0.1/lib/active_record/transactions.rb:375:in `block in with_transaction_returning_status'
activerecord-6.0.1/lib/active_record/connection_adapters/abstract/database_statements.rb:279:in `transaction'
activerecord-6.0.1/lib/active_record/transactions.rb:212:in `transaction'
activerecord-6.0.1/lib/active_record/transactions.rb:366:in `with_transaction_returning_status'
activerecord-6.0.1/lib/active_record/transactions.rb:311:in `destroy'
/var/www/discourse/app/models/upload.rb:112:in `block in destroy'
activerecord-6.0.1/lib/active_record/connection_adapters/abstract/database_statements.rb:281:in `block in transaction'
activerecord-6.0.1/lib/active_record/connection_adapters/abstract/transaction.rb:280:in `block in within_new_transaction'
/usr/local/lib/ruby/2.6.0/monitor.rb:235:in `mon_synchronize'
activerecord-6.0.1/lib/active_record/connection_adapters/abstract/transaction.rb:278:in `within_new_transaction'
activerecord-6.0.1/lib/active_record/connection_adapters/abstract/database_statements.rb:281:in `transaction'
activerecord-6.0.1/lib/active_record/transactions.rb:212:in `transaction'
/var/www/discourse/app/models/upload.rb:110:in `destroy'
activerecord-6.0.1/lib/active_record/persistence.rb:551:in `destroy!'
activerecord-6.0.1/lib/active_record/relation/batches.rb:70:in `block (2 levels) in find_each'
activerecord-6.0.1/lib/active_record/relation/batches.rb:70:in `each'
activerecord-6.0.1/lib/active_record/relation/batches.rb:70:in `block in find_each'
activerecord-6.0.1/lib/active_record/relation/batches.rb:136:in `block in find_in_batches'
activerecord-6.0.1/lib/active_record/relation/batches.rb:238:in `block in in_batches'
activerecord-6.0.1/lib/active_record/relation/batches.rb:222:in `loop'
activerecord-6.0.1/lib/active_record/relation/batches.rb:222:in `in_batches'
activerecord-6.0.1/lib/active_record/relation/batches.rb:135:in `find_in_batches'
activerecord-6.0.1/lib/active_record/relation/batches.rb:69:in `find_each'
/var/www/discourse/app/jobs/scheduled/clean_up_uploads.rb:16:in `execute'
/var/www/discourse/app/jobs/base.rb:232:in `block (2 levels) in perform'
rails_multisite-2.0.7/lib/rails_multisite/connection_management.rb:63:in `with_connection'
/var/www/discourse/app/jobs/base.rb:221:in `block in perform'
/var/www/discourse/app/jobs/base.rb:217:in `each'
/var/www/discourse/app/jobs/base.rb:217:in `perform'
/var/www/discourse/app/jobs/base.rb:279:in `perform'
mini_scheduler-0.12.2/lib/mini_scheduler/manager.rb:86:in `process_queue'
mini_scheduler-0.12.2/lib/mini_scheduler/manager.rb:36:in `block (2 levels) in initialize'

¡Muchas gracias por el consejo!

Puedo confirmar que Tombstone tampoco se está eliminando por PurgeDeletedUploads en nuestro S3.

https://meta.discourse.org/t/how-to-reverse-engineer-the-discourse-api/20576/24?u=terrapop

Parece que esto solo limpia lo local; no puedo encontrar ninguna referencia a S3:

def purge_tombstone(grace_period)
  if Dir.exists?(Discourse.store.tombstone_dir)
    Discourse::Utils.execute_command(
      'find', tombstone_dir, '-mtime', "+#{grace_period}", '-type', 'f', '-delete'
    )
  end
end

¿Significa esto que Tombstone crecerá en S3 (o en cualquier otro directorio de carga externo) hasta el infinito?

No, revisé S3 recientemente y los respaldos esperados estaban ahí (5).

No estoy hablando de copias de seguridad; esto se refiere a imágenes que definitivamente NO se eliminarán de Tombstone en S3. Además, todo este tema trata sobre imágenes, no sobre copias de seguridad.

Sería bueno que alguien de @team confirmara que las imágenes en Tombstone no se eliminan como deberían, para que así pudiéramos encontrar una solución y eliminarlas nosotros mismos periódicamente, si ese es realmente el caso.