수정 내역이 user_actions 테이블에 저장되지 않음

사용자가 다른 사람의 게시글을 수정할 때마다 이 동작이 user_actions 테이블에 기록될 것이라고 생각했는데, 방금 이것이 간헐적으로만(일부 사용자의 경우에만, 일부 시간에만) 일어난다는 것을 깨달았습니다.

이것이 의도된 동작인가요, 아니면 제가 고려하지 못한 다른 조건이 있나요?

이 문제를 재현하는 단계별 설명을 드리기 어렵지만, 제가 이를 발견한 방법은 다음과 같습니다:

  1. 수정 알림이 있는 게시글을 찾습니다:
  2. 주어진 acting_user_id(수정자), 주어진 user_id(수정 대상), 주어진 topic_id로 user_actions를 조회합니다. 제 경우:
select * from user_actions ua 
where ua.acting_user_id = 229 
and ua.user_id = 259 
and ua.target_topic_id = 1907;

다음과 같은 결과를 얻습니다:

  • Action type 2는 수정자가 수정 대상에게 좋아요(LIKE)를 보냈음을 의미합니다.
  • Action type 6은 수정자가 수정 대상에게 답변을 했음을 의미합니다.
  id   | action_type | user_id | target_topic_id | target_post_id | target_user_id | acting_user_id |         created_at         |         updated_at
-------+-------------+---------+-----------------+----------------+----------------+----------------+----------------------------+----------------------------
 78476 |           2 |     259 |            1907 |          17893 |                |            229 | 2020-03-20 03:39:12.255619 | 2020-03-20 03:39:12.395574
 78478 |           6 |     259 |            1907 |          17900 |                |            229 | 2020-03-20 03:44:04.847102 | 2020-03-20 03:44:04.847102

이 두 동작 모두 UI에서 확인할 수 있지만, EDIT을 나타내는 action_type 11도 찾아야 한다고 기대합니다.

UI에서 수정 사항을 확인하는 것 외에도, target_post_id를 사용하여 post_revisions 테이블에서 조회함으로써 그 존재를 확인할 수 있습니다:

select id, user_id, post_id, number, created_at, updated_at from post_revisions pr where post_id = 17893;

  id  | user_id | post_id | number |         created_at         |         updated_at         |
------+---------+---------+--------+----------------------------+----------------------------+--------
 8927 |     229 |   17893 |      2 | 2020-03-20 03:40:06.644576 | 2020-03-20 03:43:32.769535 |

그렇다면 왜 이 동작이 user_actions에 표시되지 않을까요?

편집은 그곳에 저장될 목적으로 설계된 것이 아니며, post_revisions에 저장됩니다.

아니, 수정이 아니라 user_action EDIT 이벤트를 말하는 거야:

문제는 이 이벤트가 90%의 경우에만 트리거된다는 거야. 나머지 10%에서는 왜 작동하지 않는지 이해가 안 돼.

수정 알림이 생성되는 경우를 내가 완전히 이해하지 못했거나, 이 문제가 내가 생각했던 것보다 훨씬 광범위한 문제일 수 있다는 것을 방금 깨달았습니다.

주요 가정

사용자 A가 사용자 B가 작성한 내용을 수정하면 다음과 같은 일들이 발생합니다:

  • post_revisions 테이블에 새로운 행이 추가됩니다.
  • action_type = 11인 새로운 행이 user_actions 테이블에 추가됩니다.
  • /u/userB/notifications/edits 경로로 이동하면 사용자 B는 사용자 A가 새로운 수정을 했다는 것을 볼 수 있습니다(이것은 user_actions에 의존합니다).
  • 자신의 게시글의 연필 아이콘을 클릭하면 사용자 B는 사용자 A가 수행한 실제 수정 내용을 볼 수 있습니다(이것은 post_revisions에 의존합니다).

테스트

위 가정들이 정확하다면, 아래 쿼리는 사용자 B(이 경우 id 259)가 생성한 게시글 중 다른 사용자(자기 자신이나 시스템 사용자가 아닌)에 의해 수정된 게시글에 대한 post_revisions 테이블의 모든 행을 action_type = 11인 user_actions의 해당 행과 함께 보여줘야 합니다.

with my_user_posts as (
  select
    p.id,
    p.user_id
  from
    posts p
  where
    p.user_id = 259 -- 사용자 id 선택
)
select
  up.user_id as my_user_id,
  ua.user_id as target_user_id,
  pr.post_id,
  ua.target_post_id,
  pr.user_id as editor_user_id,
  ua.acting_user_id,
  ua.action_type,
  pr.created_at as edit_created_at,
  ua.created_at as action_created_at
from
  post_revisions pr
  inner join my_user_posts up on up.id = pr.post_id
  and up.user_id != pr.user_id -- 자기 자신의 수정 제외
  and pr.user_id != -1 -- 시스템 수정 제외
  left join user_actions ua on ua.target_post_id = pr.post_id
  and ua.action_type = 11 -- EDIT 작업만
