fix: list subscriptions through v2 and paginate the method that was called - #11
Merged
Merged
Conversation
…alled
Two bugs the 0.2.1 changelog listed as known issues, one of which was worse than
recorded.
`#list` used base_path, which is `/v1/subscriptions` -- a route that does not
exist. It answers 404 "Route not found", so the method always raised and the
"inconsistent with get/update" note undersold it. base_path stays on v1 because
the action sub-paths genuinely live there: POST /v1/subscriptions/{id}/update is
what the API accepts, and so are cancel, pause, activate and the rest. Only the
collection GET moves.
The existing example stubbed `/v1/subscriptions`, so it asserted the bug rather
than the behaviour and passed either way.
`Collection#next_page` re-issued the resource's default `#list` no matter which
method had produced the page, so a page from a custom one -- Subscriptions
#list_templates is the only current case -- paged into the wrong endpoint. For
subscriptions that endpoint was the 404 above. Collection now remembers the
method it came from.
Verified against the sandbox: list returns 29 subscriptions, next_page returns a
disjoint page, auto_paginate walks all 29, and list_templates answers 0 rows with
next_page nil rather than reaching for another endpoint.
gastonrey
marked this pull request as ready for review
August 21, 2026 14:29
Two PRs have landed since 0.2.1 without a changelog entry, and the "Known issues" list under 0.2.1 documents the two bugs the previous commit fixes -- so as it stands the file tells the next reader that a method which now works still cannot return. 0.2.1 keeps its list unchanged: it was accurate for that release. The Unreleased section says which of them are fixed, and carries the API contracts that were established against the sandbox rather than inferred -- archive-before-delete, PUT rather than POST for archiving, and the bare array from the product-features endpoint -- because none of them are in Hyperline's docs. The remaining known issue is the one this run did not solve: retry policy is a constant here and configuration there, which is why a consumer needing a hard timeout or a retry on 404 still wraps #request itself.
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.
Both of these are listed as Known issues in the 0.2.1 changelog. One of them is worse than
recorded, and the example covering it was asserting the bug.
#listalways raisedSubscriptions#listusedbase_path, which is/v1/subscriptions— a route that does notexist. Verified against the sandbox:
The changelog described this as "uses the v1 path while
#get/#updateand search use v2",which reads like an inconsistency. It is a method that could never return.
base_pathstays on v1, because the action sub-paths genuinely live there:POST /v1/subscriptions/{id}/updateis what the API accepts, and so arecancel,pause,activate,reactivate,reinstateandrenew. Movingbase_pathwholesale breaks 21examples. Only the collection GET moves, onto the same
search_paththat search already uses.The existing example stubbed
/v1/subscriptions, so it passed whether or not the endpointexisted — the same failure mode as the
update_operationpayload corrected in #10: a stubvalidating a shape nobody had checked against the API.
#next_pageleft the endpoint it came fromCollection#next_pagere-issued@resource.listregardless of which method produced the page,so a page from a custom list method paged into the resource's default endpoint. Today
Subscriptions#list_templatesis the only such method, and the endpoint it would have jumped tois the 404 above.
Collectionnow takes the method that produced it, defaulting to:list, andnext_pagecallsthat. Existing callers are unaffected.
Verification
collection_spec.rbcovers the default path, the custom-method path, the last page, andauto_paginateover a custom method.next_pageback to the defaultlist(2 failures),listbackto
resource_path(1), andbase_pathmoved to v2 (21 — which is the evidence for leaving italone).
listreturns 29 subscriptions,next_pagereturns a disjoint page,auto_paginatewalks all 29, andlist_templatesanswers 0 rows with
next_pagenil instead of reaching for another endpoint.A correction
An earlier read of this claimed
list_templates(...).next_pageraisedNoMethodError. It doesnot: the sandbox has zero templates, so
next_pagecorrectly returnedniland the probe called.dataon it. The pagination bug here is the wrong-endpoint one above, pinned by a spec ratherthan by a live reproduction.
Still open, not in this PR
MAX_WRITE_RETRIES = 2whileConfigurationalreadycarries
max_retriesfor the read retry — two budgets, one unreachable.push_hyperline_catalog.rbin the monolith still monkey-patchesBaseResource#request,because it needs a hard timeout, retries on 404 and 409, poison detection, and nonce-carrying
keys. Until retry policy is configurable here, any signature change in this gem breaks that
script silently — which is exactly what feat: write safety, error classes, and the Features resource #10 did.