데이터베이스에 직접 쓰기

여기서 데이터베이스에 직접 읽기/쓰기를 해본 분이 계신가요? 처음에는 API를 사용해 스레드와 게시글을 생성해 보았지만, 너무 불안정해서 이제는 데이터베이스에 직접 기록하는 방법을 검토하고 있습니다.

저장하고 싶은 데이터는 비교적 단순합니다: (스레드 제목, 작성자, 카테고리, 본문)과 게시글의 경우 (작성자, 본문)입니다.

하지만 여러 추가 필드도 채워야 하고, 사용자 데이터베이스에서 조회를 해야 할 수도 있다고 생각합니다.

처음부터 시작하는 것이므로, 이전에 이 작업을 해본 분이나 테이블 구조나 주의해야 할 사항에 대해 조언해 주실 분이 계신지 확인해 보고 싶습니다.

각 항목에 날짜/시간도 추가해야 한다는 걸 깜빡했어요. (원래 게시글을 수정해서 업데이트할 수 없어요.)

직접 겪은 문제들을 공유해 주시겠어요?

제 다른 게시글들을 참고할 수 있습니다. 해당 게시글들은 다음 내용들을 다루고 있습니다:

  • 레이트 리밋 문제
  • 검증 문제
  • 스레드와 토픽 간 일관되지 않게 작동하는 검증 우회

결국, API의 예측 불가능한 문제를 시간 단위로 씨름하는 것보다 데이터베이스에 직접 접근하는 것이 더 쉬울 것 같았습니다.

API의 까다로운 문제를 해결하기 위해 수 시간을 허비하는 대신, 몇 분 만에 작동하는 것을 만들었고, hopefully 더 나은 성능을 기대할 수 있었습니다:

동일한 작업을 수행하고자 하는 분들을 위해, 지금까지의 탐색 결과를 정리한 노트를 공유합니다:

먼저 컨테이너에 진입합니다:

sudo ./launcher enter app

그 다음 데이터베이스에 연결합니다:

sudo -u postgres psql discourse

토픽을 삽입하려면:
insert into topics (title, user_id, archetype, fancy_title, category_id, created_at, updated_at, last_post_user_id, bumped_at) values ('psql test', 1, 'regular', 'psql test',8, NOW(), NOW(), 1, NOW());

새로운 ID를 가져옵니다. 제 경우 886이었습니다.

그 다음 게시글을 삽입합니다:

insert into posts (user_id, topic_id, post_number, raw, cooked, created_at, updated_at, last_version_at) values (1,886,1,'this is the raw text','this is the cooked test',NOW(),NOW(),NOW());

그 다음 posts_count를 업데이트합니다(토픽 삽입 시 이미 처리되지 않은 경우). 토픽 본문에는 초기 게시글이 필요해 보입니다. 아래는 해당 토픽의 게시글 수를 1로 변경합니다:

update topics set posts_count=2 where id=886;

다른 계정을 사용 중이어서 그런 것일까요?

API를 어떻게 사용하는지 파악하는 것을 권장합니다. Rails가 많은 마법 같은 처리를 대신해 주지만, 데이터베이스를 사용할 수 없게 만드는 실수를 할 가능성이 높습니다.

하지만 토픽과 게시글 테이블에 데이터를 추가할 때, 테이블 형식이 올바르게 되어 있다면 문제가 생길 수 있는 부분이 보입니까?

이것은 정말 나쁜 아이디어입니다.

왜 이것이 API를 사용하거나 Rails 명령을 실행하여 게시물을 생성하는 것보다 더 쉽다고 생각하나요?

게시물을 생성하는 Rails 명령에 대해 알지 못했습니다. 이 부분에 대해 더 자세한 정보가 있으신가요?

네, 자세한 내용은 다음과 같습니다: Discourse는 Rails 앱입니다!

Discourse가 Rails 앱이라는 것은 알고 있습니다. 하지만 당신은 이렇게 말했죠:

따라서 'rails 명령’을 통해 스레드를 생성하는 다른 방법이 있다는 것을 시사하는 것입니다. 여기서 rails 명령이란 수동으로 계정을 생성하고 discourse 웹 프론트엔드에 직접 입력하는 것을 의미하는 것이 아니라면 말입니다.

특히 앱 외부에서 호출을 수행하는 경우 API를 사용하는 것이 좋은 관행입니다. API는 인증과 인가, 그리고 항상 가정할 수 없는 많은 비즈니스 로직을 처리해 주니까요.

제가 하고 싶은 일 중 하나는 모든 인가(authorisation)를 우회하여 게시물을 데이터베이스에 저장하는 것입니다. 사용자가 특정 카테고리에 게시물을 작성할 권한이 없거나, 주제가 너무 짧거나, 엔트로피가 부족하거나 기타 이유로 인해 게시물이 실패하지 않도록 하려는 것이죠.

모든 이러한 검사를 우회하고 단순히 게시물이나 주제만 생성하는 ‘슈퍼유저’ API 호출이 있으면 좋겠습니다.

예를 들어, 현재 특정 카테고리에 게시물을 작성할 권한이 없는 사용자 아래에 주제를 생성하려면 bypass_validations 매개변수를 사용하여 이를 수행할 수 있습니다. 그러나 같은 사용자가 답글을 생성하기 위해 API를 호출할 때, 검증 검사는 건너뛰지지 않고 스레드 생성이 실패합니다. (이것은 6년 전에 수정을 위한 풀 리퀘스트와 함께 보고되었지만, 수정이 코드베이스에 반영되지 않은 버그입니다.)

또한 이 경우, 데이터베이스에 직접 쓰는 경우와 달리 원래 스레드 생성을 롤백할 수 있는 트랜잭션 지원이 없으며, 수동으로 해당 스레드를 찾아 정리하고 수정해야 합니다.

지금은 게시물/주제를 삽입하는 것만으로도 잘 작동하는 것 같습니다. ‘cooked’ 컬럼은 NULL을 허용할 수 없어서 약간 걱정했지만, 지금은 raw와 동일한 텍스트로 채워 넣고 baked_at과 baked_version은 NULL로 두었습니다.

게시물을 볼 때 베이킹 프로세스가 꽤 빠르게 트리거되는 것으로 보입니다.

좋습니다. 재베이킹을 트리거하는 방법을 찾았습니다:

rake posts:rebake

스펙(specs)과 가져오기(import) 스크립트를 가이드로 사용하여 Ruby 명령을 통해 Discourse 데이터 구조를 조작하세요.

실험에는 Rails 콘솔을 사용하세요.

클라이언트가 Ruby로 작성된 경우, Ruby API 게임을 사용할 수 있다는 점을 짚어둘 필요가 있습니다:

Rails로 레코드를 생성하면, 게시글이 저장될 때 자동으로 rebake가 수행되며 알림 전송 등 여러 작업도 함께 실행됩니다.

게시글이 원시 데이터베이스 접근 방식으로 생성되면, Discourse도 즉시 다시 베이킹하는 것으로 보입니다.