해결책
API 메서드 끝에 다음 코드를 추가하는 것으로 문제를 해결했습니다:
MessageBus.publish("/topic/#{@topic.id}", reload_topic: true, refresh_stream: true)
이렇게 하면 현재 사용자에게만 아니라 해당 토픽을 보고 있는 다른 모든 사용자에게도 새로고침이 이루어져야 합니다.
여기까지 도달하게 된 탐색 과정
코드베이스를 따라 함께 보고 싶다면 아래를 읽어보세요. 다른 분들에게도 유용할 수 있어 공유합니다.
MessageBus란?
Sam의 2013년 MessageBus 설명에 따르면 Ruby 코드는 게시(publish)와 구독(subscribe)을 할 수 있는 반면, Javascript 코드는 구독만 할 수 있는 것 같습니다. 즉, 제안된 아키텍처에 따르면 서버 측 코드가 UI를 알리는 역할을 담당하게 됩니다.
저에게 유용한 MessageBus 예시가 있나요?
플러그인 예시 중 MessageBus를 사용하는 것은 없습니다.
GroupArchivedMessage.move_to_inbox!은 제가 원하는 것과 다소 유사한 이 코드를 호출하지만, 여기서 사용되는 type 코드는 제 경우에 사용할 수 없습니다.
MessageBus.publish("/topic/#{topic_id}", { type: "move_to_inbox" }, group_ids: [group_id])
이 코드는 유망해 보입니다.
MessageBus.publish("/topic/#{@topic.id}", reload_topic: true, refresh_stream: true)
제가 최종적으로 선택한 해결책입니다.
브라우저가 업데이트를 수신하면 어떻게 되나요?
Topics 컨트롤러는 현재 보고 있는 토픽의 업데이트를 구독합니다. 이는 "post-stream:refresh"를 트리거하여 새로고침을 시작합니다. 다른 끝에서 이 이벤트를 수신하는 것으로 찾을 수 있는 것은 ScrollingPostStream뿐이며, 이는 _refresh 메서드를 이벤트에 바인딩합니다. 이것이 실제로 업데이트를 수행하는 것으로 보입니다.
이로부터, 다른 사용자에게 업데이트를 푸시하지 않고 현재 클라이언트만 업데이트하려면 동일한 코드를 직접 호출할 수 있다고 추론할 수 있습니다:
this.appEvents.trigger("post-stream:refresh", args)
그리고 이는 어떤 컴포넌트에서든 호출할 수 있는 것으로 보입니다.
move_posts의 원래 구현은 어떻게 되나요? MessageBus에 게시하나요?
코어 코드를 조사해 보니: 토픽 컨트롤러의 move_posts() 메서드는 move_posts_to_destination()를 호출하고, 이는 topic.move_posts()를 호출하며, 이는 new PostMover()를 호출한 후 to_topic() 또는 to_new_topic()를 호출합니다. 이 메서드들은 MessageBus를 호출하지 않지만 DiscourseEvent.trigger()는 호출합니다.
저는 커스텀 API 메서드에서 topic.move_posts()를 호출합니다. 즉, 제 코드는 컨트롤러 로직을 건너뛰고 모델로 직접 호출합니다:
new_topic = topic.move_posts(current_user, [post.id], {title: title, category_id: category_id})
제 경우, 시퀀스의 마지막 단계로 move_posts_to()가 호출되며, 이는 다음을 호출합니다:
DiscourseEvent.trigger(
:posts_moved,
destination_topic_id: destination_topic.id,
original_topic_id: original_topic.id,
)
그러나 DiscourseEvent는 MessageBus와 아무 관련이 없는 것 같습니다. 서버 내부의 라이프사이클에만 사용되는 걸까요?
따라서 토픽 이동 시 MessageBus에 게시되지 않는다고 결론 내립니다.