Help us shape the future of Go! Take the 2026 Go Developer Survey

backendutil

package
v0.99.8 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 30, 2026 License: MIT Imports: 11 Imported by: 0

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

View Source
const IssueCommentPageSize = 100

IssueCommentPageSize is the per-page value for paginated issue-comment fetches across all backends.

View Source
const LabelPageSize = 100

LabelPageSize is the per-page value for paginated label-list fetches across all backends.

View Source
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

View Source
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

func AllPages[T any](fetch func(page int) ([]T, error)) ([]T, error)

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

func ConditionalCache(cfg provider.Config) *transport.ETagCache

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

func ConvertHooks(h *provider.Hooks) *transport.Hooks

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

func DefaultBaseURL(base, def string) string

DefaultBaseURL returns base if non-empty, otherwise def.

func Esc

func Esc(s string) string

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

func NewScanLimitError(msg string) error

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

func NormalizeBaseURL(base string) string

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

func ParseIssueNumber(platform provider.Platform, op, number string) (int, error)

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

func ParseIssueNumber64(platform provider.Platform, op, number string) (int64, error)

ParseIssueNumber64 is like ParseIssueNumber but returns int64 for platforms whose SDK uses int64 IDs (Gitea, Forgejo, GitLab).

func ParseMilestoneNumber

func ParseMilestoneNumber(platform provider.Platform, op, number string) (int64, error)

ParseMilestoneNumber parses a string milestone number/ID into int64.

func ParsePRNumber

func ParsePRNumber(platform provider.Platform, op, number string) (int, error)

ParsePRNumber parses a string PR/MR number into int.

func ParsePRNumber64

func ParsePRNumber64(platform provider.Platform, op, number string) (int64, error)

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

func SDKHTTPClient(tc *transport.Client, skipTLS bool) *http.Client

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.

func ToTransportLogger

func ToTransportLogger(l provider.Logger) transport.Logger

ToTransportLogger adapts a provider.Logger to a transport.Logger.

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

func NewIDCache(ttl time.Duration) *IDCache

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) Get

func (c *IDCache) Get(key string) (int64, bool)

Get returns the cached ID for key when present and fresh.

func (*IDCache) Len

func (c *IDCache) Len() int

Len returns the number of entries in the cache (including stale ones).

func (*IDCache) Put

func (c *IDCache) Put(key string, id int64)

Put stores id under key with a fresh TTL.

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

type LabelPageFunc func(page, perPage int) ([]LabelRef, error)

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

type LabelRef struct {
	ID   int64
	Name string
}

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

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL