core

package
v0.5.3 Latest Latest
Warning

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

Go to latest
Published: May 1, 2026 License: MIT Imports: 19 Imported by: 0

Documentation

Overview

Package core provides core infrastructure for TGCP including authentication, HTTP client configuration, caching, service registry, and project management.

HTTP Client Configuration

The HTTP client is configured with three layers of middleware:

  1. Google Authentication (Application Default Credentials)
  2. Rate Limiting (Token Bucket Algorithm)
  3. Retry Logic (Exponential Backoff)

Rate Limiting

The rate limiter uses a token bucket algorithm to prevent API quota exhaustion. Configuration: 10 requests per second with a burst capacity of 20 requests.

How it works:

  • Tokens are added to the bucket at a constant rate (10 tokens/second)
  • Each request consumes 1 token
  • If tokens are available, the request proceeds immediately
  • If no tokens are available, the request waits until a token is available
  • Burst capacity allows handling traffic spikes up to 20 requests

Example:

client, err := core.NewHTTPClient(ctx, "https://www.googleapis.com/auth/cloud-platform")
if err != nil {
    return err
}
// All requests through this client are automatically rate-limited

Retry Logic

The retry transport implements exponential backoff for transient failures. Configuration: Maximum 3 retries with exponential backoff (100ms, 200ms, 400ms).

Retry conditions:

  • Network errors (connection failures, timeouts)
  • HTTP 429 (Too Many Requests) - rate limit exceeded
  • HTTP 5xx (Server Errors) - temporary server issues

Non-retryable conditions:

  • HTTP 4xx (Client Errors) - except 429
  • Context cancellation
  • Maximum retries exceeded

Backoff calculation: 2^i * 100ms where i is the retry attempt (0, 1, 2)

  • Attempt 1: 100ms delay
  • Attempt 2: 200ms delay
  • Attempt 3: 400ms delay

Example:

// A request that fails with 500 will be retried up to 3 times
// with increasing delays between attempts
resp, err := client.Get("https://compute.googleapis.com/...")

Index

Constants

View Source
const (
	// GitHubRepo is the repository for version checking
	GitHubRepo = "yogirk/tgcp"
	// ReleasesURL is the GitHub API endpoint for latest release
	ReleasesURL = "https://api.github.com/repos/" + GitHubRepo + "/releases/latest"
)

Variables

This section is empty.

Functions

func CheckForUpdates added in v0.2.0

func CheckForUpdates(currentVersion string) tea.Cmd

CheckForUpdates fetches the latest release from GitHub and compares versions

func NewHTTPClient

func NewHTTPClient(ctx context.Context, scopes ...string) (*http.Client, error)

NewHTTPClient returns an http.Client configured with: 1. Google Authentication (ADC) 2. Rate Limiting (10 RPS, Burst 20) 3. Retry Logic (Exponential Backoff, 3 retries)

The client uses a middleware chain: Client -> RateLimit -> Retry -> Auth(Base) All requests through this client are automatically rate-limited and retried on transient failures.

Example:

ctx := context.Background()
client, err := core.NewHTTPClient(ctx, "https://www.googleapis.com/auth/cloud-platform")
if err != nil {
    return fmt.Errorf("failed to create HTTP client: %w", err)
}
// Use client for GCP API calls - rate limiting and retries are automatic

Types

type AuthState

type AuthState struct {
	Authenticated bool
	UserEmail     string
	ProjectID     string
	Error         error
}

AuthState holds the authentication information

func Authenticate

func Authenticate(ctx context.Context, projectOverride string) AuthState

Authenticate performs the ADC check and project detection If projectOverride is not empty, it takes precedence.

type Cache

type Cache struct {
	// contains filtered or unexported fields
}

Cache provides a thread-safe in-memory cache

func NewCache

func NewCache() *Cache

NewCache creates a new Cache instance

func (*Cache) Delete

func (c *Cache) Delete(key string)

Delete removes an item from the cache

func (*Cache) Flush

func (c *Cache) Flush()

Flush removes all items from the cache

func (*Cache) Get

func (c *Cache) Get(key string) (interface{}, bool)

Get retrieves an item from the cache. Returns nil, false if not found or expired.

func (*Cache) Set

func (c *Cache) Set(key string, value interface{}, ttl time.Duration)

Set adds an item to the cache with a TTL

type CacheItem

type CacheItem struct {
	Value      interface{}
	Expiration time.Time
}

CacheItem holds the value and expiration time

type Command

type Command struct {
	Name        string
	Description string
	Action      func() Route
}

Command represents an actionable command in the palette

type GitHubRelease added in v0.2.0

