2.5.0에서 주제의 손상된 업로드 링크가 500 오류를 일으킴

저는 Discourse 사이트를 운영하고 있으며, 이 소프트웨어를 얼마나 좋아하는지 말씀드리고 싶습니다. 훌륭한 작업을 해 주신 팀 전체에 감사드립니다. 정말 멋진 도구입니다.

2.5.0 버전으로 업그레이드한 후 큰 문제에 직면했습니다. 문제의 요약과 제가 적용한 임시 해결책은 다음과 같습니다. 이 정보가 향후 버전에서 더 나은 수정으로 이어지기를 바랍니다.

데이터베이스에 있는 일부 주제에 깨진 업로드 파일이 포함되어 있습니다. “S3 업로드” 기능을 사용하다가 실수로 버킷을 삭제해 버렸습니다. 네, 정말 멍청한 실수였지만, 실제로 그렇게 되었습니다. 그 결과 모든 주제 이미지가 사라졌습니다.

많은 이미지를 잃어버린 사실은 차치하더라도, 그 외에는 모든 것이 정상이었으며, Discourse는 존재하지 않는 이미지에 대한 깨진 링크를 표시했지만 시스템 자체는 잘 작동하고 있었습니다.

하지만 2.5.0 버전으로 업그레이드하려 했을 때 문제가 발생했습니다. 로그인한 사용자들은 모두 500 에러를 받았고, 익명 방문자만 웹사이트를 볼 수 있었습니다.

조사해 본 결과, Discourse가 “No such file”(파일을 찾을 수 없음) 에러로 인해 멈추고 있음을 알게 되었습니다. 파일 다운로드를 시도하고 있었던 것 같습니다. /var/www/discourse/app/models/upload.rb 파일에서 local? 메서드를 강제로 true로 설정해야 했고, 그렇게 하니 문제가 해결되었습니다. 하지만 다음 업그레이드를 앞두고 조금 걱정됩니다…

이것은 분명히 새로운 문제입니다. 이전 업그레이드에서는 이러한 문제가 발생하지 않았거든요.

참고로, 주제 내에 있는 모든 죽은 이미지 링크를 제거할 수 있는 방법이 있을까요?

감사합니다.

정반대의 동작이 발생했습니다: 로그인한 사용자는 정상적으로 작동하지만, 로그인하지 않은 사용자는 연결할 수 없고 500 오류가 발생합니다.

해당 오류의 전체 백트레이스를 공유해 주시겠습니까?
/logs 페이지를 확인해 보세요.

저한테는 호환되지 않는 플러그인처럼 들리는데, 어떤 비공식 플러그인을 사용 중이신가요? 그 플러그인들을 제외하고 다시 빌드해 보셨나요?

네, 제 log/production.log 파일에는 다음 예외가 기록되어 있었습니다 (Discourse가 비어 있는 S3 버킷에 접근할 때 발생했습니다. 버킷을 다시 생성해 문제를 해결할 수 있기를 바랐습니다).

Started GET “/” for 86.246.127.170 at 2020-05-16 14:29:06 +0000
Processing by ListController#latest as HTML
Creating scope :open. Overwriting existing method Poll.open.
Completed 500 Internal Server Error in 3638ms (ActiveRecord: 0.0ms | Allocations: 135090)
NoMethodError (undefined method path' for nil:NilClass) /var/www/discourse/lib/file_store/base_store.rb:150:in cache_file’

도움이 되길 바랍니다.

감사합니다. 그게 원인일 수도 있겠네요. 실제로 Discourse Adsense와 discourse-chat-integration 두 개의 플러그인이 설치되어 있습니다. 이 둘을 제외하고 재빌드를 시도해 보겠습니다.

이 문제가 플러그인으로 인한 것이 아님을 확인했습니다: 플러그인을 설치하지 않은 상태에서(다만 docker_manager만 설치) 새 설치 + 마지막 백업 복원을 통해 동일한 버그를 재현했습니다.

가장 먼저 받는 스택 트레이스는 다음과 같습니다:

Completed 500 Internal Server Error in 4169ms (ActiveRecord: 0.0ms | Allocations: 72058)
NoMethodError (undefined method path' for nil:NilClass) /var/www/discourse/lib/file_store/base_store.rb:150:in cache_file’

다음과 같이 패치했습니다:

def cache_file(file, filename)
path = get_cache_path_for(filename)
dir = File.dirname(path)
FileUtils.mkdir_p(dir) unless Dir.exist?(dir)

  if file.nil?
    return
  end

  FileUtils.cp(file.path, path)

이로 인해 두 번째 오류(최초 게시물에서 언급한 오류)가 발생했습니다:

Started GET “/” for 86.246.127.170 at 2020-05-18 07:37:40 +0000
Processing by CategoriesController#index as HTML
Completed 500 Internal Server Error in 4342ms (ActiveRecord: 0.0ms | Allocations: 60478)
NoMethodError (undefined method path' for nil:NilClass) /var/www/discourse/app/models/upload.rb:193:in fix_dimensions!’

local? 메서드가 true를 반환하도록 강제하여 수정했습니다:

def local?
return true
!(url =~ /^(https?:)?///)
end

한때 파일을 S3로 이동하거나 S3에서 가져온 적이 있나요?

네, 그렇게 했습니다. 하지만 그 후 버킷이 삭제되었어요. 그래서 로컬 저장소로 다시 전환했는데, 당연히 이전 주제들에서 이미지가 깨진 링크가 남았습니다.

여기서 가장 좋은 방법은 데이터베이스에서 잘못된 Upload 행들을 전부 삭제하는 것입니다.

업로드가 없다면 해당 데이터를 유지하지 마세요.

네, 동의합니다. 하지만 DB에서 이렇게 위험한 작업을 수동으로 실행하는 것이 걱정됩니다. 더 ‘제대로’ 수행할 수 있는 방법에 대한 제안이 있을까요? 아니면 정말로 ‘수동으로’ 해야 하나요?

또한, Discourse의 이러한 동작 변경이 다소 우려스럽습니다. 제 판단으로는, 어딘가에 깨진 이미지 링크가 존재할 경우 앱이 충돌할 수 있다는 뜻입니다.

이전에는 그런 일이 없었습니다. 이러한 상황에서 더 견고하게 처리하도록 개선하는 것을 제안합니다.

우리가 가진 것과 매우 유사합니다:

마법사 설정을 다시 실행하여 "수정"되었습니다!

네, 동일한 문제인 것 같습니다. @sukria 최신 tests-passed 버전으로 업데이트하면 깨진 업로드에 대해 더 견고하게 동작하도록 수정을 추가했습니다(다만, 깨진 업로드 참조를 정리하는 것이 여전히 좋습니다).

나도 그런 깨진 링크를 쉽게 정리하는 방법에 관심이 있어요 :wink:

david님, 감사합니다. tests-passed 기준으로 새로 빌드해 보니 바로 정상 작동했습니다. 감사합니다!
토픽 안의 그 죽은 링크들을 제거하는 깔끔하고 쉬운 방법이 있을까요?