order by
  pr.post_id,
  pr.created_at;

예상 출력

모든 행에는 post_revisions 데이터와 user_actions 데이터가 모두 포함되어야 합니다.

실제 출력

일부 post_revisions 행에는 일치하는 user_actions 데이터가 없습니다. 따라서 사용자는 각 게시글의 연필 아이콘을 클릭하여 수정 이력을 볼 수 있지만, 여러 건의 수정을 받았다는 알림을 받지 못했습니다.

시도해 본 것들

  • user_action 데이터가 없는 오래된 게시글에 추가 수정을 수행했습니다. 결과: user_action 데이터도 나타나지 않았습니다.
  • 가짜 사용자를 생성하고, user_action 데이터가 없는 게시글의 수정 전 내용을 복사하여 해당 내용으로 게시글을 생성한 후, 다른 사용자가 수행했던 것과 동일한 수정을 적용했습니다. 결과: user_action 데이터가 올바르게 나타났습니다.
  • 사용자가 활성 상태이거나 오프라인일 때 위의 절차를 반복했습니다. 결과: 변화 없음.
  • 수정 허용 기간(editing grace period)을 변경하면서 위의 절차를 반복했습니다. 결과: 변화 없음.

결론

  • 이 문제는 다음과 같은 원인이 아닌 것 같습니다:

    • 사용자 특정 문제. 사실상 모든 사용자에게 발생합니다.
    • 연결 상태 특정 문제. 사용자가 활성 상태이거나 오프라인인지에 따라 출력이 달라지지 않습니다.
    • 시간 특정 문제. 수정 허용 기간을 변경해도 효과가 없었습니다.
  • 이 문제는 다음과 같은 원인으로 보입니다:

    • 작업(action) 특정 문제. 다른 작업(LIKE, WAS_LIKED, RESPONSE, REPLY, MENTION 또는 QUOTE)에 대한 알림 문제로는 어떤 것도 발견하지 못했습니다. 유일한 문제는 EDIT 작업과 관련되어 있습니다.

    • 게시글 특정 문제. 모든 게시글에서 발생하는 것이 아니라, 특정 게시글(무작위로 보이는)에서만 발생합니다.

  • 특정 게시글 생성 과정에서 EDIT user_actions가 저장되는 것을 방지하는 어떤 일이 일어나고 있을 가능성은 있지만, 그것이 무엇일지는 전혀 알 수 없습니다.

  • 또한 이것이 의도된 동작일 수도 있으며, 사용자가 수정에 대해 알림을 받지 않는 특정 조건이 있을 수 있지만, 어디에도 이에 대한 문서화를 찾지 못했습니다.

다음 단계

  • 수정이 발생할 때마다 수정 알림이 트리거되지 않을 수 있는 이유가 있다면 알려주세요.
  • 독자적인 Discourse 인스턴스가 있다면, 위의 SQL 쿼리를 사용자 id 중 일부에 대해 실행하여 user_actions 데이터 누락이 보이는지 확인하고 보고해 주시겠습니까?

편집 유예 기간에 대해 명확히 이해하고 계신지 100% 확인하고 싶습니다. 다른 사용자가 게시물을 편집하더라도 이 규칙은 여전히 적용됩니다.

(예, 사용자 A가 사용자 B의 게시물을 편집하면 항상 강제 편집 리비전이 생성됩니다. 하지만 이것이 사용자 A가 60초 동안 사용자 B의 게시물을 6번 편집하면 6개의 리비전과 6개의 알림이 생성된다는 뜻은 아닙니다. 위 스크린샷에서 보실 수 있듯이, 리비전과 알림은 각각 하나만 생성됩니다.)

이 각 편집들은 5분 이상 간격이 있나요?

댓글 감사합니다, Jeff. 확인 결과, 이 수정 사항들은 실제로 5분 이상 간격을 두고 이루어졌습니다. 하지만 그렇지 않더라도, post_revision이 하나만 생성되더라도 항상 그에 수반되는 EDIT user_action이 생성되어야 하는 것 아닌가요?

부연 설명으로, 편집 허용 시간(editing grace period)을 0으로 변경해 보았는데, 그렇게 하면 모든 변경 사항마다 동일한 post_revision이 두 개씩 생성됩니다. 이것이 의도된 동작인지, 아니면 별개의 버그인지는 알 수 없습니다.

그 부분을 확인해 보려던 것인데, 확인이 되어 다행입니다.

위 쿼리를 각자의 Discourse 사이트에서 실행해서, 유형 11의 user_actions가 없는 post_revisions가 나오는지 확인해 주실 수 있나요?

