Štěpán Němec <stepnem@smrk.net> wrote: > On Sat, 16 Mar 2024 21:27:56 +0000 > Eric Wong wrote: > > > Štěpán Němec <stepnem@smrk.net> wrote: > >> The difference between the "numerous optional modules" > >> section (containing only two modules) and the "everything > >> else optional" section was unclear (to me, at least). > >> Just put both under a single heading. > > > > <snip> > > > >> +++ b/INSTALL > >> @@ -58,7 +58,8 @@ Where "deb" indicates package names for Debian-derived distributions, > >> "pkgin" for NetBSD, "apk" for Alpine Linux and "rpm" is for RPM-based > >> distributions (only known to work on Fedora). > >> > >> -Numerous optional modules are likely to be useful as well: > >> +Numerous optional modules might be useful as well, depending > >> +on your use case and preferences: > >> > > > > OK, I like the first change. > > > >> - DBD::SQLite deb: libdbd-sqlite3-perl > >> pkg: p5-DBD-SQLite > >> @@ -71,8 +72,6 @@ Numerous optional modules are likely to be useful as well: > >> rpm: perl-Search-Xapian > >> (required for lei; HTTP and IMAP search) > >> > >> -Every effort has been to make everything else optional: > >> - > > > > I consider DBD::SQLite and Xapian significantly more important > > than the rest, so I favor keeping the above line. > > The main issue I see with that (as mentioned in my commit > message) is that you first say numerous optional modules are > useful, list only two modules after that, then say > everything else is optional. "else"? So, all modules are > optional, but some are more optional than others? :-P > > I'd say a single heading and keeping further details to the > parentheticals pertaining to specific modules is both > clearer and easier to maintain, but whatever version you > choose, I as reader see the following issues with the old > text (and at least some of those issues would remain if you > kept my first hunk and not the second, as you suggest): > > - the difference between the two sections is unclear > - it doesn't make sense to first single out two modules as > optional, and then continue with "make everything else > optional" > - two are not "numerous" > - "Every effort has been to make everything else optional" > sounds weird to me. Is "made" missing after "been"? Yes, my brain was interpolating "made" in without realizing it wasn't in the text :x > Or maybe "We've tried to make everything else optional" or > "Everything else is supposed to be optional"? > - Perhaps "optional" isn't really the right word for the > general description to begin with, given that some modules > are required in some cases (indicated by parentheticals)? Yeah, probably "optional" is the wrong word. > A different attempt based on your feedback: OK, pushed as commit 7de64dc25f8348f902f2815d520ecce3d0e90ca8 Thanks.
On Sat, 16 Mar 2024 21:27:56 +0000 Eric Wong wrote: > Štěpán Němec <stepnem@smrk.net> wrote: >> The difference between the "numerous optional modules" >> section (containing only two modules) and the "everything >> else optional" section was unclear (to me, at least). >> Just put both under a single heading. > > <snip> > >> +++ b/INSTALL >> @@ -58,7 +58,8 @@ Where "deb" indicates package names for Debian-derived distributions, >> "pkgin" for NetBSD, "apk" for Alpine Linux and "rpm" is for RPM-based >> distributions (only known to work on Fedora). >> >> -Numerous optional modules are likely to be useful as well: >> +Numerous optional modules might be useful as well, depending >> +on your use case and preferences: >> > > OK, I like the first change. > >> - DBD::SQLite deb: libdbd-sqlite3-perl >> pkg: p5-DBD-SQLite >> @@ -71,8 +72,6 @@ Numerous optional modules are likely to be useful as well: >> rpm: perl-Search-Xapian >> (required for lei; HTTP and IMAP search) >> >> -Every effort has been to make everything else optional: >> - > > I consider DBD::SQLite and Xapian significantly more important > than the rest, so I favor keeping the above line. The main issue I see with that (as mentioned in my commit message) is that you first say numerous optional modules are useful, list only two modules after that, then say everything else is optional. "else"? So, all modules are optional, but some are more optional than others? :-P I'd say a single heading and keeping further details to the parentheticals pertaining to specific modules is both clearer and easier to maintain, but whatever version you choose, I as reader see the following issues with the old text (and at least some of those issues would remain if you kept my first hunk and not the second, as you suggest): - the difference between the two sections is unclear - it doesn't make sense to first single out two modules as optional, and then continue with "make everything else optional" - two are not "numerous" - "Every effort has been to make everything else optional" sounds weird to me. Is "made" missing after "been"? Or maybe "We've tried to make everything else optional" or "Everything else is supposed to be optional"? - Perhaps "optional" isn't really the right word for the general description to begin with, given that some modules are required in some cases (indicated by parentheticals)? A different attempt based on your feedback: -- >8 -- Subject: [PATCH] INSTALL: try to be less confusing about optional modules --- INSTALL | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/INSTALL b/INSTALL index c04831c2fb5b..3c5890b43517 100644 --- a/INSTALL +++ b/INSTALL @@ -58,7 +58,7 @@ Where "deb" indicates package names for Debian-derived distributions, "pkgin" for NetBSD, "apk" for Alpine Linux and "rpm" is for RPM-based distributions (only known to work on Fedora). -Numerous optional modules are likely to be useful as well: +Most users will likely also want the following: - DBD::SQLite deb: libdbd-sqlite3-perl pkg: p5-DBD-SQLite @@ -71,7 +71,8 @@ Numerous optional modules are likely to be useful as well: rpm: perl-Search-Xapian (required for lei; HTTP and IMAP search) -Every effort has been to make everything else optional: +Other modules might be useful as well, depending on your use case and +preferences: - Plack deb: libplack-perl pkg: p5-Plack base-commit: 5e8068b28aa01befa9c6fa7368db956148816189 prerequisite-patch-id: fc68213abff90eb709806fcae4dad389f2e59959 -- 2.44.0 Thanks, Štěpán
thanks, pushed
Štěpán Němec <stepnem@smrk.net> wrote: > The difference between the "numerous optional modules" > section (containing only two modules) and the "everything > else optional" section was unclear (to me, at least). > Just put both under a single heading. <snip> > +++ b/INSTALL > @@ -58,7 +58,8 @@ Where "deb" indicates package names for Debian-derived distributions, > "pkgin" for NetBSD, "apk" for Alpine Linux and "rpm" is for RPM-based > distributions (only known to work on Fedora). > > -Numerous optional modules are likely to be useful as well: > +Numerous optional modules might be useful as well, depending > +on your use case and preferences: > OK, I like the first change. > - DBD::SQLite deb: libdbd-sqlite3-perl > pkg: p5-DBD-SQLite > @@ -71,8 +72,6 @@ Numerous optional modules are likely to be useful as well: > rpm: perl-Search-Xapian > (required for lei; HTTP and IMAP search) > > -Every effort has been to make everything else optional: > - I consider DBD::SQLite and Xapian significantly more important than the rest, so I favor keeping the above line. > - Plack deb: libplack-perl > pkg: p5-Plack > rpm: perl-Plack, perl-Plack-Test,
> please keep meta@public-inbox.org in the Cc: Ok. > No, please don't ask Debian maintainers to package unreleased > versions. The non-lei feature: codesearch, is not ready to be > supported in a 2.0 release. > > The only good news is 2.0 will probably be the last release > involving large data model additions/changes. Ok. Thanks. I'll just wait for 2.0. -- g
--- Documentation/RelNotes/v2.0.0.wip | 10 +++++----- Documentation/public-inbox-config.pod | 2 +- INSTALL | 2 +- examples/public-inbox-netd@.service | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Documentation/RelNotes/v2.0.0.wip b/Documentation/RelNotes/v2.0.0.wip index 53ef5fe5c7a1..4d872fd721db 100644 --- a/Documentation/RelNotes/v2.0.0.wip +++ b/Documentation/RelNotes/v2.0.0.wip @@ -43,8 +43,8 @@ New users + hackers: The install/ directory includes tools to automate installation and - removal of dependencies for stripped down or full setups. See - install/README for more details + removal of dependencies for stripped-down or full setups. See + install/README for more details. treewide @@ -52,7 +52,7 @@ * standardize on `#' prefix for stderr diagnostics (previously `I:') - * SHA-256 coderepos are fully-supported (but not inboxes, yet) + * SHA-256 coderepos are fully supported (but not inboxes, yet) * jemalloc (tested as an LD_PRELOAD) is recommended to reduce fragmentation in long-running daemon processes serving unpredictable traffic @@ -174,8 +174,8 @@ * `public-inbox-cindex --join' prefers using Xapian's C++ API directly to avoid Perl method dispatch overhead to get usable - performance assocating ~300 inboxes with over 1K coderepos - (and vice-versa). Users needing this performance will need + performance associating ~300 inboxes with over 1K coderepos + (and vice versa). Users requiring such performance will need a C++ compiler, pkg-config, and the Xapian development files (see INSTALL). diff --git a/Documentation/public-inbox-config.pod b/Documentation/public-inbox-config.pod index d3f5d04b0644..b4a1d94dec00 100644 --- a/Documentation/public-inbox-config.pod +++ b/Documentation/public-inbox-config.pod @@ -390,7 +390,7 @@ Default: C<404> =item publicinbox.nameIsUrl Treat the name of the public inbox as its unqualified URL when -using C<publicInbox.wwwListing=all>. This is, every +using C<publicInbox.wwwListing=all>. That is, every C<[publicinbox "foo"]> section implicitly sets C<publicinbox.foo.url=foo>. This is a convenient alternative to specifying diff --git a/INSTALL b/INSTALL index b1d7fd1b68e9..c04831c2fb5b 100644 --- a/INSTALL +++ b/INSTALL @@ -6,7 +6,7 @@ lei as a command-line tool. Any HTTP, IMAP, NNTP, or POP3 client can access public-inbox servers, as can git-{clone,fetch} on the HTTP(S) endpoint. -Since our marketing sucks, ease-of-installation is an important goal +Since our marketing sucks, ease of installation is an important goal for this project and we only depend on distro-provided packages. As of 2024, public-inbox is packaged by several OS distributions, diff --git a/examples/public-inbox-netd@.service b/examples/public-inbox-netd@.service index 2330bd5952fe..83d2e995c0f6 100644 --- a/examples/public-inbox-netd@.service +++ b/examples/public-inbox-netd@.service @@ -13,7 +13,7 @@ After = public-inbox-netd.socket [Service] # An LD_PRELOAD for libjemalloc can be added here. It currently seems -# more resistant to fragmentation to glibc in long-lived daemons. +# more resistant to fragmentation in long-lived daemons than glibc. Environment = PI_CONFIG=/home/pi/.public-inbox/config \ PATH=/usr/local/bin:/usr/bin:/bin \ TZ=UTC \ base-commit: 5e8068b28aa01befa9c6fa7368db956148816189 -- 2.44.0
The difference between the "numerous optional modules" section (containing only two modules) and the "everything else optional" section was unclear (to me, at least). Just put both under a single heading. --- INSTALL | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/INSTALL b/INSTALL index c04831c2fb5b..9672ba8cf6fa 100644 --- a/INSTALL +++ b/INSTALL @@ -58,7 +58,8 @@ Where "deb" indicates package names for Debian-derived distributions, "pkgin" for NetBSD, "apk" for Alpine Linux and "rpm" is for RPM-based distributions (only known to work on Fedora). -Numerous optional modules are likely to be useful as well: +Numerous optional modules might be useful as well, depending +on your use case and preferences: - DBD::SQLite deb: libdbd-sqlite3-perl pkg: p5-DBD-SQLite @@ -71,8 +72,6 @@ Numerous optional modules are likely to be useful as well: rpm: perl-Search-Xapian (required for lei; HTTP and IMAP search) -Every effort has been to make everything else optional: - - Plack deb: libplack-perl pkg: p5-Plack rpm: perl-Plack, perl-Plack-Test, -- 2.44.0
Abandoning this idea for now... jemalloc via LD_PRELOAD seems be working out to deal with fragmentation. I hope to be able to steal jemalloc ideas for glibc malloc to give a better out-of-the-box experience on GNU/Linux systems.
please keep meta@public-inbox.org in the Cc: Gonsolo <gonsolo@gmail.com> wrote: > > Which version of public-inbox is this? It looks like 1.9 based > > on the line number[1]. > > Package from Ubuntu/Debian. > > lei 1.9.0-1 (Ubuntu) <snip> > 936c275178dfc6908577487ce97d3a83c58c5449 PublicInbox/LeiSearch.pm OK. > > Any info you can share about the queries you use? (https, local > > public-inbox clones). > > lei edit-search: <snip> > [lei "q"] > include = https://lore.kernel.org/all/ > external = 1 > local = 1 > remote = 1 > threads = 1 OK, yeah. I seem to recall problems with http(s) externals being racy and made more reliable with the use of OnDestroy callbacks in public-inbox.git > > I've seen it a few times in the past, but IIRC couldn't reliably > > reproduce it and haven't seen it in a while. I'm always running > > latest <https://80x24.org/public-inbox.git>, though, and that > > has numerous reliability improvements over 1.9. > > Ok. Maybe I'm going to ping the Debian maintainer. No, please don't ask Debian maintainers to package unreleased versions. The non-lei feature: codesearch, is not ready to be supported in a 2.0 release. The only good news is 2.0 will probably be the last release involving large data model additions/changes.
INSTALL now covers more of lei since I'm less uncomfortable about it for 2.0 and points users towards the install/ helpers if installing from source. --- Documentation/RelNotes/v2.0.0.wip | 46 ++++++++++++++++-- Documentation/marketing.txt | 13 +++++- INSTALL | 77 +++++++++++++++++++------------ install/README | 6 ++- 4 files changed, 107 insertions(+), 35 deletions(-) diff --git a/Documentation/RelNotes/v2.0.0.wip b/Documentation/RelNotes/v2.0.0.wip index c473e8d7..53ef5fe5 100644 --- a/Documentation/RelNotes/v2.0.0.wip +++ b/Documentation/RelNotes/v2.0.0.wip @@ -6,7 +6,8 @@ Content-Disposition: inline This release includes several new features and fixes; mostly around improved integration between inboxes and coderepos for -solver. Portability and reliability is also improved. +solver. Portability and reliability is also improved, especially +in the internal process management of lei. public-inbox-cindex is a new command to index coderepos for WWW search and perform automatic associations between @@ -39,13 +40,22 @@ Compatibility: entries if `newsgroup' isn't specified) will also generate warnings since they break -extindex and the new -cindex (coderepo index). +New users + hackers: + + The install/ directory includes tools to automate installation and + removal of dependencies for stripped down or full setups. See + install/README for more details + treewide * support raw UTF-8 headers from SMTPUTF8 hosts * standardize on `#' prefix for stderr diagnostics (previously `I:') - * SHA-256 coderepos are fully-supported (inboxes not yet) + * SHA-256 coderepos are fully-supported (but not inboxes, yet) + + * jemalloc (tested as an LD_PRELOAD) is recommended to reduce fragmentation + in long-running daemon processes serving unpredictable traffic PublicInbox::WWW @@ -71,12 +81,18 @@ PublicInbox::WWW * add topics_(new|active).(html|atom) endpoints + * linkify peer public-inbox addresses in To/Cc headers + +public-inbox-watch: + + * watching MH folders is now supported + lei * use http.proxy / http.<remote>.proxy from system-wide git-config if unconfigured for lei - * improve IMAP error reporting + * improve IMAP and NNTP error reporting * reduce default IMAP connections to avoid overloading servers @@ -94,10 +110,16 @@ lei * improved bash completion for labels (see contrib/completion) + * support for reading (but not writing) MH folders + + * `lei index' accepts `+L:$LABEL' like `lei import' does + solver (used by lei (rediff|blob), and PublicInbox::WWW) * handle copies in patches properly + * no longer redundantly parallelized within each WWW process + portability * SIGWINCH is handled properly on less common architectures and OSes @@ -112,6 +134,12 @@ portability * support Alpine Linux, Dragonfly, NetBSD and OpenBSD. This resulted not only in bugfixes to our code, but also to Dragonfly and OpenBSD. + * Inline::C||Socket::MsgHdr no longer required for SCM_RIGHTS + with sendmsg/recvmsg on supported *BSDs. + + * inotify support no longer requires Linux::Inotify2 XS package + for most architectures + public-inbox-pop3d * support `limit=NUM' and `initial_limit=NUM' query parameters @@ -144,9 +172,19 @@ Search improvements (lei and PublicInbox::WWW) * quoted text inside base-85 binary patches is no longer indexed + * `public-inbox-cindex --join' prefers using Xapian's C++ API + directly to avoid Perl method dispatch overhead to get usable + performance assocating ~300 inboxes with over 1K coderepos + (and vice-versa). Users needing this performance will need + a C++ compiler, pkg-config, and the Xapian development files + (see INSTALL). + + This C++ helper will be used more heavily in the future + to enable query parser customizations and other functionality + unavailable from the Xapian SWIG or XS bindings. Thanks to all the bug reporters and users who made this release -possible. +possible, and thanks for bearing with my anxiety over making releases. Please report bugs via plain-text mail to: meta@public-inbox.org diff --git a/Documentation/marketing.txt b/Documentation/marketing.txt index 385e5172..8e4aa3b5 100644 --- a/Documentation/marketing.txt +++ b/Documentation/marketing.txt @@ -3,7 +3,9 @@ marketing guide for public-inbox TL; DR: Don't market this. If you must: don't be pushy and annoying about it. Slow down. -Please no superlatives, hype or BS. +Please no superlatives, hype or BS. Please keep all marketing +materials text-only to be accessible to those on slow networks +and ancient hardware. It's online and public, so it already markets itself. Being informative is not a bad thing, being insistent is. @@ -25,3 +27,12 @@ than the adoption of any software. Every time somebody recognizes and rejects various forms of lock-in and centralization is already a victory for us. + +Please keep in mind: + +* Perl 5 is not a well-liked language +* AGPL is not a well-liked license +* maintainer is a shy introvert + +Be sure to mention these things in any marketing materials +to avoid wasting time of people who hate Perl and/or AGPL. diff --git a/INSTALL b/INSTALL index c5d69d1b..b1d7fd1b 100644 --- a/INSTALL +++ b/INSTALL @@ -1,11 +1,15 @@ -public-inbox (server-side) installation ---------------------------------------- +public-inbox / lei installation +------------------------------- -This is for folks who want to set up their own public-inbox instance. -Clients should use normal git-clone/git-fetch, IMAP or NNTP clients -if they want to import mail into their personal inboxes. +This is for people who want to run public-inbox on their server or +lei as a command-line tool. Any HTTP, IMAP, NNTP, or POP3 client can +access public-inbox servers, as can git-{clone,fetch} on the HTTP(S) +endpoint. -As of 2023, public-inbox is packaged by several OS distributions, +Since our marketing sucks, ease-of-installation is an important goal +for this project and we only depend on distro-provided packages. + +As of 2024, public-inbox is packaged by several OS distributions, listed in alphabetical order: Debian, GNU Guix, NixOS, and Void Linux. public-inbox is developed on Debian GNU/Linux systems and will @@ -14,12 +18,18 @@ the "oldstable" distribution, currently Debian 11.x ("bullseye"), but older versions of Debian remain supported (as are newer ones). Most packages are available in other GNU/Linux distributions, -FreeBSD, NetBSD, and OpenBSD. CentOS 7.x users will likely want -newer git and Xapian for better performance and v2 inbox support: +Alpine Linux, FreeBSD, NetBSD, OpenBSD, and DragonflyBSD. +CentOS 7.x users will likely want newer git and Xapian for +better performance and v2 inbox support: https://public-inbox.org/meta/20210421151308.yz5hzkgm75klunpe@nitro.local/ -TODO: this still needs to be documented better, -also see the scripts/ and sa_config/ directories in the source tree +As of 2.0, install/deps.perl makes it easier to install target +dependencies needed for certain features. See install/README in +the source tree for more info. + +Also see sa_config/ directories in the source tree for recommended +SpamAssassin configuration examples if using public-inbox-mda or +public-inbox-watch. Requirements ------------ @@ -43,22 +53,10 @@ Beyond that, there is one non-standard Perl package required: rpm: perl-URI (for HTML/Atom generation) -Plack and Date::Parse are optional as of public-inbox v1.3.0, -but required for older releases: - -* Plack deb: libplack-perl - pkg: p5-Plack - rpm: perl-Plack, perl-Plack-Test, - (for HTML/Atom generation) - -- Date::Parse deb: libtimedate-perl - pkg: p5-TimeDate - rpm: perl-TimeDate - (for broken, mostly historical emails) - Where "deb" indicates package names for Debian-derived distributions, -"pkg" is for the FreeBSD package (and some other common BSDs, too), and -"rpm" is for RPM-based distributions (only known to work on Fedora). +"pkg" is for the FreeBSD package (and some other common BSDs, too), +"pkgin" for NetBSD, "apk" for Alpine Linux and "rpm" is for RPM-based +distributions (only known to work on Fedora). Numerous optional modules are likely to be useful as well: @@ -71,7 +69,14 @@ Numerous optional modules are likely to be useful as well: pkg: p5-Xapian (FreeBSD, NetBSD) xapian-bindings-perl (OpenBSD) rpm: perl-Search-Xapian - (lei; HTTP and IMAP search) + (required for lei; HTTP and IMAP search) + +Every effort has been to make everything else optional: + +- Plack deb: libplack-perl + pkg: p5-Plack + rpm: perl-Plack, perl-Plack-Test, + (for WWW interface, public-inbox-httpd(1)) - Inline::C deb: libinline-c-perl pkg: p5-Inline-C @@ -88,7 +93,7 @@ Numerous optional modules are likely to be useful as well: - Parse::RecDescent deb: libparse-recdescent-perl pkg: p5-Parse-RecDescent rpm: perl-ParseRecDescent - (only for public-inbox-imapd(1)) + (for public-inbox-imapd(1)) - Mail::IMAPClient deb: libmail-imapclient-perl pkg: p5-Mail-IMAPClient @@ -113,10 +118,19 @@ Numerous optional modules are likely to be useful as well: * xapian-tools deb: xapian-tools pkg: xapian-core + pkgin: xapian rpm: xapian-core (for public-inbox-compact(1) and public-inbox-cindex(1)) +* Xapian development files deb: libxapian-dev + pkg: xapian-core + pkgin: xapian + apk: xapian-core-dev + rpm: xapian-core-devel / xapian14-core-libs + (for public-inbox-cindex(1) and future + performance enhancements) + * curl (tool) deb, pkg, rpm: curl (for lei HTTP(S) externals with curl and public-inbox-clone(1)) @@ -124,11 +138,11 @@ Numerous optional modules are likely to be useful as well: - Linux::Inotify2 deb: liblinux-inotify2-perl rpm: perl-Linux-Inotify2 (for lei, public-inbox-watch and -imapd - on Linux) + on Linux; not required as of 2.0)) - IO::KQueue pkg: p5-IO-KQueue (for lei, public-inbox-watch and -imapd - on *BSDs) + on *BSDs only) - Net::Server deb: libnet-server-perl pkg: p5-Net-Server @@ -159,6 +173,11 @@ Uncommonly needed modules (see HACKING for development-only modules): pkg: p5-Crypt-CBC (for PublicInbox::Unsubscribe (rarely used)) +- Date::Parse deb: libtimedate-perl + pkg: p5-TimeDate + rpm: perl-TimeDate + (for broken, mostly historical emails) + standard MakeMaker installation (Perl) -------------------------------------- diff --git a/install/README b/install/README index dd652552..2cdac4d2 100644 --- a/install/README +++ b/install/README @@ -1,7 +1,11 @@ tooling for mass package installation ------------------------------------- -TL;DR: sudo ./install/deps.perl all +TL;DR (as root or with sudo): + + ./install/deps.perl all # install everything + ./install/deps.perl lei # only what's needed for lei + ./install/deps.perl www-search # for hosting WWW search Files in this directory are designed for:
Gonsolo <gonsolo@gmail.com> wrote: > Hi! > > Since a few days I'm getting the following error when running "lei up --all": > > 10770 lei2mail 1 (nshard=3) 8b214638a3a05e3d9f2345a632a5eed0de7f9ab6: > Exception: Document 22720 not found at > /usr/share/perl5/PublicInbox/LeiSearch.pm line 68. > > Is there anything I can do? Which version of public-inbox is this? It looks like 1.9 based on the line number[1]. Any info you can share about the queries you use? (https, local public-inbox clones). I've seen it a few times in the past, but IIRC couldn't reliably reproduce it and haven't seen it in a while. I'm always running latest <https://80x24.org/public-inbox.git>, though, and that has numerous reliability improvements over 1.9. In any case, there's no mail data loss from xsmsg_vmd, only metadata (missed flags) and I think it could've been a data synchronization problem that was fixed in public-inbox.git. [1] Running "lei sucks" should show all relevant version info. The blob OID for LeiSearch.pm would certainly help confirm that.
Hi! Since a few days I'm getting the following error when running "lei up --all": 10770 lei2mail 1 (nshard=3) 8b214638a3a05e3d9f2345a632a5eed0de7f9ab6: Exception: Document 22720 not found at /usr/share/perl5/PublicInbox/LeiSearch.pm line 68. Is there anything I can do? Best regards -- g
Felix Lechner <felix.lechner@lease-up.com> wrote: > Hi, > > What's a good place to ask questions about running public-inbox-mda, > please? This is the only place :> > I can't get public-inbox-mda to import on-disk messages. They end up in > the emergency Maildir. My configuration and a sample message are below. <snip> > [publicinbox "help"] > address = help@patchwise.org You probably need to set ORIGINAL_RECIPIENT=help@patchwise.org in your environment. (postfix and presumably other MTAs do this when invoking public-inbox-mda) > Also, why is it a fault when the "inbox address [is] specified in To: or > Cc: header"? Isn't that how messages appear on a mailing list? Thanks! Erm, that should be "not" specified, I think.... In other words, Bcc-ing a public mailing list is often spammy or deceptive behavior. Patch coming later. If you're running public-inbox.git, `lei import' should be faster for importing on-disk mbox{rd,cl,cl2,o}, maildir, MH. And there'll probably be a `public-inbox-ctl' tool to inject messages from HTTP(S) ActivityPub requests. I'm really behind on making releases, unfortunately; but all the email-only stuff should be OK in public-inbox.git; and I've been bogged down by offline stuff this year :<
Hi, What's a good place to ask questions about running public-inbox-mda, please? I can't get public-inbox-mda to import on-disk messages. They end up in the emergency Maildir. My configuration and a sample message are below. Also, why is it a fault when the "inbox address [is] specified in To: or Cc: header"? Isn't that how messages appear on a mailing list? Thanks! Kind regards Felix Lechner * * * [publicinboxmda] spamcheck = none [publicinbox "help"] inboxdir = /srv/patchwise/inbox/help.git address = help@patchwise.org url = https://patchwise.org/help newsgroup = inbox.comp.bugs.patchwise.help listid = help.patchwise.org * * * Return-Path: <felix.lechner@lease-up.com> Delivered-To: help@patchwise.org DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; s=2017; bh=/ksuGrWv8XZH4Xz xkdQogzQXtVAiarS3rMKbtWQsMKo=; h=date:subject:cc:to:from; d=lease-up.com; b=PZqkCHXfAvVGgjMQ0s2KaJaLL2/IZDzcNOVaJonYjRLTO9WAu+jp /K3Mp6Lu+92wlUlxHsV9FqUejBkRNwq/9BZomLRZ3Ds7M2poYaJqNZSbqsz3CHtnyRB6ES 04fHgPjOblq/VT3XEe3zJYMVAyRSd7SmiiCU1cEPnMrha1avE= Received: by sail-ipv4.us-core.com (OpenSMTPD) with ESMTPSA id 79007b4b (TLSv1.3:TLS_CHACHA20_POLY1305_SHA256:256:NO) for <help@patchwise.org>; Mon, 11 Mar 2024 03:00:56 +0000 (UTC) From: Felix Lechner <felix.lechner@lease-up.com> To: help@patchwise.org Cc: Subject: Welcome to a patch-wise bug tracker Date: Sun, 10 Mar 2024 20:00:56 -0700 Message-ID: <87a5n5wjyv.fsf@lease-up.com> MIME-Version: 1.0 Content-Type: text/plain Hi, This website hopes to unify some email-based practices for software contributions using patches. The service is currently vaporware. We hope to combine the best features of Debbugs [1] Mumi [2] Public Inbox [3] and others, while adding novel ideas of our own. Please send patches to this account for now, i.e. help@patchwise.org. Kind regards Felix [1] https://debbugs.gnu.org/ [2] https://issues.guix.gnu.org/ [3] https://public-inbox.org/README
While PublicInbox::Config is responsible for some instances of setting $git->{nick}, more PublicInbox::Git objects may be created from loading the cindex and we should do our best to reuse that memory, too. Followup-to: 84ed7ec1c887 (dedupe inbox names, coderepo nicks + git dirs, 2024-03-04) --- lib/PublicInbox/CodeSearch.pm | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/PublicInbox/CodeSearch.pm b/lib/PublicInbox/CodeSearch.pm index 48033bb5..e5fa4480 100644 --- a/lib/PublicInbox/CodeSearch.pm +++ b/lib/PublicInbox/CodeSearch.pm @@ -283,7 +283,8 @@ EOM $nick =~ s!$lre!$nick_pfx!s or next; $dir2cr{$p} = $coderepos->{$nick} //= do { my $git = PublicInbox::Git->new($p); - $git->{nick} = $nick; # for git->pub_urls + my %dedupe = ($nick => undef); + ($git->{nick}) = keys %dedupe; # for git->pub_urls $git; }; }
I may be mistaken, but I suspect the reason jemalloc handles long-lived processes better than glibc is due to granularity reduction being scaled to larger size classes. This can waste 20% of an individual allocation, but increases the likelyhood of reuse (without splitting/consolidating into other sizes). In other words, glibc seems to try too hard to make the best fit for initial allocations. This ends up being suboptimal over time as those allocations are freed and similar (but not identical) allocations come in. jemalloc sacrifices the best initial fit for better fits over a long process lifetime. --- Documentation/public-inbox-tuning.pod | 5 +++++ examples/public-inbox-netd@.service | 2 ++ 2 files changed, 7 insertions(+) diff --git a/Documentation/public-inbox-tuning.pod b/Documentation/public-inbox-tuning.pod index 38810ce6..73246144 100644 --- a/Documentation/public-inbox-tuning.pod +++ b/Documentation/public-inbox-tuning.pod @@ -163,6 +163,11 @@ Transport Layer Security (IMAPS, NNTPS, or via STARTTLS) significantly increases memory use of client sockets, be sure to account for that in capacity planning. +Bursts of small object allocations late in process life contribute to +fragmentation of the heap due to arenas (slabs) used internally by Perl. +jemalloc (tested as an LD_PRELOAD on GNU/Linux) appears to reduce +overall fragmentation compared to glibc malloc in long-lived processes. + =head2 Other OS tuning knobs Linux users: the C<sys.vm.max_map_count> sysctl may need to be increased if diff --git a/examples/public-inbox-netd@.service b/examples/public-inbox-netd@.service index de5feea6..2330bd59 100644 --- a/examples/public-inbox-netd@.service +++ b/examples/public-inbox-netd@.service @@ -12,6 +12,8 @@ Wants = public-inbox-netd.socket After = public-inbox-netd.socket [Service] +# An LD_PRELOAD for libjemalloc can be added here. It currently seems +# more resistant to fragmentation to glibc in long-lived daemons. Environment = PI_CONFIG=/home/pi/.public-inbox/config \ PATH=/usr/local/bin:/usr/bin:/bin \ TZ=UTC \
With my current mirror of lore + gko, this saves over 300K allocations and brings the allocation count in this area down to under 5K. The reduction in AV refs saves around 45MB RAM according to measurements done live via Devel::Mwrap. --- lib/PublicInbox/CodeSearch.pm | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/lib/PublicInbox/CodeSearch.pm b/lib/PublicInbox/CodeSearch.pm index 1f95a726..48033bb5 100644 --- a/lib/PublicInbox/CodeSearch.pm +++ b/lib/PublicInbox/CodeSearch.pm @@ -292,6 +292,7 @@ W: cindex.$name.topdir=$self->{topdir} has no usable join data for $cfg_f EOM my ($ekeys, $roots, $ibx2root) = @$jd{qw(ekeys roots ibx2root)}; my $roots2paths = roots2paths($self); + my %dedupe; # 50x alloc reduction w/ lore + gko mirror (Mar 2024) for my $root_offs (@$ibx2root) { my $ekey = shift(@$ekeys) // die 'BUG: {ekeys} empty'; scalar(@$root_offs) or next; @@ -320,9 +321,15 @@ EOM if (my $git = $dir2cr{$_}) { $ibx_p2g{$_} = $git; $ibx2self = 1; - $ibx->{-hide_www} or - push @{$git->{ibx_score}}, + if (!$ibx->{-hide_www}) { + # don't stringify $nr directly + # to avoid long-lived PV + my $k = ($nr + 0)."\0". + ($ibx + 0); + my $s = $dedupe{$k} //= [ $nr, $ibx->{name} ]; + push @{$git->{ibx_score}}, $s; + } push @$gits, $git; } else { warn <<EOM;
Wrap the entire solver command chain with a dedicated limiter. The normal limiter is designed for longer-lived commands or ones which serve a single HTTP request (e.g. git-http-backend or cgit) and not effective for short memory + CPU intensive commands used for solver. Each overall solver request is both memory + CPU intensive: it spawns several short-lived git processes(*) in addition to a longer-lived `git cat-file --batch' process. Thus running parallel solvers from a single -netd/-httpd worker (which have their own parallelization) results in excessive parallelism that is both memory and CPU-bound (not network-bound) and cascade into slowdowns for handling simpler memory/CPU-bound requests. Parallel solvers were also responsible for the increased lifetime and frequency of zombies since the event loop was too saturated to reap them. We'll also return 503 on excessive solver queueing, since these require an FD for the client HTTP(S) socket to be held onto. (*) git (update-index|apply|ls-files) are all run by solver and short-lived --- lib/PublicInbox/SolverGit.pm | 15 ++++++----- lib/PublicInbox/ViewVCS.pm | 48 +++++++++++++++++++++++++++++------- 2 files changed, 48 insertions(+), 15 deletions(-) diff --git a/lib/PublicInbox/SolverGit.pm b/lib/PublicInbox/SolverGit.pm index 4e79f750..296e7d17 100644 --- a/lib/PublicInbox/SolverGit.pm +++ b/lib/PublicInbox/SolverGit.pm @@ -256,6 +256,12 @@ sub update_index_result ($$) { next_step($self); # onto do_git_apply } +sub qsp_qx ($$$) { + my ($self, $qsp, $cb) = @_; + $qsp->{qsp_err} = \($self->{-qsp_err} = ''); + $qsp->psgi_qx($self->{psgi_env}, $self->{limiter}, $cb, $self); +} + sub prepare_index ($) { my ($self) = @_; my $patches = $self->{patches}; @@ -284,9 +290,8 @@ sub prepare_index ($) { my $cmd = [ qw(git update-index -z --index-info) ]; my $qsp = PublicInbox::Qspawn->new($cmd, $self->{git_env}, $rdr); $path_a = git_quote($path_a); - $qsp->{qsp_err} = \($self->{-qsp_err} = ''); $self->{-msg} = "index prepared:\n$mode_a $oid_full\t$path_a"; - $qsp->psgi_qx($self->{psgi_env}, undef, \&update_index_result, $self); + qsp_qx $self, $qsp, \&update_index_result; } # pure Perl "git init" @@ -465,8 +470,7 @@ sub apply_result ($$) { # qx_cb my @cmd = qw(git ls-files -s -z); my $qsp = PublicInbox::Qspawn->new(\@cmd, $self->{git_env}); $self->{-cur_di} = $di; - $qsp->{qsp_err} = \($self->{-qsp_err} = ''); - $qsp->psgi_qx($self->{psgi_env}, undef, \&ls_files_result, $self); + qsp_qx $self, $qsp, \&ls_files_result; } sub do_git_apply ($) { @@ -495,8 +499,7 @@ sub do_git_apply ($) { my $opt = { 2 => 1, -C => _tmp($self)->dirname, quiet => 1 }; my $qsp = PublicInbox::Qspawn->new(\@cmd, $self->{git_env}, $opt); $self->{-cur_di} = $di; - $qsp->{qsp_err} = \($self->{-qsp_err} = ''); - $qsp->psgi_qx($self->{psgi_env}, undef, \&apply_result, $self); + qsp_qx $self, $qsp, \&apply_result; } sub di_url ($$) { diff --git a/lib/PublicInbox/ViewVCS.pm b/lib/PublicInbox/ViewVCS.pm index 61329db6..790b9a2c 100644 --- a/lib/PublicInbox/ViewVCS.pm +++ b/lib/PublicInbox/ViewVCS.pm @@ -49,6 +49,10 @@ my %GIT_MODE = ( '160000' => 'g', # commit (gitlink) ); +# TODO: not fork safe, but we don't fork w/o exec in PublicInbox::WWW +my (@solver_q, $solver_lim); +my $solver_nr = 0; + sub html_page ($$;@) { my ($ctx, $code) = @_[0, 1]; my $wcb = delete $ctx->{-wcb}; @@ -614,26 +618,52 @@ sub show_blob { # git->cat_async callback '</code></pre></td></tr></table>'.dbg_log($ctx), @def); } -# GET /$INBOX/$GIT_OBJECT_ID/s/ -# GET /$INBOX/$GIT_OBJECT_ID/s/$FILENAME -sub show ($$;$) { - my ($ctx, $oid_b, $fn) = @_; - my $hints = $ctx->{hints} = {}; +sub start_solver ($) { + my ($ctx) = @_; while (my ($from, $to) = each %QP_MAP) { my $v = $ctx->{qp}->{$from} // next; - $hints->{$to} = $v if $v ne ''; + $ctx->{hints}->{$to} = $v if $v ne ''; } - $ctx->{fn} = $fn; - $ctx->{-tmp} = File::Temp->newdir("solver.$oid_b-XXXX", TMPDIR => 1); + $ctx->{-next_solver} = PublicInbox::OnDestroy->new($$, \&next_solver); + ++$solver_nr; + $ctx->{-tmp} = File::Temp->newdir("solver.$ctx->{oid_b}-XXXX", + TMPDIR => 1); $ctx->{lh} or open $ctx->{lh}, '+>>', "$ctx->{-tmp}/solve.log"; my $solver = PublicInbox::SolverGit->new($ctx->{ibx}, \&solve_result, $ctx); + $solver->{limiter} = $solver_lim; $solver->{gits} //= [ $ctx->{git} ]; $solver->{tmp} = $ctx->{-tmp}; # share tmpdir # PSGI server will call this immediately and give us a callback (-wcb) + $solver->solve(@$ctx{qw(env lh oid_b hints)}); +} + +# run the next solver job when done and DESTROY-ed +sub next_solver { + --$solver_nr; + # XXX FIXME: client may've disconnected if it waited a long while + start_solver(shift(@solver_q) // return); +} + +sub may_start_solver ($) { + my ($ctx) = @_; + $solver_lim //= $ctx->{www}->{pi_cfg}->limiter('codeblob'); + if ($solver_nr >= $solver_lim->{max}) { + @solver_q > 128 ? html_page($ctx, 503, 'too busy') + : push(@solver_q, $ctx); + } else { + start_solver($ctx); + } +} + +# GET /$INBOX/$GIT_OBJECT_ID/s/ +# GET /$INBOX/$GIT_OBJECT_ID/s/$FILENAME +sub show ($$;$) { + my ($ctx, $oid_b, $fn) = @_; + @$ctx{qw(oid_b fn)} = ($oid_b, $fn); sub { $ctx->{-wcb} = $_[0]; # HTTP write callback - $solver->solve($ctx->{env}, $ctx->{lh}, $oid_b, $hints); + may_start_solver $ctx; }; }
1/4 gets rid of some overload caused by parallel solver invocations under heavy (likely bot) traffic crawling yhbt.net/lore with many coderepos enabled and joined to inboxes. 2/4 is a large reduction in allocations from loading coderepo <=> inbox associations, 4/4 is smaller. I found 2/4 with Devel::Mwrap and noticed 4/4 while working on 2/4. 3/4 is just a doc update but I've been successfully using jemalloc on my lore+gko mirror for a week or two, now (and I plan to experiment with making glibc||dlmalloc more resistant to fragmentation) Eric Wong (4): www: use a dedicated limiter for blob solver codesearch: deduplicate {ibx_score} name pairs doc: tuning: note reduced fragmentation w/ jemalloc codesearch: deduplicate $git->{nick} field Documentation/public-inbox-tuning.pod | 5 +++ examples/public-inbox-netd@.service | 2 ++ lib/PublicInbox/CodeSearch.pm | 14 ++++++-- lib/PublicInbox/SolverGit.pm | 15 +++++---- lib/PublicInbox/ViewVCS.pm | 48 ++++++++++++++++++++++----- 5 files changed, 66 insertions(+), 18 deletions(-)
Fortunately, this only affects `--multi-accept=' users, with `--multi-accept=-1' users getting infinite loops. I noticed this when EMFILE was reached on my setup, but any error should cause us to give up accept(2) (at least temporarily) and allow work for other items in the event loop to be processed. --- lib/PublicInbox/Listener.pm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/PublicInbox/Listener.pm b/lib/PublicInbox/Listener.pm index 4669cf04..c83901b2 100644 --- a/lib/PublicInbox/Listener.pm +++ b/lib/PublicInbox/Listener.pm @@ -41,9 +41,9 @@ sub event_step { # ECONNABORTED is common with bad connections return; } elsif (my $sym = $ERR_WARN{int($!)}) { - warn "W: accept(): $! ($sym)\n"; + return warn "W: accept(): $! ($sym)\n"; } else { - warn "BUG?: accept(): $!\n"; + return warn "BUG?: accept(): $!\n"; } } while ($n--); }
Eric Wong <e@80x24.org> wrote: > Will try to fix ASAP but offline problems persist :< Fortunately it turned out to be a simple fix :x -------8<------- Subject: [PATCH] import: fix handling of init.defaultBranch We must chomp the newline in the branch name if it's set. Reported-by: Rob Herring <robh@kernel.org> Link: https://public-inbox.org/meta/CAL_JsqK7P4gjLPyvzxNEcYmxT4j6Ah5f3Pz1RqDHxmysTg3aEg@mail.gmail.com/ Fixes: 73830410e4336b77 (treewide: use run_qx where appropriate, 2023-10-27) --- lib/PublicInbox/Import.pm | 1 + t/clone-coderepo.t | 8 +++++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/lib/PublicInbox/Import.pm b/lib/PublicInbox/Import.pm index a951874b..ed34d548 100644 --- a/lib/PublicInbox/Import.pm +++ b/lib/PublicInbox/Import.pm @@ -26,6 +26,7 @@ sub default_branch () { state $default_branch = do { my $h = run_qx([qw(git config --global init.defaultBranch)], { GIT_CONFIG => undef }); + chomp $h; $h eq '' ? 'refs/heads/master' : "refs/heads/$h"; } } diff --git a/t/clone-coderepo.t b/t/clone-coderepo.t index c0951941..c6180fc4 100644 --- a/t/clone-coderepo.t +++ b/t/clone-coderepo.t @@ -7,6 +7,7 @@ use PublicInbox::Import; use File::Temp; use File::Path qw(remove_tree); use PublicInbox::SHA qw(sha1_hex); +use PublicInbox::IO; require_mods(qw(json Plack::Builder HTTP::Date HTTP::Status)); require_git_http_backend; require_git '1.8.5'; @@ -38,9 +39,10 @@ my $t0 = time - 1; my $m; # manifest hashref { - my $rdr = {}; - my $fi_data = './t/git.fast-import-data'; - open $rdr->{0}, '<', $fi_data or xbail "open($fi_data): $!"; + my $fi_data = PublicInbox::IO::try_cat './t/git.fast-import-data'; + my $db = PublicInbox::Import::default_branch; + $fi_data =~ s!\brefs/heads/master\b!$db!gs; + my $rdr = { 0 => \$fi_data }; my @git = ('git', "--git-dir=$pa"); xsys_e([@git, qw(fast-import --quiet)], undef, $rdr); xsys_e([qw(/bin/cp -Rp a.git b.git)], undef, { -C => "$tmpdir/src" });
Rob Herring <robh@kernel.org> wrote:
> Most Recent Commands Before Crash
> ---------------------------------
> blob
> mark :1
> data 12367
> get-mark :1
> reset refs/heads/main
Ah, it looks like init.defaultBranch != master is completely
broken :x You should be able to workaround the problem by
leaving defaultBranch unset for now.
Will try to fix ASAP but offline problems persist :<
This allows accurate reporting of the error location and can be made to dump a Perl backtrace via PERL5OPT='-MCarp=verbose'. Noticed while tracking down fast-import failures. Link: https://public-inbox.org/meta/CAL_JsqK7P4gjLPyvzxNEcYmxT4j6Ah5f3Pz1RqDHxmysTg3aEg@mail.gmail.com/ --- lib/PublicInbox/Import.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/PublicInbox/Import.pm b/lib/PublicInbox/Import.pm index 51ddfa7f..a951874b 100644 --- a/lib/PublicInbox/Import.pm +++ b/lib/PublicInbox/Import.pm @@ -85,7 +85,7 @@ sub gfi_start { $self->{io}; } -sub wfail () { die "write to fast-import failed: $!" } +sub wfail () { croak "write to fast-import failed: $!" } sub now_raw () { time . ' +0000' }
Noticed while tracking down fast-import crash bug report. Link: https://public-inbox.org/meta/CAL_JsqK7P4gjLPyvzxNEcYmxT4j6Ah5f3Pz1RqDHxmysTg3aEg@mail.gmail.com/ --- lib/PublicInbox/LeiSearch.pm | 2 ++ lib/PublicInbox/LeiToMail.pm | 1 + lib/PublicInbox/OverIdx.pm | 6 +++++- 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/PublicInbox/LeiSearch.pm b/lib/PublicInbox/LeiSearch.pm index 29e3213f..684668c5 100644 --- a/lib/PublicInbox/LeiSearch.pm +++ b/lib/PublicInbox/LeiSearch.pm @@ -103,6 +103,8 @@ sub xoids_for { for my $o (@overs) { my ($id, $prev); while (my $cur = $o->next_by_mid($mid, \$id, \$prev)) { + # {bytes} may be '' from old bug + $cur->{bytes} = 1 if $cur->{bytes} eq ''; next if $cur->{bytes} == 0 || $xoids->{$cur->{blob}}; $git->cat_async($cur->{blob}, \&_cmp_1st, diff --git a/lib/PublicInbox/LeiToMail.pm b/lib/PublicInbox/LeiToMail.pm index a816df6c..dfae29e9 100644 --- a/lib/PublicInbox/LeiToMail.pm +++ b/lib/PublicInbox/LeiToMail.pm @@ -149,6 +149,7 @@ sub git_to_mail { # git->cat_async callback "W: $oid is $type (!= blob)"); $size or return $self->{lei}->child_error(0,"E: $oid is empty"); $smsg->{blob} eq $oid or die "BUG: expected=$smsg->{blob}"; + $smsg->{bytes} ||= $size; $self->{wcb}->($bref, $smsg); }; $self->{lei}->fail("$@ (oid=$oid)") if $@; diff --git a/lib/PublicInbox/OverIdx.pm b/lib/PublicInbox/OverIdx.pm index c9c25828..4f8533f7 100644 --- a/lib/PublicInbox/OverIdx.pm +++ b/lib/PublicInbox/OverIdx.pm @@ -17,6 +17,7 @@ use PublicInbox::MID qw/id_compress mids_for_index references/; use PublicInbox::Smsg qw(subject_normalized); use Compress::Zlib qw(compress); use Carp qw(croak); +use bytes (); # length sub dbh_new { my ($self) = @_; @@ -263,7 +264,10 @@ sub ddd_for ($) { sub add_overview { my ($self, $eml, $smsg) = @_; - $smsg->{lines} = $eml->body_raw =~ tr!\n!\n!; + my $raw = $eml->body_raw; + $smsg->{lines} = $raw =~ tr!\n!\n!; + $smsg->{bytes} //= bytes::length $raw; + undef $raw; my $mids = mids_for_index($eml); my $refs = $smsg->parse_references($eml, $mids); $mids->[0] //= do {
I'm still trying to track down the cause of fast-import failures[1], but this series presents some useful fixes regardless. Link: https://public-inbox.org/meta/CAL_JsqK7P4gjLPyvzxNEcYmxT4j6Ah5f3Pz1RqDHxmysTg3aEg@mail.gmail.com/ Eric Wong (2): lei: prevent empty {bytes} field in saved search import: croak (instead of die) on write failures lib/PublicInbox/Import.pm | 2 +- lib/PublicInbox/LeiSearch.pm | 2 ++ lib/PublicInbox/LeiToMail.pm | 1 + lib/PublicInbox/OverIdx.pm | 6 +++++- 4 files changed, 9 insertions(+), 2 deletions(-)