기존 주제에 새 게시글을 생성하도록 API를 호출할 때 500 오류가 발생합니다. 로그에서는 다음과 같은 내용이 표시됩니다:
ActiveRecord::StatementInvalid (PG::InvalidTextRepresentation: ERROR: invalid input syntax for type inet: ""
LINE 1: ..._addresses".* FROM "screened_ip_addresses" WHERE ('' <<= ip_...
^
)
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rack-mini-profiler-2.0.1/lib/patches/db/pg.rb:69:in `exec_params'
Failed to handle exception in exception app middleware : PG::InvalidTextRepresentation: ERROR: invalid input syntax for type inet: ""
LINE 1: ..._addresses".* FROM "screened_ip_addresses" WHERE ('' <<= ip_...
^
제 차단된 IP 목록은 다음과 같습니다. 아래 스크린샷 외에도 API를 호출하는 머신의 IP를 화이트리스트에 추가했습니다. (시스템 수준의 API 키를 사용하여 기존 포럼 소프트웨어의 오래된 주제/메시지를 대량으로 가져오는 작업을 수행하고 있습니다.)
Hey @blake, 답변해 주셔서 감사합니다. 제 코드에 문제가 없는지 확실히 확인하기 위해 Insomnia (Postman과 비슷하지만 개인적으로 더 단순하고 사용하기 쉽다고 생각합니다)에 기본적인 API 호출을 구성해 보았습니다. 불행히도 결과는 동일했지만, 적어도 이제 상황이 매우 명확해졌습니다:
새로운 게시글을 생성하기 위해 준비한 호출입니다 (이미 “게시글 최소 단어 수” 설정을 1로 낮춰 두었습니다):
음, 여기 분명 뭔가 이상한 일이 일어나고 있는 것 같아요. 스크립트를 다시 실행해 보니, 대량으로 토픽을 생성하고 메시지를 게시하는 중이네요… 그리고 또 다시, 이번에는 다른 사용자로 테스트했는데 500 에러가 발생했어요.
그 사용자명을 Insomnia로 가져와서 API를 테스트해 보니, 역시 500 에러가 뜨네요. 'system’으로 바꾸니 정상적으로 통과하더니… 원래 사용자명으로 다시 돌아가니 또 500 에러가 나요!
500 에러를 일으키는 사용자(그리고 'system’을 제외한 모든 내 사용자)는 TL1이고, TL1이 게시물을 올릴 수 있도록 제한을 변경했는데도 문제가 지속되고 있어요.
이건 분명某种 방식으로 레이트 리미팅(rate limiting)과 관련이 있는 것 같은 느낌이 드네요. nginx나 다른 업스트림 구성 요소가 500 에러의 원인일 수도 있겠다고 의심했지만, nginx에서 모든 레이트 리미팅을 제거했는데도 에러 로그에 표시되는 500 에러는 여전히 그 SQL 버그와 동일하게 나타나고 있어요.
SQL 에러가 IP 주소를 참조하는 컬럼 주변에서 발생하고 있는 것 같다는 걸 알아차렸어요. 레이트 리미팅 작동 방식에 뭔가 이상한 점이 있어서 이 문제를 일으킬 수 있을까요? IP를 변경하기 위해 VPN으로 로그인해 보았지만 여전히 500 에러가 나요.
그동안, 문제가 rack-mini-profiler에 있는 것 같다는 걸 알게 되었어요. 이건 필수적인 것이 아니니 꺼보려고 해요. 이게 문제를 해결해 줄지 볼게요… 아니요. 이제 관리자 계정에서 미니 프로파일러는 더 이상 보이지 않지만, 에러 로그에 동일한 에러와 함께 동일한 HTTP 500 에러가 계속 나고 있어요
업데이트: 사용자를 TL3으로 변경하면 문제가 사라지는 것 같아요. 다시 TL1로 전환하면 문제가 다시 발생해요. 이 가설을 테스트해 보고 있어요… 아니요. 때로는 효과가 있지만, 다른 경우에는 사용자가 수동으로 TL을 편집해도 사용자의 상태가 "고정(stuck)"된 것처럼 보이기도 해요.
@blake 또는 @staff 중 다른 누군가… 도와주세요! 이제 뭘 더 시도해 볼 수 있을까요? (에러를 일으키는 코드와 관련된) 완전히 초기화하고 공장 출하 상태로 리셋할 수 있는 것이 있을까요?
그러나 흥미로운 점은, 500 에러를 발생시키는 해당 SQL 요청을 수행하기 전에 이 코드가 ip_address의 존재 여부를 확인하고 있다는 것입니다.
Discourse 인스턴스가 어떻게 설정되어 있는지 설명해 주시겠습니까? 가져오기(import)를 통해 설치한 것인가요? 최신 버전을 사용 중인가요? RAM 용량은 얼마나 되나요? 이 가이드를 따르셨나요?
이 사이트 설정을 확인해 보실 수 있을까요: max new accounts per registration ip? 이 경우 중요한지 확실하지 않지만, 문제가 원인이 될 수도 있습니다.
벌크 스크립트에서 요청 사이에 1초의 대기 시간을 두고 속도를 늦춰 보시면 차이가 나는지 확인해 볼 수 있을까요?
이 API 호출의 목적은 무엇인가요? 사용자와 게시물을 가져오기 위해 한 번만 실행하는 스크립트라면, API 호출을 하지 않고 실제 서버에서 실행되는 가져오기 스크립트를 사용하는 것이 더 나을 수 있습니다.
많은 질문을 드려 죄송합니다. 이전에 이 문제를 겪어 본 적이 없고 screened_ip_addresses 주변의 코드는 오랫동안 업데이트되지 않았기 때문입니다. 코드베이스 어딘가에 버그가 없다고 말하는 것은 아니지만, 간단히 살펴본 결과 현재까지는 눈에 띄는 부분이 없습니다.
물론이죠. Digital Ocean에서 완전히 Docker로 구동되고 있습니다. 그 훌륭한 가이드를 그대로 따랐습니다.
확인했습니다. 해당 설정을 기본값인 3에서 99999로 변경해 봤습니다. 달라진 점은 없고, 여전히 500 에러가 발생합니다.
그렇게 해봤지만 달라진 점이 없습니다. Insomnia를 통해 ‘문제 있는’ 계정 하나만 사용해도 500 에러가 발생한다는 점을 참고해 주세요. 즉, 지금은 그 하나의 계정이 '독성’을 띠고 있는 것처럼 보입니다. 그 계정으로 ‘create message’ API 호출을 하나만 수행해도(그 전이나 후의 호출이 없어도) 여전히 500 에러가 발생합니다. 하지만 네, 제 임포트 스크립트도 500 에러를 받고 있긴 합니다
네, 저는 숙련된 개발자이지만 RoR/Ruby는 전혀 모르기 때문에 여러분이 제공하는 표준 옵션을 실제로 사용할 수 없습니다. 물론 기존 포럼을 수동으로 돌아다니며 API를 통해 사용자를 생성하는 것보다 훨씬 우수할 것이라는 점은 인정합니다. 그래서 마켓플레이스 게시글을 올린 것입니다… 제 손으로 이 모든 것을 작동시키는 것을 원하지만, 엄격한 마감 기한도 있습니다
전혀 이해합니다. 그리고 이 문제에 관심을 가져주셔서 감사합니다.
그럼 도움이 될 수 있는 것을 하나 제안하겠습니다. 표준 설치 환경이고 커스터마이징을 거의 하지 않았으며, 그리고 제 코드 없이도 버그를 쉽게 재현할 수 있고(Insomnia만 사용하면 됩니다) 또한 포럼을 정식 오픈하지 않았기 때문에, Digital Ocean 인스턴스의 루트 로그인 정보, API 키 등을 전달해 드릴 수 있습니다. 그리고 거기에 자유롭게 들어가서 이것저것 만져보셔도 괜찮습니다. 제 Discourse 포럼은 현재 비어 있는 카테고리들과 우리가 설정해 둔 몇 개의 특별 소개 메시기가 있을 뿐, 기본적으로 비어 있고 실제 사용자가 아직 없습니다(관리자만 있음). 따라서 테스트를 원하시면 주제와 메시지를 생성하거나 삭제하는 등 자유롭게 사용하셔도 됩니다.
이것이 버그를 직접 눈으로 확인하는 가장 빠른 방법일 것입니다. 그리고 루트 권한으로 들어가게 되면, 이것이 왜 발생하는지 알아내기 위해 원하시는 저수준의 Discourse 설정들을 자유롭게 조정할 수도 있습니다.
음, 거기에 뭔가 있는 것 같았어요… 제 테스트용 ‘독이 든’ 문제 사용자 george21은 TL0 상태였습니다. 그래서 TL1로 변경했는데 그제서야 작동했어요. 좋아요! 아마 그게 원인인 것 같습니다! 그래서 george21을 다시 TL0로 되돌렸더니… 이제 더 이상 ‘독이 든’ 상태가 아니에요. TL0 상태에서도 API 호출을 할 수 있습니다.
이제 다시 가져오기(import) 스크립트를 실행해 보겠습니다. 아하. 이제 george21이 가져오기 스크립트에서 500 오류를 던지고 있습니다. Insomnia에서 시도해 보았는데 실패합니다. 그래서 이제 george21을 다시 TL1로 변경해 보면… 네, HTTP 호출을 실행할 수 있습니다.
즉, 제가 재현할 수 있는 현상은 다음과 같습니다:
일련의 API 호출이 이루어지면(?) 어떤 식으로든 TL0 사용자의 후속 API 호출이 실패하게 됩니다.
TL0 사용자를 TL1로 변경하면 API 호출이 통과합니다.
그리고 기이하게도, 그 같은 사용자를 다시 TL0로 변경해도 여전히 API 호출이 통과합니다.
스크립트를 다시 실행하면 또 다른 TL0 사용자에 대해 실패할 때까지 정상적으로 작동합니다.
참고로:
제 지식 범위 내에서 TL0에 대한 모든 최소 요건 등이 상향 조정되었습니다(즉, TL0 사용자가 게시물을 올리는 것을 막을 수 있는 모든 블로킹 요소를 제거하려고 시도했습니다) 그리고,
이것이 TL0 사용자를 위한某种 내부 속도 제한 문제일지라도, API가 500 오류를 던지고 오류 로그에 SQL 오류를 기록하는 것은 아닙니다. 따라서 이 시점에서 어딘가에 분명히 버그가 있다고 말할 수 있습니다.
네, 음, 알고 있습니다. 그리고 (제시된 예시들을 바탕으로) 왜 제 가져오기 스크립트를 직접 작성하지 않는지에 대한 이유를 이미 네 번쯤 설명드렸죠. 그래서 제 접근 방식 변경.
그리고 그 사이, 저는 이 버그를 찾아 수정하는 데 도움을 주기 위해 여기에서 계속 기여하고 있습니다. 오늘은 제 가져오기 스크립트에 영향을 미치고 있습니다. 내일은 여러분 사이트에서 API가 필요한 중요한 스크립트에 영향을 미칠 수도 있습니다…