What happened
In both piped (v0) and pipedv1, the deployment store's sync() loop calls ListNotCompletedDeployments exactly once per sync cycle and discards the cursor field on the response:
pkg/app/piped/apistore/deploymentstore/store.go:105-111
pkg/app/pipedv1/apistore/deploymentstore/store.go:105-111
Both files carry an explicit TODO that has been there since the RPC was introduced:
// TODO: Call ListNotCompletedDeployments itervally until all required deployments are fetched.
resp, err := s.apiClient.ListNotCompletedDeployments(ctx, &pipedservice.ListNotCompletedDeploymentsRequest{})
The server already returns a cursor on partial pages (pkg/app/server/service/pipedservice/service.proto:278-281), but the request message has no cursor / page_size fields, and the server (pkg/app/server/grpcapi/piped_api.go:350-386) does not accept one either — so there is currently no way for piped to request the next page.
Impact
If the controlplane's datastore returns a partial page of not-completed deployments (this depends on the backing datastore's default page size), piped will silently skip every deployment past the first page until the next sync tick — and since sync always starts from the beginning, the tail can be starved indefinitely under steady deployment pressure.
This is the classic "cursor returned but never followed" bug; it becomes user-visible as "some deployments appear stuck in PENDING/PLANNED until piped restarts or load decreases."
Proposed fix
- Add
cursor (string) and page_size (int32) to ListNotCompletedDeploymentsRequest in service.proto, regenerate stubs.
- In
PipedAPI.ListNotCompletedDeployments, forward req.Cursor and req.PageSize into datastore.ListOptions.
- In both piped stores, replace the single call with a loop that re-invokes the RPC with the returned cursor until it comes back empty, accumulating deployments across pages before classifying them into
pendings / planneds / runnings.
- Add table-driven tests for both stores against a fake
apiClient that returns multiple pages.
Happy to split this into a proto/server PR and a piped-client PR if maintainers would prefer smaller diffs. Will sign commits with DCO.
Environment
- Branch:
master at commit 78fdbeb7c
- Affected components:
piped, pipedv1, controlplane
If a maintainer is willing to assign this to me, I would like to pick it up.
What happened
In both
piped(v0) andpipedv1, the deployment store'ssync()loop callsListNotCompletedDeploymentsexactly once per sync cycle and discards thecursorfield on the response:pkg/app/piped/apistore/deploymentstore/store.go:105-111pkg/app/pipedv1/apistore/deploymentstore/store.go:105-111Both files carry an explicit TODO that has been there since the RPC was introduced:
The server already returns a cursor on partial pages (
pkg/app/server/service/pipedservice/service.proto:278-281), but the request message has nocursor/page_sizefields, and the server (pkg/app/server/grpcapi/piped_api.go:350-386) does not accept one either — so there is currently no way for piped to request the next page.Impact
If the controlplane's datastore returns a partial page of not-completed deployments (this depends on the backing datastore's default page size),
pipedwill silently skip every deployment past the first page until the next sync tick — and since sync always starts from the beginning, the tail can be starved indefinitely under steady deployment pressure.This is the classic "cursor returned but never followed" bug; it becomes user-visible as "some deployments appear stuck in PENDING/PLANNED until piped restarts or load decreases."
Proposed fix
cursor(string) andpage_size(int32) toListNotCompletedDeploymentsRequestinservice.proto, regenerate stubs.PipedAPI.ListNotCompletedDeployments, forwardreq.Cursorandreq.PageSizeintodatastore.ListOptions.pendings/planneds/runnings.apiClientthat returns multiple pages.Happy to split this into a proto/server PR and a piped-client PR if maintainers would prefer smaller diffs. Will sign commits with DCO.
Environment
masterat commit78fdbeb7cpiped,pipedv1,controlplaneIf a maintainer is willing to assign this to me, I would like to pick it up.