1

我正在构建一个协作绘图板(例如 r/place):有一个像素网格,用户可以随时更改它,并且像素更新会在线传播给所有其他用户。我想使用凤凰频道来广播像素变化。

我的问题是关于当用户连接到服务时如何正确发送当前应用程序状态。

目前我有一个 ETS 表保存绘图板状态。我可以MyChannel.handle_in/3在广播任何像素写入之前更新此表。

我担心读取当前状态MyChannel.join和用户被 Phoenix 订阅频道之间,不同的进程会更新状态。

用户将获得应用程序状态的陈旧版本,并且他们还没有被订阅,因此他们也不会通过 Channel 获得更新。

为了解决这个问题,我认为我需要一种方法来自动读取当前状态,然后订阅 pubsub,确保在该时间段内没有消息写入 ETS 表或 Channel。我猜是锁?是 Elixirey,还是有其他方法?

4

1 回答 1

2

在写这个问题时,我查看了 Chris McCoord 的ElixirConf 2015 培训材料。我认为在该示例中存在相同的竞争条件,但事实证明没有!该渠道拥有解决方案。

在该示例中,Channel.join函数进程向自身发送一条 :after_join 消息,该消息稍后(在被订阅后)将触发 handle_info({:after_join...}) 读取应用程序状态并将其发送给用户。

关键是在订阅后查询应用状态。

并且总是在发布前改变状态。

我总是这么说是因为我经历了以下 24 种可能的顺序中的每一种:

  • 读取状态,
  • 改变状态,
  • 订阅频道
  • 发布到频道

并确认订阅后读取状态,结合发布前更新状态,保证不丢失数据。 这是我的工作要点

它确实会导致 4 种可能的情况,其中状态更改会出现两次,但这比数据丢失更容易处理。

于 2017-06-20T06:16:23.233 回答