PluginStore의 적절한 사용 방법은 무엇인가요?

PluginStore가 슬랙 스레드 ID를 저장하여 스레드 응답을 처리하는 기능을 구현하는 가장 쉬운 방법인 것 같습니다. 하지만 discourse-chat-integration 전체를 살펴보니 PluginStore의 유일한 사용처가 고아 코드(orphaned) 상태이며, 조회된 값이 실제로는 어디에서도 사용되지 않는 것을 확인했습니다.

이것은 해당 기능이 비추천(deprecated)되었음을 의미하는 건가요, 아니면 다른 방식으로 처리되고 있는 건가요?

저는 토픽당 최대 1개의 값만 저장할 예정이므로, 전반적으로 볼 때 카드inality(개별 값의 다양성)가 비교적 낮은 편입니다. PluginStore에 이 정도 용도로 사용하는 것이 적절한가요?

토픽당 최대 1개의 값을 저장하는 경우, 이 사용 사례에는 토픽 사용자 정의 필드를 사용하는 것이 더 적합할 수 있습니다.

PluginStore는 단순한 KV 스토어로, 데이터의 카디널리티가 기존 사용자 정의 필드 테이블에 적합하지 않은 플러그인에서 사용됩니다. 지난 몇 년간, 투표 플러그인처럼 적절한 경우 데이터 신뢰성을 높이기 위해 플러그인을 자체 테이블로 이동하는 방향으로 전환해 왔습니다. 사용 사례에 맞는다면 여전히 PluginStore를 사용할 수 있습니다.

감사합니다, 그렇게 해보는 게 좋을 것 같아요. 여기가 처음이라, 귀찮게 하지 않으면서 배울 수 있도록 플러그인에서 토픽 커스텀 필드 예시를 하나 보여줄 수 있을까요? :smiling_face:

투표 플러그인은 discourse-topic-voting/plugin.rb at main · discourse/discourse-topic-voting · GitHub 과 https://github.com/discourse/discourse-voting/blob/master/app/jobs/onceoff/voting_ensure_consistency.rb#L53 처럼 주제 사용자 정의 필드를 일부 사용합니다.

그 방향으로 나아가면 맞을 것 같아요. 정말 감사합니다!

이것을 처음 접하는 사람이 나중에 이 글을 발견하게 된다면, Ruby on Rails를 처음 접하는 사람으로서 제가 범했던 실수 몇 가지를 공유합니다:

  • isolate_namespace가 복사할 패턴의 일부라고 생각했고, 이 네임스페이스가 데이터베이스의 항목이 아니라 라우트 네임스페이스를 가리킨다는 사실을 깨닫지 못했습니다. 이로 인해 문제가 발생했습니다. :smiling_face:
  • 커스텀 필드를 설정하는 것만으로는 저장되지 않습니다. 해당 필드가 포함된 객체(예: topic.save!)나 커스텀 필드 자체(예: topic.save_custom_fields)를 저장해야 합니다.

네, HasCustomFields 믹신에는 save_custom_fields와 자동 타입 캐스팅 등 몇 가지 장점이 있습니다.

장기적으로 플러그인 스토어와 커스텀 필드 모두를 제거하고, 훨씬 더 제한적이고 통제된 시스템으로 대체하거나 수정할 수 있다고 봅니다. 이 둘은 도움이 되는 것보다 더 많은 문제를 일으키기 때문입니다.

현재 커스텀 필드를 실제로 사용하고 정말 필요한 유일한 경우는, 게시글에 “특별한” 정보가 존재한다는 것을 직렬화기(serialize)에게 알리는 경우이거나, 시스템의 게시글 중 50%를 장식(decorate)해야 하는 예외적인 상황에서 데이터를 그곳에 저장하는 경우입니다.

커스텀 필드는 너무 유연하고 동시성(concurrency) 문제가 많습니다.

풍부한 데이터를 추가하는 가장 좋은 방법은 플러그인이 필요한 테이블을 생성하고 소유하는 것입니다. 이것이 가장 먼저 해야 할 일이며, N+1 문제나 기타 문제로 인해 막히면 이를 피하는 데 도움을 받기 위해 커스텀 필드를 사용하는 것이 좋습니다.

와, 그러면 기존 플러그인 생태계의 상당 부분이 깨지지 않을까요?

제 discourse-chat-integration 기여물(스레드 지원을 위해, 해당 주제 참고)은 여기서 받은 조언을 바탕으로 커스텀 필드를 사용했습니다.

플러그인을 위해 모델과 마이그레이션을 만드는 일반적인 방법은 무엇인가요? 메인 레일스 생성기를 사용하고 그 결과를 플러그인 폴더로 복사하시나요? 저는 플러그인 전용 접두사가 붙은 모델과 마이그레이션을 생성하는 커스텀 생성기를 직접 만들었습니다. GitHub - spirobel/discourse at plugin_model_and_migrations · GitHub 다른 분들에게도 도움이 될 수 있을 것 같습니다. :smiley:

discourse-policy와 polls 플러그인을 참고해 마이그레이션을 어떻게 처리하는지 예시를 살펴보세요. 따라야 할 패턴입니다.

변경 사항은 점진적으로 이루어지며, 이에 대한 가이드를 제공하겠습니다. 현재 플러그인 스토어와 커스텀 필드에 대한 높은 의존성은 매주 수많은 정기적인 문제를 야기하고 있습니다.

폴링(polls) 플러그인을 살펴본 후, 플러그인을 위한 모델 생성기(migration generator)와 함께 이 마이그레이션 생성기를 만들었습니다:

제 이해가 맞다면, 플러그인스토어가 처음 만들어진 이유 중 하나는 플러그인이 자체 테이블을 생성할 때 이름 충돌이 발생할 수 있다는 우려 때문이었습니다. 제가 만든 생성기는 모델과 마이그레이션의 이름 앞에 플러그인 이름을 접두사로 붙입니다. 이 생성기들을 만든 주된 이유는 마이그레이션이 예측 가능한 순서를 만들기 위해 앞에 날짜 숫자가 필요하기 때문이며, 그래서 수동으로 만들고 싶지 않았습니다.

충돌은 이론적으로는 문제가 될 수 있었지만, 큰 동기는 아니었습니다. 큰 동기는 마이그레이션을 실행하는 방법에 대해 다소 불분명했고, 매우 낮은 마찰(low friction)을 원했기 때문이었습니다. 요즘에는 플러그인에서 마이그레이션을 만드는 것이 자명(trivial)한 일입니다. 단순히 마이그레이션 폴더에 파일을 생성하면 됩니다.

어쨌든, 사용자 정의 필드(post custom fields)에서는 여전히 충돌이 발생할 수 있습니다.