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 Auth(cfg provider.Config, style string) transport.AuthStrategy
- func ChainTransport(inner, outer http.RoundTripper) http.RoundTripper
- func ConditionalCache(cfg provider.Config) *transport.ETagCache
- 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 NewTransportClient(cfg provider.Config, baseURL, style string, extra ...transport.ClientOption) *transport.Client
- func NormalizeBaseURL(base string) string
- func PageList[T any](page, perPage, walkPageSize int, fetch func(page, perPage int) ([]T, error)) ([]T, error)
- 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 SDKHTTPClient(tc *transport.Client, skipTLS bool) *http.Client
- 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 Auth ¶ added in v0.72.0
func Auth(cfg provider.Config, style string) transport.AuthStrategy
Auth builds the transport auth strategy for cfg. When cfg.TokenSource is set it returns a per-request refreshable TokenSourceAuth in the given style (provider.TokenSource and transport.TokenSource share one method set, so the value forwards unchanged); otherwise it returns the static strategy equivalent for that style. style is one of the transport.AuthStyle* constants.
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 ConditionalCache ¶ added in v0.72.0
ConditionalCache returns the ETag cache shared by a backend's transport client and round tripper when cfg.ConditionalRequests is enabled, nil otherwise. Assign straight to transport.Client.ETag.
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 NewTransportClient ¶ added in v0.77.0
func NewTransportClient(cfg provider.Config, baseURL, style string, extra ...transport.ClientOption) *transport.Client
NewTransportClient builds the transport.Client every backend shares between its own raw HTTP calls and its SDK round tripper, applying the provider config concerns exactly once: auth style (static token or refreshable TokenSource), logger, ETag conditional-request cache, retry policy, TLS-skip transport, and hooks. The extra options are appended last, so a backend with platform-specific plumbing (e.g. TencentCODE's pinned TLS transport) can override the standard wiring per option.
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 PageList ¶ added in v0.77.0
func PageList[T any](page, perPage, walkPageSize int, fetch func(page, perPage int) ([]T, error)) ([]T, error)
PageList is the shared dual-mode list idiom of the Gitea-family backends: page == 0 walks every page of the endpoint (AllPages, budget-capped) at walkPageSize; page > 0 fetches exactly the caller-driven single page at the normalized caller per-page size. fetch is invoked as fetch(page, perPage) with both values ready to forward into the SDK list options.
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).
func SDKHTTPClient ¶ added in v0.77.0
SDKHTTPClient builds the http.Client handed to a platform SDK so that SDK-issued requests flow through the same auth/retry/hooks pipeline as the backend's own calls: the SkipTLS-honouring transport underneath the client's retrying round tripper.
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.
Storage, TTL and expiry bookkeeping are delegated to oekit/pkg/cache's LocalCache (in-process TTL+LRU cache); the backend-facing contract (Get/Put/Evict/Len) is unchanged.
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