type GitHubRelease struct {
	TagName     string `json:"tag_name"`
	Name        string `json:"name"`
	HTMLURL     string `json:"html_url"`
	Body        string `json:"body"`
	Prerelease  bool   `json:"prerelease"`
	Draft       bool   `json:"draft"`
	PublishedAt string `json:"published_at"`
}

GitHubRelease represents the GitHub API response for a release

type LastUpdatedMsg

type LastUpdatedMsg time.Time

LastUpdatedMsg updates the "Last Updated" timestamp

type LoadingMsg

type LoadingMsg struct {
	IsLoading bool
	Message   string // Optional custom message (empty = use playful messages)
}

LoadingMsg signals loading state changes to MainModel Services emit this when they start/stop loading data

type NavigationModel struct {
	CurrentRoute Route
	History      []Route
	Commands     []Command
	BaseCommands []Command // Persist default commands

	// Palette State
	PaletteActive bool
	Query         string
	Suggestions   []SuggestionMatch // Includes match info for highlighting
	Selection     int
}

NavigationModel manages routing and command palette state

func NewNavigation

func NewNavigation() NavigationModel
func (m *NavigationModel) ExecuteSelection() *Route

ExecuteSelection returns the route for the selected command

func (m *NavigationModel) FilterCommands(query string)

FilterCommands updates suggestions based on input query.

Ranking is a three-tier cascade so that literal matches always beat loose fuzzy hits — critical for short queries like "gce" where a plain fuzzy rank would float "GKE" above "GCE":

  1. Prefix match on Name (case-insensitive)
  2. Substring match anywhere in Name
  3. Fuzzy match on "Name + Description" for everything else

Within each tier, results preserve registration order from defaultCommands.

func (m *NavigationModel) RestoreBaseCommands()

RestoreBaseCommands resets to default commands

func (m *NavigationModel) SelectNext()

SelectNext moves selection down

func (m *NavigationModel) SelectPrev()

SelectPrev moves selection up

func (m *NavigationModel) SetCommands(cmds []Command)

SetCommands updates the available commands (e.g. for switching context)

type Project

type Project struct {
	ID   string
	Name string
}

Project represents a GCP project

type ProjectManager

type ProjectManager struct {
	// contains filtered or unexported fields
}

ProjectManager handles project listing and switching

func NewProjectManager

func NewProjectManager(cache *Cache) *ProjectManager

NewProjectManager creates a new manager

func (*ProjectManager) ListProjects

func (pm *ProjectManager) ListProjects(ctx context.Context) ([]Project, error)

ListProjects fetches available projects for the user

func (*ProjectManager) SearchProjects

func (pm *ProjectManager) SearchProjects(query string) []Project

SearchProjects filters projects by query

type RateLimitTransport

type RateLimitTransport struct {
	Next    http.RoundTripper
	Limiter *TokenBucket
}

func (*RateLimitTransport) RoundTrip

func (t *RateLimitTransport) RoundTrip(req *http.Request) (*http.Response, error)

type RetryTransport

type RetryTransport struct {
	Next http.RoundTripper
}

RetryTransport implements automatic retry with exponential backoff for HTTP requests. It wraps an existing http.RoundTripper and retries failed requests up to 3 times.

Retry conditions:

  • Network errors (connection failures, timeouts)
  • HTTP 429 (Too Many Requests)
  • HTTP 5xx (Server Errors)

Non-retryable:

  • HTTP 4xx (Client Errors) except 429
  • Context cancellation
  • Maximum retries exceeded

Backoff: Exponential backoff with formula 2^i * 100ms

  • Retry 1: 100ms delay
  • Retry 2: 200ms delay
  • Retry 3: 400ms delay

func (*RetryTransport) RoundTrip

func (t *RetryTransport) RoundTrip(req *http.Request) (*http.Response, error)

RoundTrip executes the HTTP request with automatic retry on transient failures. It implements exponential backoff between retry attempts.

The method will retry up to 3 times for:

  • Network errors
  • HTTP 429 (rate limit)
  • HTTP 5xx (server errors)

Returns the last response/error if all retries are exhausted.

type Route

type Route struct {
	View    ViewType
	Service string // e.g., "gce", "sql"
	ID      string // resource ID or Project ID
}

Route represents a navigational destination

type ServiceFactory

type ServiceFactory func(*Cache) services.Service

ServiceFactory is a function that creates a new service instance

type ServiceRegistry

type ServiceRegistry struct {
	// contains filtered or unexported fields
}

ServiceRegistry manages service registration and lazy initialization

func NewServiceRegistry

func NewServiceRegistry(cache *Cache) *ServiceRegistry

NewServiceRegistry creates a new service registry

func (*ServiceRegistry) GetOrInitializeService

func (r *ServiceRegistry) GetOrInitializeService(ctx context.Context, name string) (services.Service, error)

