저는 몇 년째 비교적 작은 규모의 Discourse 인스턴스를 운영 중입니다. 트래픽이 꽤 낮은 편이라, 몇 달 전부터 이메일(알림, 다이제스트) 전송이 명백히 실패하기 시작했다는 사실을 알아차리는 데 시간이 걸렸습니다. 추적을 해본 결과, 2022-10-22경 2.8.0.beta7로 업그레이드한 시점으로 가리키며, 그 이전에는 2.8.0.beta4를 사용していました. 적어도 해당 인스턴스에서 게시글이나 메시지에 대한 이메일을 받은 적이 없습니다.
이메일들이 Sidekiq에 쌓여 있으며, 제가 관련 지을 수 없고 검색해도 딱 맞는 내용을 찾을 수 없는 메시지가 포함되어 있습니다. undefined method 메시지에 대한 보고가 있었지만, 제 상황과는 어떤 조건도 일치하지 않습니다. (TLS 문제가 아니며, 메일 서버 타임아웃도 아니고, 이벤트 플러그인 문제도 아니며, 보안 미디어 수정 사항은 이미 적용되어 있어야 합니다 — 게다가 정확한 에러 메시지도 달랐습니다.)
Sidekiq 에러:
Wrapped NoMethodError: undefined method `value' for #<Array:0x00007f7fd5277d68> Did you mean? values_at
#<Array: 이후 부분은 각 보류 중인 이메일마다 다릅니다. 지난밤에 새 VM으로 Discourse를 재설치하고 최신 백업에서 복원했지만, 이메일 문제는 데이터와 함께 복원된 것 같습니다
에러율이 10월 말부터 상승하기 시작했으므로, 이 문제가 2.8.0.beta7에서 도입된 것이라고 꽤 확신합니다:
## Plugins go here
## see https://meta.discourse.org/t/19157 for details
hooks:
after_code:
- exec:
cd: $home/plugins
cmd:
- git clone https://github.com/discourse/docker_manager.git
## Any custom commands to run after building
네, 표준 설치입니다. AFAICS(제가 보는 바로는) 현재 실행 중인 컨테이너는 하나뿐입니다. (새 VM을 생성하고, DNS를 재지정하고, apt update, apt dist-upgrade, 재부팅, git pull, ./discourse-setup, 웹 기반 설정, 백업 업로드, 백업 복원, 메일 재활성화, 그리고 다시 에러를 확인했습니다.) 참고로 기존 설치에서는 백업 링크를 메일로 전송할 수 있었고, 새 설치에서도 테스트 메일 전송은 여전히 정상 작동합니다 — 게시글 관련 메일만 실패하는 것으로 보입니다.
root@discourse:~# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ac408a70305d local_discourse/app "/sbin/boot" 12 hours ago Up 12 hours 0.0.0.0:80->80/tcp, :::80->80/tcp, 0.0.0.0:443->443/tcp, :::443->443/tcp app
수정:
root@discourse:~# apt update
Hit:1 https://download.docker.com/linux/debian buster InRelease
Hit:2 http://deb.debian.org/debian buster InRelease
Get:3 http://deb.debian.org/debian buster-updates InRelease [51,9 kB]
Get:4 http://security.debian.org/debian-security buster/updates InRelease [65,4 kB]
Fetched 117 kB in 2s (60,5 kB/s)
Reading package lists... Done
Building dependency tree
Reading state information... Done
All packages are up to date.
그러나 최초 복원 작업은 실제로 실패했습니다. database_restorer.rb가 restore_dump 단계에서 post_id 3841의 중복 링크로 인해 실패했습니다. 결국 2017년 게시글에 있는 해당 링크들을 이전 설치 환경에서 캡처한 스크린샷으로 대체하고 다시 백업을 수행한 후, 비로소 새 설치 환경에 백업을 복원할 수 있었습니다. Postgres에 대해 언급하셨듯이, 이 문제는 CREATE INDEX 실행 중 ERROR: could not create unique index "unique_post_links" 오류와 함께 발생했습니다. 추가 정보: EXCEPTION: psql failed: DETAIL: Key (topic_id, post_id, url)=(1300, 3841, [redacted]) is duplicated.
자, 아무도 쉽게 해결하는 방법을 모른다면, 이 문제를 제대로 디버깅해 보겠습니다. 하지만 저는 여러분의 도움이 필요합니다. Discourse는 제가 익숙하지 않은 여러 기술을 사용하는 상당히 복잡한 애플리케이션이니까요. 그래서: 메일은 어떻게 "Sidekiq로 전송"되는 건가요?
Discourse의 어떤 구성 요소가 Sidekiq에 “value” 메서드를 제공하고 있나요?
업그레이드 이후 이메일 알림이 작동하지 않게 되면서, Discourse는 안타깝게도 이제 거의 쓸모가 없습니다. 즉각적인 주의가 필요한 대신, 이제 주제에 대한 반응은 며칠씩 걸리거나, 아예 아무도 반응하지 않습니다. 2022년에 사람들이 능동적으로 사이트를 확인하기 때문이죠. 알림이 없으면 ⇒ 아무 일도 일어나지 않은 것 같으니 ⇒ 사이트를 확인할 필요도 없다
말씀드린 것처럼, 오래된 사이트는 여전히 실행 중이며, 백업을 받아 신선한 설치 환경에 적용했지만 복구가 실패했습니다. 복구까지 성공할 때까지 문제의 원인으로 지목된 포스트를 수정했습니다. 그런데 신선한 설치 환경에서도 Sidekiq 문제가 다시 발생하거나 여전히 지속되고 있습니다.
오래된 사이트도 Postgres 13을 실행 중입니다(하지만 수년 전으로 거슬러 올라가므로, 처음부터 이 버전으로 시작하지는 않았을 가능성이 큽니다 )
좋습니다. 인덱스가 복구되었다면, 이는 value 메서드가 있는 모델 대신 배열이 무엇인가에 전달되고 있음을 시사합니다. 문제는 본질적으로 Sidekiq에 있는 것이 아니라, Sidekiq가 호출하도록 하는 함수에 있습니다.
즉, 단일 항목이 아닌 배열을 반환하는 어떤 것이 호출되고 있는 것 같습니다. 다만 정확히 무엇인지는 추측할 수 없습니다. /var/discourse/shared/standalone/logs/rails/production.log (또는 제 기억이나 손가락이 틀렸다면 매우 유사한 경로)를 확인해 보셔야 할 것 같습니다. 그런 다음 해당 로그에서 그 오류를 찾아보거나(또는 오류가 다시 발생하도록 만들어 파일 끝에 위치하도록 하세요). 거기서 무엇이 실패하고 있는지에 대한 더 많은 정보를 얻을 수 있을 것입니다.
Started POST "/sidekiq/retries" for 185.39.142.187 at 2022-04-11 16:31:35 +0000
start
Started GET "/sidekiq/retries" for 185.39.142.187 at 2022-04-11 16:31:35 +0000
Rendered email/notification.html.erb (Duration: 42.8ms | Allocations: 4323)
Rendered layouts/email_template.html.erb (Duration: 0.3ms | Allocations: 29)
Job exception: undefined method `value' for #<Array:0x00007ff393af6c78>
Did you mean? values_at
fail
shared/standalone/log/rails/production_errors.log 파일은 비어 있습니다.
228 MessageBuilder.custom_headers(SiteSetting.email_custom_headers).each do |key, _|
*229 value = header_value(key)
230
231 # Remove Auto-Submitted header for group private message emails, it does
232 # not make sense there and may hurt deliverability.
그러면 사용자 정의 헤더일 수 있나요?
실제로 거기에 항목이 있습니다:
기본값으로 리셋했고 … 실제로 독자들의 확인을 통해 이메일 알림이 다시 전송되고 있는 것 같습니다.
감사합니다!
다만 한 가지 질문이 남아 있습니다: 왜 »Auto-Submitted: auto-generated|Precedence: bulk«가 이 실패를 일으키나요? 사용자 정의 헤더는 »|«로 구분되어야 한다고 되어 있습니다.
RFC에 따르면 많은 필드가 여러 번 나타날 수 있으며, 헤더가 하나만 있거나 일치하는 헤더가 여러 개인 경우, 헤더 상단에서 하단으로 순서대로 배열된 값의 배열을 반환합니다.
Discourse는 자동으로 Precedence 헤더를 설정하므로, email_custom_headers 설정을 통해 추가하는 헤더와 합쳐져 이제 두 개의Precedence 헤더가 있게 되며, @message.header["Precedence"]는 문자열 대신 배열을 반환합니다.
email_custom_headers에 메시지 객체에 이미 존재하는 헤더가 포함된 경우 이 버그가 발생한다고 생각합니다.