]> Sergey Matveev's repositories - public-inbox.git/blobdiff - lib/PublicInbox/ManifestJsGz.pm
wwwlisting: avoid hogging event loop
[public-inbox.git] / lib / PublicInbox / ManifestJsGz.pm
index 328303ceb097abbc9558b0c62fbf19176cded78a..f98d9d010925dcf1a6d6a1ff8fca89f7ad65eec5 100644 (file)
@@ -1,8 +1,11 @@
 # Copyright (C) 2020 all contributors <meta@public-inbox.org>
 # License: AGPL-3.0+ <https://www.gnu.org/licenses/agpl-3.0.txt>
+
+# generates manifest.js.gz for grokmirror(1)
 package PublicInbox::ManifestJsGz;
 use strict;
 use v5.10.1;
+use parent qw(PublicInbox::WwwListing);
 use Digest::SHA ();
 use File::Spec ();
 use bytes (); # length
@@ -19,22 +22,12 @@ for my $mod (qw(JSON::MaybeXS JSON JSON::PP)) {
        $json = $mod->new->ascii(1) and last;
 }
 
-sub response {
-       my ($env, $list) = @_;
-       $json or return [ 404, [], [] ];
-       my $self = bless {
-               -abs2urlpath => {},
-               -mtime => 0,
-               manifest => {},
-               -list => $list,
-               psgi_env => $env,
-       }, __PACKAGE__;
-
-       # PSGI server will call this immediately and give us a callback (-wcb)
-       sub {
-               $self->{-wcb} = $_[0]; # HTTP write callback
-               iterate_start($self);
-       };
+# called by WwwListing
+sub url_regexp {
+       my ($ctx) = @_;
+       # grokmirror uses relative paths, so it's domain-dependent
+       # SUPER calls PublicInbox::WwwListing::url_regexp
+       $ctx->SUPER::url_regexp('publicInbox.grokManifest', 'match=domain');
 }
 
 sub fingerprint ($) {
@@ -53,7 +46,7 @@ sub fingerprint ($) {
 }
 
 sub manifest_add ($$;$$) {
-       my ($self, $ibx, $epoch, $default_desc) = @_;
+       my ($ctx, $ibx, $epoch, $default_desc) = @_;
        my $url_path = "/$ibx->{name}";
        my $git_dir = $ibx->{inboxdir};
        if (defined $epoch) {
@@ -92,12 +85,12 @@ sub manifest_add ($$;$$) {
                        $reference =~ s!/[^/]+/?\z!!; # basename
                }
        }
-       $self->{-abs2urlpath}->{$git_dir} = $url_path;
+       $ctx->{-abs2urlpath}->{$git_dir} = $url_path;
        my $modified = $git->modified;
-       if ($modified > $self->{-mtime}) {
-               $self->{-mtime} = $modified;
+       if ($modified > ($ctx->{-mtime} // 0)) {
+               $ctx->{-mtime} = $modified;
        }
-       $self->{manifest}->{$url_path} = {
+       $ctx->{manifest}->{$url_path} = {
                owner => $owner,
                reference => $reference,
                description => $desc,
@@ -106,48 +99,37 @@ sub manifest_add ($$;$$) {
        };
 }
 
-sub iterate_start {
-       my ($self) = @_;
-       if (my $async = $self->{psgi_env}->{'pi-httpd.async'}) {
-               # PublicInbox::HTTPD::Async->new
-               $async->(undef, undef, $self);
-       } else {
-               event_step($self) while $self->{-wcb};
-       }
-}
-
-sub event_step {
-       my ($self) = @_;
-       while (my $ibx = shift(@{$self->{-list}})) {
-               eval {
-                       if (defined(my $max = $ibx->max_git_epoch)) {
-                               my $desc = $ibx->description;
-                               for my $epoch (0..$max) {
-                                       manifest_add($self, $ibx, $epoch, $desc)
-                               }
-                       } else {
-                               manifest_add($self, $ibx);
+sub ibx_entry {
+       my ($ctx, $ibx) = @_;
+       eval {
+               if (defined(my $max = $ibx->max_git_epoch)) {
+                       my $desc = $ibx->description;
+                       for my $epoch (0..$max) {
+                               manifest_add($ctx, $ibx, $epoch, $desc);
                        }
-               };
-               warn "E: $@" if $@;
-               if (my $async = $self->{psgi_env}->{'pi-httpd.async'}) {
-                       # PublicInbox::HTTPD::Async->new
-                       $async->(undef, undef, $self);
+               } else {
+                       manifest_add($ctx, $ibx);
                }
-               return; # more steps needed
-       }
-       my $abs2urlpath = delete $self->{-abs2urlpath};
-       my $wcb = delete $self->{-wcb};
-       my $manifest = delete $self->{manifest};
+       };
+       warn "E: $@" if $@;
+}
+
+sub hide_key { 'manifest' }
+
+# overrides WwwListing->psgi_triple
+sub psgi_triple {
+       my ($ctx) = @_;
+       my $abs2urlpath = delete($ctx->{-abs2urlpath}) // {};
+       my $manifest = delete($ctx->{manifest}) // {};
        while (my ($url_path, $repo) = each %$manifest) {
                defined(my $abs = $repo->{reference}) or next;
                $repo->{reference} = $abs2urlpath->{$abs};
        }
        $manifest = $json->encode($manifest);
        gzip(\$manifest => \(my $out));
-       $wcb->([ 200, [ qw(Content-Type application/gzip),
-                'Last-Modified', time2str($self->{-mtime}),
-                'Content-Length', bytes::length($out) ], [ $out ] ]);
+       [ 200, [ qw(Content-Type application/gzip),
+                'Last-Modified', time2str($ctx->{-mtime}),
+                'Content-Length', bytes::length($out) ], [ $out ] ]
 }
 
 1;