用户操作表中未存储编辑内容

我原以为每次用户编辑他人的帖子时,该操作都会被记录在 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;

结果如下:

  • 操作类型 2 表示编辑者向被编辑者发送了点赞。
  • 操作类型 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 中确认这两项操作,但我也期望能找到表示编辑操作的操作类型 11。

除了在 UI 中看到编辑记录外,我还可以通过查询 post_revisions 表并指定 target_post_id 来确认编辑的存在:

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 中呢?

1 个赞

编辑不应存储在那里,它们存储在 post_revisions 中。

2 个赞

好的,不是编辑。我指的是 user_action 的 EDIT 事件:

问题是它 90% 的情况下都会被触发。我不明白为什么另外 10% 的情况不起作用。

1 个赞

我刚刚意识到,要么是我对创建编辑通知的情况理解不够全面,要么这是一个比我想象中更普遍的问题。

主要假设

如果用户 A 编辑了用户 B 撰写的内容,会发生以下几件事:

  • post_revisions 表中会添加一行新记录。
  • user_actions 表中会添加一行新记录,其中 action_type = 11
  • 通过访问 /u/userB/notifications/edits,用户 B 将能够看到用户 A 进行的编辑(这依赖于 user_actions)。
  • 通过点击帖子中的铅笔图标,用户 B 将能够查看用户 A 执行的具体编辑内容(这依赖于 post_revisions)。

测试

如果上述假设正确,以下查询应显示 post_revisions 表中由用户 B(在此例中为 ID 259)创建的所有帖子记录,这些帖子被任何用户(除其本人或系统用户外)编辑过,并包含 user_actions 表中对应的 action_type = 11 的记录

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 -- 仅编辑操作
order by
  pr.post_id,
  pr.created_at;

预期输出

每一行都应同时包含 post_revisions 数据和 user_actions 数据。

实际输出

部分 post_revisions 记录没有匹配的 user_actions 数据。因此,用户可以通过点击每个帖子中的铅笔图标查看修订记录,但并未收到关于多次编辑的通知

我已尝试的操作

  • 对一条没有 user_action 数据的旧帖子添加额外编辑。结果user_action 数据也未出现。
  • 创建一个假用户,复制没有 user_action 数据的帖子的编辑前内容,用该内容创建新帖子,并应用与其他用户相同的编辑操作。结果user_action 数据正确出现。
  • 重复上述操作,分别测试用户在线和离线状态。结果:无变化。
  • 重复上述操作,修改编辑宽限期。结果:无变化。

结论

  • 该问题似乎不是:

    • 用户特定的。几乎每个用户都会遇到。
    • 连接特定的。用户在线或离线状态不影响结果。
    • 时间特定的。修改编辑宽限期没有效果。
  • 该问题似乎与以下因素相关:

    • 操作特定。我尚未发现其他操作(如 LIKE、WAS_LIKED、RESPONSE、REPLY、MENTION 或 QUOTE)的通知存在问题。唯一的问题是 EDIT 操作。
    • 帖子特定。并非所有帖子都会出现此问题,仅特定帖子(看似随机)会受影响。
  • 一种可能性是,在创建某些特定帖子时,某种机制阻止了 EDIT user_actions 的保存,但我不知道具体原因。

  • 也有可能是按设计如此,即在特定条件下用户不会收到编辑通知,但我尚未在任何文档中看到相关说明。

后续步骤

  • 如果您知道为什么编辑通知可能不会在每次编辑时都被触发,请告知我。
  • 如果您有自己的 Discourse 实例,能否在某些用户 ID 上运行上述 SQL 查询,查看是否也出现 user_actions 数据缺失的情况,并反馈结果?
1 个赞

我只想确认您是否完全清楚编辑宽限期,即使是由另一位用户编辑帖子,该宽限期仍然适用。

(是的,如果用户 A 编辑用户 B 的帖子,系统总是会强制生成一个编辑修订版本。但这并不意味着,如果用户 A 在 60 秒内编辑用户 B 的帖子 6 次,就会生成 6 个修订版本和 6 条通知。正如您在上面的截图中所见,只会生成一个修订版本和一条通知。)

这些编辑是否每次间隔超过 5 分钟

2 个赞

Jeff,感谢你的评论。我可以确认,是的,这些编辑之间的间隔确实超过了 5 分钟。但即使不是这样,只要创建了一个 post_revision,难道不应该始终伴随一个 EDIT user_action 吗?

顺便提一下,我还尝试将编辑宽限期改为 0,结果发现每次更改都会创建两个完全相同的 post_revision。我不确定这是设计如此,还是另一个无关的 bug。

只是想确认一下,确认一下很好。

1 个赞

是否有人能在自己的 Discourse 站点上运行上述查询,看看是否也会出现没有对应类型为 11 的 user_actions 的 post_revisions?

仔细查看我们的代码后,我认为只有在编辑他人的帖子或通过其他方式触发与该编辑相关的通知时,才会获得 user_action 类型为 11 的记录。

3 个赞

谢谢,Sam。这正是我所预期的,但实际情况并非如此(至少在我的网站上是这样)。正如我的查询结果所示,在某些情况下,用户 A 编辑了用户 B 的帖子(这会在 post_revisions 中添加一行),但 user_actions 表中却没有对应的行(action_type 为 11)。这一点让我感到困惑。

您有该问题的复现步骤吗?是偶尔发生还是仅出现一次?

1 个赞

从我建立网站以来,这种情况就断断续续地持续发生。正如我上面提到的,我尚未发现其中的规律。

如果可以通过数据转储的方式向您提供信息,或者您需要其他资料,我很乐意协助。

为了确认我的理解,您在此报告的实际错误是:

在某些情况下,用户 A 编辑了用户 B 的帖子,但用户 B 未收到通知?

1 个赞

没错。通知不会在此处或用户框中显示(因为两者都依赖于 user_actions):

不过,它会在帖子的右上角显示(因为该位置依赖于 post_revisions):

我写了一个查询来测试这一点。如果你在你的网站上运行它(使用不同的用户 ID),你也应该能看到这些空白。

1 个赞

这是由我们托管的实例,还是自托管的实例?

我们的通知在此处触发:

该条件非常严格:

通知在此处创建:

可能导致此问题中断的因素包括:

  1. Sidekiq 任务积压或被暂停

  2. 在通知过程中异常终止任务的极罕见情况

2 个赞

我可以举一个由您托管的实例中的具体例子。

此帖子(ID 1067)由用户 3 于 2019-08-03 19:22 UTC 创建,几分钟后被我(用户 2)编辑。

然而,并没有创建类型为 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 -- 仅编辑操作  
WHERE
  pr.created_at between '2019-08-03' and '2019-08-04'
order by
  pr.post_id,
  pr.created_at

我进行了一些统计,根据不同日期,7% 到 25% 的非自编辑 post_revisions 没有对应的 user_action。

看来我们这里确实有个 bug @Nacho_Caballero,请稍等。感谢你的坚持。

3 个赞

我们曾遇到以下问题:

随后,我通过以下功能改进了实现:

此前存在一个边界情况:当用户点赞了另一位用户的帖子,随后又编辑该帖子时,系统不会就编辑操作发出通知。

此外,我还添加了一项安全机制,确保即使是由同一编辑者重复编辑,每天至少无条件通知一次(同一编辑者的重复编辑通知会在 1 天内被抑制)。目前该机制尚不可配置。

6 个赞

太好了,这很有道理。非常感谢你的修复!

1 个赞