搭建 GitLab Geo 后,在同步状态页中可以查看到大量的 Uploads 文件同步失败,查看日志,报错类似于 Error during verification: undefined method `underscore' for NilClass:Class
或 The model which owns this Upload is missing.
是因为原实例中存在大量的孤儿上传文件,孤儿文件的意思就是其引用或所属的资源已经被删除,但文件本身未被删除。
官方解决方案
官方文档中提供了一个用于清理的脚本,如下:
def delete_orphaned_uploads(dry_run: true)
if dry_run
p "This is a dry run. Upload rows will only be printed."
else
p "This is NOT A DRY RUN! Upload rows will be deleted from the DB!"
end
subquery = Geo::UploadState.where("(verification_failure LIKE 'Error during verification: The model which owns this Upload is missing.%' OR verification_failure = 'Error during verification: undefined method `underscore'' for NilClass:Class') AND verification_checksum IS NULL")
uploads = Upload.where(upload_state: subquery)
p "Found #{uploads.count} uploads with a model that does not exist"
uploads_deleted = 0
begin
uploads.each do |upload|
if dry_run
p upload
else
uploads_deleted=uploads_deleted + 1
p upload.destroy!
end
rescue => e
puts "checking upload #{upload.id} failed with #{e.message}"
end
end
p "#{uploads_deleted} remote objects were destroyed." unless dry_run
end
但实际执行后发现并未清理任何文件。参考其 changelog ,发现其脚本中存在错误的语法,使用下方的正确脚本可以进行清理。
清理方案
原脚本中的 SQL 语句拼接的有问题,无法正确筛选以 Error during verification: undefined method `underscore''
开头的项导致无法清理。
def delete_orphaned_uploads(dry_run: true)
if dry_run
p "This is a dry run. Upload rows will only be printed."
else
p "This is NOT A DRY RUN! Upload rows will be deleted from the DB!"
end
subquery = Geo::UploadState.where("(verification_failure LIKE 'Error during verification: The model which owns this Upload is missing.%' OR verification_failure LIKE 'Error during verification: undefined method `underscore'' for NilClass:Class%') AND verification_checksum IS NULL")
uploads = Upload.where(upload_state: subquery)
p "Found #{uploads.count} uploads with a model that does not exist"
uploads_deleted = 0
begin
uploads.each do |upload|
if dry_run
p upload
else
uploads_deleted=uploads_deleted + 1
p upload.destroy!
end
rescue => e
puts "checking upload #{upload.id} failed with #{e.message}"
end
end
p "#{uploads_deleted} remote objects were destroyed." unless dry_run
end
粘贴进 Rails 里执行,然后执行模拟运行:
delete_orphaned_uploads(dry_run: true)
然后实际执行清理:
delete_orphaned_uploads(dry_run: false)
附录
参考链接
- Geo: Investigate problems with upload records for designs - GitLab
- Geo: Fix typo in script to handle orphaned uploads - GitLab
本文由 柒 创作,采用 知识共享署名4.0
国际许可协议进行许可。
转载本站文章前请注明出处,文章作者保留所有权限。
最后编辑时间: 2025-04-14 17:27 PM