오류: 정수가 범위를 벗어났습니다

post_actions에는 이 방법으로 문제가 해결되었습니다. 조언해 주셔서 감사합니다!

현재는 여전히 두 가지 실패 사례가 관찰되고 있습니다:

  1. GET https://devforum.roblox.com/notifications가 bigint id를 가진 알림이 있는 사용자에게 404 오류를 반환하고 있습니다.

  2. Jobs::GrantAnniversaryBadges 예약 작업이 실패합니다

알림 모델/컨트롤러/서비스에서 notifications.id 필드를 정수(integer)로 정의하도록 하드코딩되어 있을 가능성이 있을까요?

그럴 가능성은 매우 낮습니다. 404 오류는 문제가 없어 보이는데, /logs에 문제를 설명하는 내용이 있나요?

불행히도 /logs 자체에서 특별히 유용한 정보를 찾지 못했지만, 로컬에서 이 문제를 재현해 보면 요청이 들어온 후 404가 발생하는 것을 확인할 수 있습니다. 단, 이는 최신 알림의 id를 bigint로 설정할 때만 발생하며(int32 범위 내에서는 정상 작동합니다).

여기저기 살펴보다 보니, http://localhost/notifications.json?limit=30을 호출하면 유효한 응답을 받는다는 것을 알게 되었습니다:

{
  "notifications": [
    {
      "id": 2148935910,
      "user_id": 2,
      "notification_type": 5,
      "read": true,
      "high_priority": false,
      "created_at": "2023-02-16T00:50:53.135Z",
      "post_number": 2,
      "topic_id": 8,
      "fancy_title": "Welcome to the Lounge",
      "slug": "welcome-to-the-lounge",
      "data": {
        "topic_title": "Welcome to the Lounge",
        "original_post_id": 13,
        "original_post_type": 1,
        "original_username": "blarouche",
        "revision_number": null,
        "display_username": "blarouche"
      }
    }
  ],
  "total_rows_notifications": 1,
  "seen_notification_id": 1001,
  "load_more_notifications": "/notifications?offset=60&username=bjlarouche"
}

하지만 recent 쿼리 파라미터를 전달하면, 예를 들어 http://localhost/notifications.json?recent=true&limit=30처럼 호출했을 때(알림 메뉴에서 호출되는 것이죠?) 다음과 같은 결과가 나옵니다:

{
  "errors": [
    "The requested URL or resource could not be found."
  ],
  "error_type": "not_found"
}

수정: current_user.seen_notification_id가 여전히 정수(integer)이기 때문이라고 생각하고 있습니다 :thinking:

드디어 해결되었습니다!

notifications.id 자체뿐만 아니라 notification_id를 참조하는 다른 테이블의 컬럼들도 마이그레이션해야 한다는 점을 인지했습니다. 그렇지 않으면 services/notifications.rb 또는 services/badge_granter.rb에서 오류가 발생했습니다.


향후 대용량(big) 포럼 환경에서 알림 관련 문제를 겪는 분들을 위해, 우리가 수행한 작업을 공유합니다.

총 4개 테이블의 4개 컬럼을 마이그레이션해야 했습니다:

  1. notifications.id
  2. user.seen_notification_id
  3. user_badges.notification_id
  4. shelved_notifications.notification_id

처음에는 #1에 대해 위에서 제안된 ALTER 명령을 사용하려 했지만, 언급했듯이 마이그레이션 파일이 스키마에 누적되도록 하기 위해 ActiveRecord 마이그레이션을 사용하는 것으로 결정했습니다.

20230215070319_change_notifications_id_to_bigint.rb
# frozen_string_literal: true

class ChangeNotificationsIdToBigint < ActiveRecord::Migration[6.1]
    def change
        change_column :notifications, :id, :bigint
    end
end
20230215070320_change_user_seen_notification_id_to_bigint.rb
# frozen_string_literal: true

class ChangeUserSeenNotificationIdToBigint < ActiveRecord::Migration[6.1]
    def change
        change_column :users, :seen_notification_id, :bigint
    end
end
20230215070321_change_user_badges_notification_id_to_bigint.rb
# frozen_string_literal: true

class ChangeUserBadgesNotificationIdToBigint < ActiveRecord::Migration[6.1]
    def change
        change_column :user_badges, :notification_id, :bigint
    end
end
20230215070322_change_shelved_notifications_notification_id_to_bigint.rb
# frozen_string_literal: true

class ChangeShelvedNotificationsNotificationIdToBigint < ActiveRecord::Migration[6.1]
    def change
        change_column :shelved_notifications, :notification_id, :bigint
    end
end

우리의 설정에는 커스텀 Dockerfile이 있습니다( Kubernetes에서 discourse와 sidekiq를 별도의 리소스에서 실행할 수 있도록 이미지를 빌드합니다). 따라서 Dockerfile의 일부로 이 파일들을 /db/migrate로 복사하는 작업은 간단했습니다.

그 후, rake db:migrate를 실행하여 나머지를 처리하도록 두었습니다. 모든 discourse와 sidekiq 포드에 롤링 재시작을 수행한 후, 모든 것이 예상대로 작동하기 시작했습니다 :crossed_fingers:.

3개의 좋아요

훌륭한 데이터입니다. 우리는 이를 받아들이고 코어 디스코스로 bigint 마이그레이션을 진행할 것입니다. 비용이 많이 드는 작업이지만, 대형 포럼에서 다시 발생할 것이 확실하므로 이제 해결하는 것이 좋습니다.

참고로 … OP(원문 게시글)의 주제는 post_id입니다. post_id가 오버플로되는 것을 해결하는 것은 notification보다 훨씬 더 어렵습니다. 21억 개의 게시글은 분명히 발생할 수 있지만, post_id를 bigint로 변경하는 비용은 notification id보다 훨씬 더 큽니다. 그 시간 폭탄은 조금 더 기다려도 될 것입니다.

4개의 좋아요

Brandon,

다음 PR을 적용하는 방향으로 결정할 것 같습니다:

여기서 균형을 맞춰야 할 점은, 25억 건이라는 놀라운 통지량에 도달한 1~2개의 특이한 포럼 때문에 4만 개 이상의 Discourse 인스턴스를 "벌"로 취급하고 싶지 않다는 것입니다.

어떻게 생각하시나요?

(참고: 놓친 부분 중 적어도 하나를 더 잡아낼 수 있습니다 - 채팅 테이블도 있기 때문입니다)

3개의 좋아요

이건 정말 좋네요, 현명한 해결책인 것 같아요 :slight_smile:

다시 언급하자면, 이제 병합이 완료되었습니다. :partying_face:

5개의 좋아요

이 주제는 4일 후 자동으로 닫혔습니다. 더 이상 새 답글을 작성할 수 없습니다.