GetOrInitializeService gets a service from the map, initializing it lazily if needed This is the key method for lazy initialization - services are only initialized when first accessed

func (*ServiceRegistry) GetServiceNames

func (r *ServiceRegistry) GetServiceNames() []string

GetServiceNames returns a list of all registered service names

func (*ServiceRegistry) InitializeAll

func (r *ServiceRegistry) InitializeAll(ctx context.Context, projectID string) map[string]services.Service

InitializeAll creates all registered services but does NOT initialize them Services are initialized lazily on first access via GetOrInitializeService

func (*ServiceRegistry) IsRegistered

func (r *ServiceRegistry) IsRegistered(name string) bool

IsRegistered checks if a service is registered

func (*ServiceRegistry) Register

func (r *ServiceRegistry) Register(name string, factory ServiceFactory)

Register registers a service factory with the given name

func (*ServiceRegistry) ReinitializeAll

func (r *ServiceRegistry) ReinitializeAll(ctx context.Context, projectID string, svcMap map[string]services.Service)

ReinitializeAll reinitializes all initialized services with a new project ID

type StatusMsg

type StatusMsg struct {
	Message string
	IsError bool
}

StatusMsg updates the status bar message

type SuggestionMatch

type SuggestionMatch struct {
	Command
	MatchedIndexes []int // Positions of matched characters in Name+Description
}

SuggestionMatch wraps a Command with fuzzy match info for highlighting

type SwitchToLogsMsg

type SwitchToLogsMsg struct {
	Filter  string
	Source  string // The short name of the service initiating the switch
	Heading string // Optional heading to display (e.g. resource name)
}

SwitchToLogsMsg requests a context switch to the logging service

type SwitchToServiceMsg added in v0.2.0

type SwitchToServiceMsg struct {
	Service string // The short name of the service to switch to
}

SwitchToServiceMsg requests a context switch to a specific service

type ToastMsg

type ToastMsg struct {
	Message  string
	Type     ToastType
	Duration time.Duration // 0 means use default (3 seconds)
}

ToastMsg triggers a toast notification in the UI

type ToastType

type ToastType int

ToastType defines the visual style of a toast notification

const (
	ToastSuccess ToastType = iota
	ToastError
	ToastInfo
)

type TokenBucket

type TokenBucket struct {
	// contains filtered or unexported fields
}

TokenBucket implements a token bucket rate limiting algorithm. It allows a certain number of requests per second (rate) with a burst capacity.

Algorithm:

  • Tokens are added to the bucket at a constant rate
  • Each request consumes one token
  • If tokens are available, the request proceeds immediately
  • If no tokens are available, the request waits until tokens are refilled

Thread-safe: Uses mutex to protect concurrent access to token state.

func NewTokenBucket

func NewTokenBucket(rate, burst float64) *TokenBucket

NewTokenBucket creates a new token bucket rate limiter.

Parameters:

  • rate: Tokens added per second (e.g., 10.0 = 10 requests/second)
  • burst: Maximum tokens (e.g., 20.0 = can handle 20 requests in quick succession)

Example:

limiter := NewTokenBucket(10.0, 20.0) // 10 req/s, burst of 20

func (*TokenBucket) Wait

func (tb *TokenBucket) Wait(ctx context.Context) error

Wait blocks until a token is available or the context is cancelled. It automatically refills tokens based on elapsed time since last refill.

Returns:

  • nil if a token was successfully acquired
  • context.Err() if the context was cancelled

Example:

if err := limiter.Wait(ctx); err != nil {
    return err // Context cancelled
}
// Token acquired, proceed with request

type UpdateCheckedMsg added in v0.2.0

type UpdateCheckedMsg struct {
	UpdateInfo UpdateInfo
}

UpdateCheckedMsg is sent when version check completes

type UpdateInfo added in v0.2.0

type UpdateInfo struct {
	Available      bool
	LatestVersion  string
	CurrentVersion string
	ReleaseURL     string
	ReleaseNotes   string
	CheckedAt      time.Time
	Error          error
}

UpdateInfo holds information about available updates

type VersionInfo added in v0.2.0

type VersionInfo struct {
	Version string
	Commit  string
	Date    string
}

VersionInfo holds the current application version information

func (VersionInfo) FormatVersion added in v0.2.0

func (v VersionInfo) FormatVersion() string

FormatVersion returns a formatted version string

func (VersionInfo) String added in v0.2.0

func (v VersionInfo) String() string

String returns a full version string with commit info

type ViewType

type ViewType int

ViewType enumerates available views

const (
	ViewHome ViewType = iota
	ViewServiceList
	ViewResourceDetail
	ViewHelp
	ViewProjectSwitcher
)

Jump to

Keyboard shortcuts

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