Documentation
¶
Overview ¶
Package backendutil holds the shared plumbing used by every platform backend under backends/. It exists to eliminate the copy-pasted HTTP-client, hook, retry, and base-URL construction that was previously duplicated (often byte-for-byte) across the seven backend packages.
These helpers are intentionally internal: they are an implementation detail of the backends and must not become part of the SDK's public API.
Index ¶
- Constants
- Variables
- func AllPages[T any](fetch func(page int) ([]T, error)) ([]T, error)
- func ChainTransport(inner, outer http.RoundTripper) http.RoundTripper
- func ConvertHooks(h *provider.Hooks) *transport.Hooks
- func DefaultBaseURL(base, def string) string
- func Esc(s string) string
- func HTTPTransport(skipTLS bool) http.RoundTripper
- func MapRetryConfig(rc *provider.RetryConfig) *transport.RetryConfig
- func NewScanLimitError(msg string) error
- func NormalizeBaseURL(base string) string
- func ParseIssueNumber(platform provider.Platform, op, number string) (int, error)
- func ParseIssueNumber64(platform provider.Platform, op, number string) (int64, error)
- func ParseMilestoneNumber(platform provider.Platform, op, number string) (int64, error)
- func ParsePRNumber(platform provider.Platform, op, number string) (int, error)
- func ParsePRNumber64(platform provider.Platform, op, number string) (int64, error)
- func ResolveLabelID(scan LabelPageFunc, name string, maxPages, perPage int) (int64, error)
- func ResolveLabelIDs(scan LabelPageFunc, names []string, maxPages, perPage int) (map[string]int64, error)
- func ToTransportLogger(l provider.Logger) transport.Logger
- type IDCache
- func (c *IDCache) Evict()
- func (c *IDCache) Get(key string) (int64, bool)
- func (c *IDCache) Len() int
- func (c *IDCache) Put(key string, id int64)
- func (c *IDCache) ResolveLabel(key, name string, scan LabelPageFunc, maxPages, perPage int) (int64, error)
- func (c *IDCache) ResolveLabelIDsWithCache(key string, names []string, scan LabelPageFunc, maxPages, perPage int) (map[string]int64, error)
- type LabelPageFunc
- type LabelRef
- type ScanLimitError
Constants ¶
const IssueCommentPageSize = 100
IssueCommentPageSize is the per-page value for paginated issue-comment fetches across all backends.
const LabelPageSize = 100
LabelPageSize is the per-page value for paginated label-list fetches across all backends.
const LabelScanMaxPages = 50
LabelScanMaxPages is the maximum number of pages to scan when resolving label names to IDs. At LabelPageSize items per page, this caps the scan at 5000 labels.
Variables ¶
var ErrLabelScanLimit = errors.New("label not found within scan limit")
ErrLabelScanLimit reports that the named label was not found within the scanned page budget. It is distinct from a definitive not-found: the label may exist beyond the limit, so callers surface it as a scan-limit error rather than a 404.
Functions ¶
func AllPages ¶
AllPages fetches every page of a paginated list by advancing the page number until the platform returns an empty page. fetch receives the 1-based page number and must request that page with whatever page size the caller chose. Stopping on the first empty page (rather than on a short page) keeps the result complete even when the server caps the page size below the requested per-page value; the platform's list endpoint must honor the page parameter, which every supported platform's list API does.
func ChainTransport ¶
func ChainTransport(inner, outer http.RoundTripper) http.RoundTripper
ChainTransport chains two round trippers. The outer tripper is invoked first; if it returns a non-nil response or a non-nil error that result is returned, otherwise the inner transport (the underlying connection) handles the request.
func ConvertHooks ¶
ConvertHooks adapts provider.Hooks into transport.Hooks. The request-hook signatures differ across the two packages (provider.RequestHook returns a context; transport.RequestHook returns an error), so each request hook is wrapped to discard the returned context. Identical across all backends.
func DefaultBaseURL ¶
DefaultBaseURL returns base if non-empty, otherwise def.
func Esc ¶
Esc is a shared path-escaping helper used by backends whose platform API paths contain owner/repo segments that may need URL encoding.
func HTTPTransport ¶
func HTTPTransport(skipTLS bool) http.RoundTripper
HTTPTransport returns an http.RoundTripper honouring the skipTLS flag: the default transport when verification is enabled, or a transport that disables certificate verification when the caller has explicitly opted into SkipTLS.
func MapRetryConfig ¶
func MapRetryConfig(rc *provider.RetryConfig) *transport.RetryConfig
MapRetryConfig converts a provider.RetryConfig (which counts retries, i.e. attempts beyond the first) into a transport.RetryConfig (which counts total attempts), hence the +1. Returns nil for a nil input so callers can assign the result directly.
func NewScanLimitError ¶
NewScanLimitError builds a ScanLimitError with the given message.
func NormalizeBaseURL ¶
NormalizeBaseURL returns base with a single trailing slash removed and a trailing "/api/v1" suffix removed. Used by Gitea/Forgejo-style backends whose SDKs add the version prefix themselves.
func ParseIssueNumber ¶
ParseIssueNumber parses a string issue number into the platform's native integer type. The op and platform arguments are forwarded to the standard error wrapping so callers produce identical error messages.
func ParseIssueNumber64 ¶
ParseIssueNumber64 is like ParseIssueNumber but returns int64 for platforms whose SDK uses int64 IDs (Gitea, Forgejo, GitLab).
func ParseMilestoneNumber ¶
ParseMilestoneNumber parses a string milestone number/ID into int64.
func ParsePRNumber ¶
ParsePRNumber parses a string PR/MR number into int.
func ParsePRNumber64 ¶
ParsePRNumber64 is like ParsePRNumber but returns int64.
func ResolveLabelID ¶
func ResolveLabelID(scan LabelPageFunc, name string, maxPages, perPage int) (int64, error)
ResolveLabelID scans pages for the named label and returns its ID, or ErrLabelScanLimit when the budget is exhausted or a short page is reached without a match. Scan errors propagate unchanged.
func ResolveLabelIDs ¶
func ResolveLabelIDs(scan LabelPageFunc, names []string, maxPages, perPage int) (map[string]int64, error)
ResolveLabelIDs resolves multiple label names in a single scan pass. It fetches pages once and matches all names, returning a map of name → ID. Names not found within the scan budget are omitted from the result (callers can check len(result) vs len(names) to detect misses).
Types ¶
type IDCache ¶
type IDCache struct {
// contains filtered or unexported fields
}
IDCache is a TTL cache from string keys to int64 IDs. Backends use it to memoize name→ID resolutions (labels, users) so repeated writes do not rescan. The zero value is not usable; construct with NewIDCache.
func NewIDCache ¶
NewIDCache constructs an IDCache with the given TTL (TTL <= 0 never expires entries).
func (*IDCache) Evict ¶
func (c *IDCache) Evict()
Evict removes all expired entries from the cache. Call this periodically to prevent unbounded memory growth in long-lived processes.
func (*IDCache) ResolveLabel ¶
func (c *IDCache) ResolveLabel(key, name string, scan LabelPageFunc, maxPages, perPage int) (int64, error)
ResolveLabel resolves via ResolveLabelID and caches the result under key+"/"+name. Failures are not cached.
func (*IDCache) ResolveLabelIDsWithCache ¶
func (c *IDCache) ResolveLabelIDsWithCache(key string, names []string, scan LabelPageFunc, maxPages, perPage int) (map[string]int64, error)
ResolveLabelIDsWithCache resolves multiple label names, using the cache for hits and falling back to a single scan pass for misses.
type LabelPageFunc ¶
LabelPageFunc fetches one page of labels; page is 1-based, perPage is the requested page size, and a page returning fewer than perPage refs ends the scan.
type LabelRef ¶
LabelRef is the minimal label shape the resolver needs from one platform page fetch.
type ScanLimitError ¶
type ScanLimitError struct {
Msg string
}
ScanLimitError wraps ErrLabelScanLimit with a platform-specific message (errors.Is reports it as ErrLabelScanLimit). Callers that need to distinguish "not found within the scan budget" from other failures use errors.Is(err, backendutil.ErrLabelScanLimit).
func (*ScanLimitError) Error ¶
func (e *ScanLimitError) Error() string
func (*ScanLimitError) Unwrap ¶
func (e *ScanLimitError) Unwrap() error