gpt4 book ai didi

perl - 在 Plack 中发送无缓冲响应

转载 作者:行者123 更新时间:2023-12-04 04:42:27 26 4
gpt4 key购买 nike

我正在创建一个大型 CSV 响应的 Perl 模块的一部分。服务器在 Plack 上运行,我对它远非专家。

目前我正在使用这样的东西来发送响应:

$res->content_type('text/csv');
my $body = '';
query_data (
parameters => \%query_parameters,
callback => sub {
my $row_object = shift;
$body .= $row_object->to_csv;
},
);
$res->body($body);
return $res->finalize;

但是,那个 query_data函数不是一个快速的函数并且检索很多记录。在那里,我只是将每一行连接到 $body并且,在处理完所有行之后,发送整个响应。

我不喜欢这个有两个明显的原因:首先,在 $body 之前它需要大量 RAM。被摧毁。其次,在该方法完成工作并实际发送带有 $res->body($body) 的响应之前,用户看不到响应事件。 .

我试图找到答案 in the documentation没有找到我需要的东西。

我也试过调用 $res->body($row_object->to_csv)在我的回调部分,但似乎最终只发送了我对 $res->body 的最后一次调用,覆盖所有以前的。

有没有办法发送一个 Plack 响应来刷新每一行的内容,所以用户在收集数据时开始实时接收内容,而不必先将所有数据累积到一个可验证的数据中?

提前感谢您的任何评论!

最佳答案

您不能使用 Plack::Response因为该类旨在表示完整的响应,并且您一次永远不会在内存中获得完整的响应。您正在尝试执行的操作称为流式传输,而 PSGI supports it即使 Plack::Response 没有。

以下是您可能如何实现它(改编自您的示例代码):

my $env = shift;

if (!$env->{'psgi.streaming'}) {
# do something else...
}

# Immediately start the response and stream the content.
return sub {
my $responder = shift;
my $writer = $responder->([200, ['Content-Type' => 'text/csv']]);

query_data(
parameters => \%query_parameters,
callback => sub {
my $row_object = shift;
$writer->write($row_object->to_csv);
# TODO: Need to call $writer->close() when there is no more data.
},
);
};

关于这段代码的一些有趣的事情:
  • 而不是返回 Plack::Response对象,您可以返回 sub .稍后将调用此子例程以获取实际响应。 PSGI 支持这一点以允许所谓的“延迟”响应。
  • 我们返回的子程序得到一个参数,它是 coderef。 (在这种情况下, $responder )应该被调用并传递真正的响应。如果实际响应不包括“主体”(即 arrayref 的通常第三个元素),则 $responder将返回一个我们可以写入正文的对象。 PSGI 支持此功能以允许 流媒体回应。
  • $writer对象有两种方法,writeclose两者都完全按照他们的名字所暗示的那样做。不要忘记调用close完成响应的方法;上面的代码没有显示这一点,因为它应该如何被调用取决于如何 query_data并且您的其他代码有效。
  • 大多数服务器都支持这样的流式传输。您可以查看$env->{'psgi.streaming'}确保你的。
  • 关于perl - 在 Plack 中发送无缓冲响应,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31665534/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com