【问题标题】:Catalyst event loops only reaching a single client at a timeCatalyst 事件循环一次只能到达一个客户端
【发布时间】:2026-02-03 06:00:01
【问题描述】:

我正在开发一个Catalyst/psgi 应用程序,该应用程序将充分利用异步流,但是除了一个简单的计时器(例如这里:http://www.catalystframework.org/calendar/2013/13),我对如何实现有点困惑更多“全球”事件。

对于全球事件,我的意思是:

  1. 对所有客户端都相同的周期性计时器
  2. 单个客户端对给定页面的访问(但会更新所有客户端)
  3. 一个文件状态观察器,当文件改变时更新所有客户端。

如果我错了,请纠正我,但在我看来,这些都与上面链接的示例非常不同,这将为每个客户提供不同的计数器。我希望有“全面”发生的事件。

我尝试过的一个例子(使用上面列表中的#2):

has 'write_fh' => ( is => 'rw', predicate => 'has_write_fh' );

sub events : Path('/stream') Args(0) {
    my ( $self, $c ) = @_;
    $c->res->body("");
    $c->res->content_type('text/event-stream');

    $self->write_fh( $c->res->write_fh() );
}

sub trigger : Path('/trigger') : Args(0) {
    my ( $self, $c ) = @_;

    $self->write_fh->write( *the event string* );
}

当我运行它时,它实际上比我预期的要走得更远 - 事件确实被触发了,但不可靠。在打开两个浏览器的情况下,有时事件会发送到一个,有时会发送到另一个。

现在,我想我明白为什么这永远行不通了——点击 /trigger 的客户端不知道所有其他正在观看 /stream 的客户端,因此我尝试使用的 write_fh 没有用。

但是如果每个客户端的请求都在自己包含的气泡中,我如何从其他请求访问他们的流?

还是我完全走错了路……?

【问题讨论】:

    标签: perl catalyst psgi


    【解决方案1】:

    您对 write_fh 的问题是该事件是单播的 - 一旦它被任何人接收,它将不再被接收。所以其中一个连接捕获它,而另一个根本没有。

    您需要广播您的活动。看看AnyEvent::IRC 看看它是如何实现的。

    (请注意,它是为旧版本的 AnyEvent 编写的,但它应该仍然可以工作)

    【讨论】: