Tighten the generated SDK runtime and finish the gosdk rename - #631
Merged
Merged
Conversation
Follow-up to #626, which merged before these review residuals landed. Generated runtime: - Read response bodies through readBody. bytes.Buffer.ReadFrom reserves bytes.MinRead before every read, so Grow(Content-Length) alone still reallocated and a 12-byte body cost 1.6KB. Reserve the headroom when the length is declared and fall back to io.ReadAll when it is not. - Apply credentials in place. authorize cloned the whole request for every complete alternative; it now clones only when a later alternative could still run, which is the one case where a failed Apply can leak partial writes. One Widgets.List call against a stub doer goes from 2067ns, 5560B and 45 allocs to 1696ns, 3656B and 38 allocs. Emitter: - Rename generator/sdk/golang to generator/sdk/gosdk so the directory matches the package, and carry the name through the doc comment, the README, the generated file headers and the error prefix. No tag contains the merge yet, so the import path is still free to move. - Share one shape walk (forEachShapeChild) between reachability and collection so the two cannot disagree about what is generated. - Give generator/golang a single scalar mapping. ScalarType now takes the JSON type and format, and goType uses the same builtinScalarType, so SDK parameters and model fields cannot drift. Tests: the generated -race suite now proves a failed alternative does not leak into its fallback (it fails with the clone removed) and that Content-Length is a preallocation hint, never a bound. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #631 +/- ##
==========================================
+ Coverage 99.79% 99.87% +0.08%
==========================================
Files 288 296 +8
Lines 35523 37147 +1624
==========================================
+ Hits 35449 37101 +1652
+ Misses 46 27 -19
+ Partials 28 19 -9
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Follow-up to #626. I merged that one before the last of the review residuals landed, so here they are on their own branch.
The one that was on me
In the 626 review I said "seed a
bytes.BufferfromContent-Length". The implementation did exactly that, and it made small bodies worse.bytes.Buffer.ReadFromreservesbytes.MinRead(512) before every read, including the final one that reports EOF, soGrow(Content-Length)still reallocates. A 12-byte JSON body cost 1.6KB and 4 to 5 allocs where plainio.ReadAllcost 584B and 3.readBodynow reserves the headroom when the length is declared and falls back toio.ReadAllwhen it is unknown, over the limit, or not addressable. A 1MB body is 1.06MB and 3 allocs, against 2.2MB and 26 on the original path.Credentials applied in place
authorizecloned the entire request for every complete alternative. The clone only matters when a failedApplycould leave partial writes behind and a later alternative could still run. That is now the only case that clones. Everything else applies straight to the request.Widgets.Listcall, stub doermaintodayFinishing the rename
package gosdkwas living in a directory calledgolang, under a doc comment that said "Package golang", with 48 error strings prefixedsdk/golang:. The directory is nowgenerator/sdk/gosdkand the name is carried through the doc comment, the README, the generated file headers and the error prefix (gosdk:).This moves an import path. No tag contains the 626 merge yet (latest is
v0.38.7), so it is free today and a breaking change after the next release. Worth landing before one is cut.Two smaller things
forEachShapeChild, so they cannot disagree about what gets generated. Neither callback heap-allocates.generator/golanghas one scalar mapping.ScalarTypetakes the JSON type and format, andgoTypeuses the samebuiltinScalarType, so SDK parameter types and model field types come from one place.ScalarTypechanged signature, which is fine for the same reason the rename is: it has never been released.Tests
The generated
-racesuite gained two cases. One proves a credential that fails part-way through an alternative does not leak into the fallback request (it fails with the clone removed, showingAuthorization: Bearer tokenriding along with the service key). The other provesContent-Lengthis a preallocation hint and never a bound: declared, absent, understated and over-limit all behave.All three generator packages stay at 100%, and every block this branch touches is covered.
Deliberately left alone
newRequeststill parses the path, stringifies the endpoint, and letshttp.NewRequestWithContextparse it again. That is about 3 of the remaining 38 allocs. The clean fix changes how URLs are assembled for malformed path templates, so it wants its own PR with table tests on URL assembly.time.Timeparameter encoder. WithOptions.Modelswired, mappingdate-timetotime.Timemakes anydate-timeparameter a generation error until one exists. Next increment.higharazzo.Workflowas public API, because the engine will want it. That is a call about the core model's surface, so it is not riding in here.autotargets apply and removing it would drop project coverage.🤖 Generated with Claude Code