Skip to content

Send bundle chunks from the file, and test against several Chorus clients - #31

Merged
hahn-kev merged 3 commits into
masterfrom
claude/bundle-chunks-file-delivery-35ffe9
Oct 26, 2026
Merged

hahn-kev merged 3 commits into
masterfrom
claude/bundle-chunks-file-delivery-35ffe9

Conversation

@hahn-kev-bot

@hahn-kev-bot hahn-kev-bot commented Oct 23, 2026 •

Copy link
Copy Markdown
Collaborator

AI summary

Send bundle chunks from the file

pullBundleChunk used to read each chunk into a byte[] and write that array as the response. A slow client kept the whole chunk in server memory until it finished downloading.

Now the response carries a file region (path, offset, count), and RestDispatcher sends it with HttpResponse.SendFileAsync. That uses sendfile where the platform supports it, so the chunk never sits in managed memory.

  • HgResumeResponse gains BodyFile (a FileRegion record), used in place of Content.
  • HgResumeApi.GetChunkAsync is replaced by GetChunkRegion, which only works out the region (the smaller of chunkSize and the bytes past offset, or empty).
  • Headers, Content-Length and the wire format don't change. Content-Length is still set explicitly, which the Chorus client needs.

Test against several Chorus clients

The integration tests take -p:ChorusClient=pinned|latest|hg3, and CI runs each one as a matrix leg against the same image.

Client LibChorus Mercurial Why
pinned (default) 6.0.0-beta0064 6.5.1.43 Last release before the transport moved from HttpWebRequest to HttpClient (sillsdev/chorus#399). Also runs the HTTP-level tests.
latest newest on NuGet (*-*) newest Catches breakage from new Chorus releases.
hg3 6.0.0-beta0041 3.0.3.11 Old Mercurial 3 clients, as LexBox tested.
  • hg3 needs port 80. That Chorus drops the port from the repo URL (fixed in fix case where port number is lost using resumable chorus#343), so ServerFixture gains HGRESUME_HOST_PORT, and the hg3 leg publishes the server on port 80. Its Linux hg is a python2 script, so that leg installs Python 2.7 the same way LexBox does.
  • No mixed Mercurial files. Each client gets its own hg drop dir (obj/hg/<client>) and output dir (bin/<config>/<client>), so switching clients locally never mixes Mercurial files. The two .gitignore entries for the old drop location are gone.
  • CI layout. The workflow now builds the amd64 image once and passes it to the test legs as an artifact. The multi-arch build and push runs only after every leg passes.

LexBox's own hg 3 leg had silently been testing Mercurial 6 since it moved to central package management. That's fixed separately in sillsdev/languageforge-lexbox#2793.

Test plan

  • dotnet build passes
  • HgResume.Api.Tests pass (15/15)
  • Integration tests pass locally on pinned (52/52) and latest (52/52)
  • hg3 leg passes in CI (4/4; not run locally because port 80 is taken by a local kind cluster)
  • All three CI legs green (pinned 52/52, latest 4/4, hg3 4/4), and the multi-arch build and push ran

🤖 Generated with Claude Code

hahn-kev and others added 2 commits October 23, 2026 15:25
pullBundleChunk read each chunk into a byte array and then wrote that
array as the response, so a slow client pinned the whole chunk in server
memory for as long as its download took. Now the response carries the
file region (path, offset, count) and RestDispatcher sends it with
SendFileAsync, which uses sendfile where the platform has it and never
holds the chunk in managed memory. Headers, Content-Length and the wire
format are unchanged, so existing clients are unaffected; clients that
ask for the rest of the bundle in one request no longer cost the server
that much memory per download.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LLSihB4ffNi95ioJQEvsLr
The integration tests drove one hard-coded LibChorus. They now take
-p:ChorusClient=pinned|latest|hg3, and CI runs each one as a matrix leg
against the same image:

- pinned: LibChorus 6.0.0-beta0064 with Mercurial 6, the last release
  before the resumable transport moved from HttpWebRequest to HttpClient
  (sillsdev/chorus#399). The default, and the only leg that runs the
  HTTP-level tests too.
- latest: the newest LibChorus, Mercurial and SIL.Core on NuGet.
- hg3: LibChorus 6.0.0-beta0041 with Mercurial 3.0.3.11, as LexBox
  tested. That Chorus drops the port from the repo URL (fixed in
  sillsdev/chorus#343), so ServerFixture gains HGRESUME_HOST_PORT and
  this leg publishes the server on port 80. Its Linux hg needs python2.

Each client gets its own hg drop and output dir, so switching between
them locally never mixes Mercurial files. CI now builds the image once,
hands it to the test legs as an artifact, and pushes only after every
leg passes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@hahn-kev-bot hahn-kev-bot changed the title Send bundle chunks straight from the file instead of buffering them Send bundle chunks from the file, and test against several Chorus clients Oct 23, 2026
Chorus only looks for Mercurial/ in the test assembly's dir and the two
above it. On Linux the tests had been finding the hg drop in the project
dir, three levels above bin/Debug/net10.0. With the per-client output
dir and hg drop dir that no longer lines up, so copy Mercurial/ into the
output dir on Linux too, as on Windows.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@hahn-kev
hahn-kev requested a review from rmunn October 23, 2026 10:09
@hahn-kev
hahn-kev merged commit 361f50c into master Oct 26, 2026
5 checks passed
@hahn-kev
hahn-kev deleted the claude/bundle-chunks-file-delivery-35ffe9 branch October 26, 2026 04:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants