加入Phoenix Channel(或其他pubsub)时同步应用程序状态

时间:2017-06-20 05:52:12

标签: elixir phoenix-framework ets phoenix-channels

我正在建立一个协作绘图板(例如r / place):有一个像素网格,用户可以随时更改像素更新,并将像素更新传播到所有其他在线用户。我想使用Phoenix Channels来广播像素变化。

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

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

我担心介于之间读取MyChannel.join中的当前状态,而用户正在订阅Phoenix的频道,不同的进程会更新状态。

用户将获得应用程序状态的陈旧版本,并且他们尚未订阅,因此他们也不会通过频道获得更新。

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

1 个答案:

答案 0 :(得分:1)

在写这个问题时,我看了一下Chris McCoord的ElixirConf 2015 training materials。我认为那个例子中有相同的竞争条件,但事实证明没有!该渠道拥有解决方案。

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

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

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

我总是说,因为我经历了以下24种可能的排序:

  • 阅读状态,
  • 改变状态,
  • 订阅频道
  • 发布到频道
订阅后确认阅读状态,并结合使用 在发布之前更新状态,保证不会丢失数据。  Here my work in a gist

它确实导致4种可能的情况,其中状态变化被看到两次,但这比数据丢失更容易处理。