코드를 살펴본 결과, 다른 사람의 게시물을 편집하거나 편집과 관련된 알림을 다른 방식으로 트리거할 때만 user_action 유형 11이 반환되는 것 같습니다.

감사합니다, Sam. 그게 제가 기대했던 결과였지만, 제가 발견한 것(적어도 제 사이트에서는)과는 다릅니다. 제 쿼리 결과에서 볼 수 있듯이, 어떤 경우에는 사용자 A가 사용자 B의 게시물을 수정합니다(이 경우 post_revisions 테이블에 행이 추가되지만), user_actions 테이블에는 해당하는 행(action_type 11)이 없습니다. 바로 이 부분이 이해가 되지 않습니다.

해당 문제를 재현할 수 있나요? 한 번만 발생한 건가요?

사이트를 시작한 이후로 계속 간헐적으로 발생하고 있습니다. 위에서 언급했듯이 패턴을 파악하지 못하고 있습니다.

데이터 덤프를 제공하거나 다른 정보가 필요하신 경우 기꺼이 도움을 드리겠습니다.

잘 이해했는지 확인하기 위해 질문드립니다. 여기서 보고하신 실제 버그는 다음과 같은 것인가요?

특정 조건에서 사용자 A가 사용자 B의 게시물을 편집했는데, 사용자 B에게 알림이 전송되지 않는 경우?

맞습니다. 알림은 여기나 사용자 상자에는 표시되지 않습니다(둘 다 user_actions에 의존하기 때문):

하지만 게시글 우측 상단에는 표시됩니다(이것은 post_revisions에 의존하기 때문):

이를 테스트하기 위해 쿼리를 작성했습니다. 해당 쿼리를 사용자의 사이트에서 실행하면(다른 사용자 ID로) 역시 간격이 있는 것을 확인할 수 있습니다.

이것은 우리가 호스팅하는 인스턴스인가요, 아니면 셀프 호스팅 인스턴스인가요?

우리의 알림은 여기서 트리거됩니다:

조건은 꽤 강력합니다:

알림은 여기서 생성됩니다:

이것을 깨뜨릴 수 있는 것은

  1. Sidekiq가 작업으로 뒤섞이거나 일시 정지된 경우

  2. 알림을 보내는 도중 작업을 중간에 종료하는 매우 드문 조건입니다

내가 호스팅한 인스턴스에서 구체적인 예를 들어 설명해 드릴 수 있습니다.

이 게시물 (ID 1067)은 2019-08-03 19:22 UTC에 사용자 3에 의해 생성되었습니다. 생성된 지 몇 분 후에 저(사용자 2)가 수정을 가했습니다.

그러나 type 11의 user_action이 생성되지 않았습니다. (같은 날 해당 사용자가 게시물 1001과 1003에 대해 받은 다른 2건의 수정과 달리)

다음 쿼리를 실행하면 더 명확하게 확인할 수 있습니다:

with my_user_posts as (
  select
    p.id,
    p.user_id
  from
    posts p
  where
    p.user_id = 3 -- 사용자 ID 선택
)
select
  up.user_id as my_user_id,
  ua.user_id as target_user_id,
  pr.post_id,
  ua.target_post_id,
  pr.user_id as editor_user_id,
  ua.acting_user_id,
  ua.action_type,
  pr.created_at as edit_created_at,
  ua.created_at as action_created_at
from
  post_revisions pr
  inner join my_user_posts up on up.id = pr.post_id
  and up.user_id != pr.user_id -- 자기 자신의 수정 제외
  and pr.user_id != -1 -- 시스템 수정 제외
  left join user_actions ua on ua.target_post_id = pr.post_id
  and ua.action_type = 11 -- EDIT 작업만  
WHERE
  pr.created_at between '2019-08-03' and '2019-08-04'
order by
  pr.post_id,
  pr.created_at

일부 수치를 계산해 본 결과, 날짜에 따라 자기 자신의 수정이 아닌 post_revisions 중 7%에서 25%까지가 일치하는 user_action이 없는 것으로 나타났습니다.

결국 @Nacho_Caballero, 여기 버그가 있는 것 같네요. 잠시 기다려 주세요. 이 문제를 끈질기게 짚어 주셔서 감사합니다.

다음과 같은 버그가 있었습니다:

그리고 이 기능으로 구현을 개선했습니다:

다른 사용자의 게시글에 좋아요를 누른 후 수정을 진행하는 엣지 케이스에서, 수정 시 알림이 전송되지 않는 문제가 있었습니다.

또한, 반복적인 편집자일 경우에도 하루에 한 번은 무조건 알림을 보내도록 하는 안전 장치를 추가했습니다. (동일한 편집자의 반복적인 수정 알림은 1일 동안 억제됩니다). 현재 이 설정은 변경할 수 없습니다.

훌륭합니다. 아주 합리적이네요. 수정해 주셔서 정말 감사합니다!