feat(inbounds): add a narrow endpoint for subscription sort order - #6179
feat(inbounds): add a narrow endpoint for subscription sort order#6179n0ctal wants to merge 1 commit into
Conversation
|
Follow-up on the two remaining red checks, with what I could verify from here.
I checked out
The same job is green on
Nothing in either check comes from this branch. |
Changing an inbound's position in subscription output currently goes through /update/:id, which takes a whole inbound: the caller has to send settings and the entire client list back, and whatever it read before the edit is what gets written. Two people reordering and editing clients in the same inbound race on one blob, and the reorder wins by overwriting. Mirror the existing /setEnable/:id shape. The handler takes only the index and the service reads the stored inbound, so nothing in the request can reach the settings JSON. Node-owned inbounds are marked dirty in the same transaction and pushed through the existing runtime update.
5157d8e to
ba1fd60
Compare
Summary
Reordering an inbound in subscription output requires
/update/:id, which accepts and rewrites the whole inbound including its client list. Add/panel/api/inbounds/:id/subSortIndex, taking only the index — the same shape as the existing/setEnable/:id.Why
SubSortIndexis presentation-only:internal/sub/service.goorders subscription entries by it, and nothing in the Xray config depends on it. Changing it should not require sending a client list back.Today it does.
UpdateInboundtakes a*model.Inbound, so a UI or script that wants to move an inbound one place up reads the inbound, sets one integer and writes everything back. If a client was added or edited in that window, the reorder overwrites it — a lost update with no error on either side, and the larger the inbound the wider the window.The repository already treats this as a known shape: the summary of
/update/:idinendpoints.tssays "Heavy on inbounds with thousands of clients — prefer /setEnable for enable-only flips". This is the same argument for the other metadata-only field.Scope
internal/web/controller/inbound.go—POST /:id/subSortIndex, binding onlysubSortIndex(min=1), modelled onsetInboundEnable.internal/web/service/inbound.go—SetInboundSubSortIndexreads the stored inbound, no-ops when unchanged, updates the single column, marks a node-owned inbound dirty in the same transaction, and pushes through the existingrt.UpdateInbound. No new runtime method and no new remote endpoint.frontend/src/pages/api-docs/endpoints.ts+ regeneratedfrontend/public/openapi.jsonviamake gen.internal/web/service/inbound_subsort_test.go— asserts the index changes and the settings JSON is byte-identical afterwards.Deliberately not included: a narrow remote push. The node still receives a full
UpdateInbound, so this PR fixes the lost-update problem without widening the node contract. Narrowing the remote call is a separate change if you want it.Validation
go test ./internal/web/service/ -run SetInboundSubSortIndex -count=1green.go test ./internal/web/ -run RouteRegistryContract -count=1green, so the registry entry matches the route.make genrun;go build ./...,go vet,gofmt -lclean.Risk
Low and additive. No existing route, service method or model field changes behaviour;
/update/:idkeeps working exactly as before.