음, 엄밀히 말해 bug은 아닐 수도 있고, 원래 그렇게 설계된 것일 수도 있지만, JS 쪽에서 presence가 어떻게 업데이트되는지에 대해 몇 가지 의문이 있습니다. 관련 파일은 app/assets/javascripts/discourse/app/services/presence.js입니다.
지금까지 파악한 바로는 JS 클라이언트는 다음과 같은 동작을 합니다:
업데이트 대기열이 비어 있지 않을 경우, 업데이트를 1초에 1회로 스로틀링합니다.
변경 사항이 없을 경우, 30초에 1회 요청을 보냅니다.
관찰해 본 결과, 서버에 어떤 이유로든 오류가 발생하면 JS가 1초마다 계속 요청을 보내는 것을 확인했습니다. 또한 콘솔에 Uncaught (in promise) 오류가 565번째 줄에서 발생합니다.
서버에 과부하를 주지 않도록 N번의 오류 후에는 요청을 중단하는 것이 아닌가 싶습니다.
재현 방법
presence_controller.rb의 update 메서드에서 오류를 시뮬레이션하세요. (제 경우 데모를 위해 status 405를 렌더링했습니다)
def update
# JS client is designed to throttle to one request per second
# When no changes are being made, it makes one request every 30 seconds
RateLimiter.new(nil, "update-presence-#{current_user.id}", 20, 10.seconds).performed!
render json: { error: "Not authorized" }, status: 405
return
...
그 다음 클라이언트에서 presence 관리가 있는 화면으로 이동하세요. 저는 토픽 답변 화면을 선택하고 답변을 작성하기 시작했습니다.
PresenceChannelAutoLeave라는 백그라운드 잡이 매 분마다 실행되며, 만료된 멤버들이 채널을 나가도록 합니다.
presence_channel.rb의 present(user:, client_id:) 메서드에도 다음과 같이 주석으로 명시되어 있습니다:
# Mark a user's client as present in this channel. The client_id should be unique per
# browser tab. This method should be called repeatedly (at least once every DEFAULT_TIMEOUT)
# while the user is present in the channel.
def present(user:, client_id:)