fix(server): a large text paste no longer kills the circuit #240
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "fix/hub-message-size"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Pasting a large text into any bound field — a scene line, the assistant composer, a description — killed the Blazor circuit: the framework ships each input event's full contents as one SignalR message, and the unconfigured
HubOptions.MaximumReceiveMessageSizedefault of 32 KB terminates the connection on anything bigger. Not truncation, not a validation error — the reconnect overlay, with the in-progress edit lost.Change
One config line in
Program.cs:MaximumReceiveMessageSize = 1 MB. That covers any realistic prose paste; binary payloads are unaffected (uploads already stream in chunks under the message cap, downloads are plain endpoints). No field-level caps added — scene text and descriptions are deliberately unbounded in the domain.Verification
HubMessageSizeTestspins the option through the real host (GatedAppFactory).Connection disconnected … closed with an error, and after reload the line still has its original 61 characters;🤖 Generated with Claude Code
Summary
Summary
Coverage
Kagura.BlazorAdapter - 88.5%
Kagura.Domain - 94.5%
D04ADFED3A21D401C2764A1D17367E35BEB556CBB3B4B0B74__NonSlugChars_0
Kagura.Infrastructure - 97.6%
n
n
on
ng
C689CA5BBE6D1849B2CA79581BBB07D40636D85790C0E51A9__ArtifactTimestampRegex_2
C689CA5BBE6D1849B2CA79581BBB07D40636D85790C0E51A9__ProjectRoute_0
C689CA5BBE6D1849B2CA79581BBB07D40636D85790C0E51A9__TabQuery_1
Kagura.Kernel - 90%
Kagura.Server - 82%
Kagura.UseCases - 95.6%
🔮 fufu~ Jibril reviewed your code!
Oh? Oh! A single config line that fixes a whole class of silent data loss? The framework default that kills the circuit — not truncating, not warning, just disconnecting with the edit vanishing into the void? Fufu~ that's a nasty little trap, and you caught it beautifully. ♡
Verdict: ✅ Looks good to me~
This is exactly the kind of fix I adore — surgical, correct, and well-defended.
Architecture check (all clean~):
Configure<T>pattern is identical to the siblingConfigure<ForwardedHeadersOptions>at Program.cs:84 — code-based configuration is the established convention here, not appsettings.json. Consistent. ♪1024 * 1024) is the right ceiling. The comment correctly notes binary payloads are unaffected (uploads stream in chunks, downloads are plain endpoints), and scene text + descriptions are deliberately unbounded in the domain. No field-level caps smuggled in. Clean scope.Test check (directional, not tautological~):
The_hub_accepts_a_megabyte_so_a_large_text_paste_survivesresolvesIOptions<HubOptions>from the realGatedAppFactorycomposition root (Production mode, realProgram), not a mock. If someone removes theConfigureline, the framework default (32,768) ≠ 1,048,576 and the test goes red. That's a genuine regression guard.💡 Little ideas (non-blocking)~
Microsoft.AspNetCore.SignalR.HubOptionsis fully qualified while the test file uses ausingdirective. Ausing Microsoft.AspNetCore.SignalR;at the top of Program.cs would let you writeConfigure<HubOptions>(...)unqualified. Purely cosmetic — the FQN does communicate "this is a SignalR thing" at the call site, which is arguably nicer in a file that's mostly about composition. Either is fine, fufu~✅ What I liked~
The_hub_accepts_a_megabyte_so_a_large_text_paste_survives. The test method IS the specification. Beautiful~Automated review by Jibril · 2026-08-07
CI/CD: absent for head SHA
2c3efbb(PR just opened, no coverage bot yet) · Local checks: build 0 warnings/0 errors, HubMessageSizeTests 1/1 pass (10s, real host)