수년간 S3 마이그레이션과 관련된 수많은 문제를 목격해 왔으며, 백업 복원 시 발생하는 암시적 마이그레이션도 포함됩니다.
EXCEPTION: 8 posts are not remapped to new S3 upload URL. S3 migration failed for db 'default'.
수많은 예시 중 일부는 다음과 같습니다:
- False positives on "posts are not remapped to new S3 upload URL"
- Restore process cancelled at migrating uploads to S3 step
- Restore to New Host
오늘도 이러한 문제 중 하나가 발생했고, 금요일이었기 때문에 단순히 체크를 주석 처리하는 대신 문제를 파헤치기로 결정했습니다.
상황은 다음과 같습니다:
- 멀티사이트(multisite)를 사용하고 있습니다.
- 이 예시에서는 데이터베이스 이름을
dbname이라고 가정합니다. S3_CDN_URL이 설정되어 있습니다.CDN_URL은 설정되어 있지 않습니다.
이 경우 /lib/file_store/to_s3_migration.rb 파일에서 다음 일이 일어납니다.
먼저 접두사(prefix)가 결정됩니다.
prefix = @migrate_to_multisite ? "uploads/#{@current_db}/original/" : "original/"
그 다음 파일이 S3로 업로드되고, 그 후 리맵(remap)이 수행됩니다. 이는 기본적으로 다음과 같으며 몇 가지 변형이 있습니다.
from = "/uploads/#{@current_db}/original/"
to = "#{SiteSetting.Upload.s3_base_url}/#{prefix}"
따라서 멀티사이트 환경에서는 다음과 같이 리맵됩니다.
/uploads/dbname/original/에서https://bucket-location-url.com/uploads/dbname/original/로
그리고 마지막으로 체크가 수행됩니다.
cdn_path = SiteSetting.cdn_path("/uploads/#{@current_db}/original").sub(/https?:/, "")
count = Post.where("cooked LIKE '%#{cdn_path}%'").count
if count > 0
error_message = "#{count} posts are not remapped to new S3 upload URL. #{failure_message}"
raise_or_log(error_message, should_raise)
success = false
end
이때 SiteSetting.cdn_path는 lib/global_path.rb에서 가져오며, 다음과 같은 형태입니다.
def cdn_path(p)
GlobalSetting.cdn_url.blank? ? p : "#{GlobalSetting.cdn_url}#{path(p)}"
end
즉, S3 CDN은 있지만 일반 CDN이 없는 경우 SiteSetting.cdn_path("/uploads/#{@current_db}/original")는 단순히 /uploads/dbname/original가 됩니다.
그리고 우리의 리맵에 따르면 새로운 경로는 https://bucket-location-url.com/uploads/dbname/original/입니다.
그것을 의미합니다.
cdn_path는 새로운 대상 경로의 부분 문자열(substring)입니다.- 따라서
Post.where("cooked LIKE '%#{cdn_path}%'").count는 항상 게시물을 찾게 됩니다. - 이는 허위 경보(cry wolf)를 울리고 실패로 종료됩니다.
