diff options
author | Eric Wong <e@yhbt.net> | 2020-07-05 23:27:24 +0000 |
---|---|---|
committer | Eric Wong <e@yhbt.net> | 2020-07-06 20:01:15 +0000 |
commit | f26183401e3abfb64ad82537151f2718ac889074 (patch) | |
tree | ff5118417538eae8375c9bdc5023ceca1d1e647a /lib/PublicInbox/MboxGz.pm | |
parent | 967f6d1b1626392ee4340ea356a00651462377b3 (diff) | |
download | public-inbox-f26183401e3abfb64ad82537151f2718ac889074.tar.gz |
The new ->zmore and ->zflush APIs make it possible to replace existing verbose usages of Compress::Raw::Deflate and simplify buffering logic for streaming large gzipped data. One potentially user visible change is we now break the mbox.gz response on zlib failures, instead of silently continuing onto the next message. zlib only seems to fail on OOM, which should be rare; so it's ideal we drop the connection anyways.
Diffstat (limited to 'lib/PublicInbox/MboxGz.pm')
-rw-r--r-- | lib/PublicInbox/MboxGz.pm | 41 |
1 files changed, 11 insertions, 30 deletions
diff --git a/lib/PublicInbox/MboxGz.pm b/lib/PublicInbox/MboxGz.pm index f7fc4afc..535ef96c 100644 --- a/lib/PublicInbox/MboxGz.pm +++ b/lib/PublicInbox/MboxGz.pm @@ -2,19 +2,19 @@ # License: AGPL-3.0+ <https://www.gnu.org/licenses/agpl-3.0.txt> package PublicInbox::MboxGz; use strict; -use warnings; +use parent 'PublicInbox::GzipFilter'; use PublicInbox::Eml; use PublicInbox::Hval qw/to_filename/; use PublicInbox::Mbox; -use Compress::Raw::Zlib qw(Z_FINISH Z_OK); -my %OPT = (-WindowBits => 15 + 16, -AppendOutput => 1); sub new { my ($class, $ctx, $cb) = @_; $ctx->{base_url} = $ctx->{-inbox}->base_url($ctx->{env}); - my ($gz, $err) = Compress::Raw::Zlib::Deflate->new(%OPT); - $err == Z_OK or die "Deflate->new failed: $err"; - bless { gz => $gz, cb => $cb, ctx => $ctx }, $class; + bless { + gz => PublicInbox::GzipFilter::gzip_or_die(), + cb => $cb, + ctx => $ctx + }, $class; } sub response { @@ -27,40 +27,21 @@ sub response { [ 200, $h, $body ]; } -sub gzip_fail ($$) { - my ($ctx, $err) = @_; - $ctx->{env}->{'psgi.errors'}->print("deflate failed: $err\n"); - ''; -} - # called by Plack::Util::foreach or similar sub getline { my ($self) = @_; my $ctx = $self->{ctx} or return; - my $gz = $self->{gz}; - my $buf = delete($self->{buf}); while (my $smsg = $self->{cb}->($ctx)) { my $mref = $ctx->{-inbox}->msg_by_smsg($smsg) or next; my $h = PublicInbox::Eml->new($mref)->header_obj; - - my $err = $gz->deflate( - PublicInbox::Mbox::msg_hdr($ctx, $h, $smsg->{mid}), - $buf); - return gzip_fail($ctx, $err) if $err != Z_OK; - - $err = $gz->deflate(PublicInbox::Mbox::msg_body($$mref), $buf); - return gzip_fail($ctx, $err) if $err != Z_OK; - - return $buf if length($buf) >= 8192; - - # be fair to other clients on public-inbox-httpd: - $self->{buf} = $buf; - return ''; + $self->zmore( + PublicInbox::Mbox::msg_hdr($ctx, $h, $smsg->{mid}) + ); + return $self->translate(PublicInbox::Mbox::msg_body($$mref)); } # signal that we're done and can return undef next call: delete $self->{ctx}; - my $err = $gz->flush($buf, Z_FINISH); - ($err == Z_OK) ? $buf : gzip_fail($ctx, $err); + $self->zflush; } sub close {} # noop |