+ [ $tag, $ibx, \$beg, $end, $msgs, \%want ];
+}
+
+sub cmd_uid_fetch ($$$;@) {
+ my ($self, $tag, $range, @want) = @_;
+ my $args = fetch_common($self, $tag, $range, \@want);
+ ref($args) eq 'ARRAY' ?
+ long_response($self, \&uid_fetch_m, @$args) :
+ $args; # error
+}
+
+sub seq_fetch_m { # long_response
+ my ($self, $tag, $ibx, $beg, $end, $msgs, $want) = @_;
+ if (!@$msgs) { # refill
+ @$msgs = @{$ibx->over->query_xover($$beg, $end)};
+ if (!@$msgs) {
+ $self->write(\"$tag OK Fetch done\r\n");
+ return;
+ }
+ $$beg = $msgs->[-1]->{num} + 1;
+ }
+ my $seq = $want->{-seqno}++;
+ my $cur_num = $msgs->[0]->{num};
+ if ($cur_num == $seq) { # as expected
+ my $git = $ibx->git;
+ $git->cat_async_begin; # TODO: actually make async
+ $git->cat_async($msgs->[0]->{blob}, \&uid_fetch_cb, \@_);
+ $git->cat_async_wait;
+ } elsif ($cur_num > $seq) {
+ # send dummy messages until $seq catches up to $cur_num
+ my $smsg = bless { num => $seq, ts => 0 }, 'PublicInbox::Smsg';
+ unshift @$msgs, $smsg;
+ my $bref = dummy_message($seq, $ibx);
+ uid_fetch_cb($bref, undef, undef, undef, \@_);
+ } else { # should not happen
+ die "BUG: cur_num=$cur_num < seq=$seq";
+ }
+ 1; # more messages on the way
+}
+
+sub cmd_fetch ($$$;@) {
+ my ($self, $tag, $range, @want) = @_;
+ my $args = fetch_common($self, $tag, $range, \@want);
+ ref($args) eq 'ARRAY' ? do {
+ my $want = $args->[-1];
+ $want->{-seqno} = ${$args->[2]}; # $$beg
+ long_response($self, \&seq_fetch_m, @$args)
+ } : $args; # error