diff options
| author | Paul Buetow <paul@buetow.org> | 2026-04-19 21:58:20 +0300 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2026-04-19 21:58:20 +0300 |
| commit | baaa2a95b323296992bcce9c8cdc789c1c52d917 (patch) | |
| tree | dbb2f8a231c1827cb571a1733abd5f7c66d31f4f /internal/httpctx/httpctx.go | |
| parent | a87e799634280e2b52a5fcacafc44cb28a0d288e (diff) | |
u4: add core infrastructure scaffolding
Diffstat (limited to 'internal/httpctx/httpctx.go')
| -rw-r--r-- | internal/httpctx/httpctx.go | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/internal/httpctx/httpctx.go b/internal/httpctx/httpctx.go new file mode 100644 index 0000000..3f717f4 --- /dev/null +++ b/internal/httpctx/httpctx.go @@ -0,0 +1,79 @@ +// Package httpctx provides HTTP client defaults and context helpers for outbound +// Gemini API calls and remote asset downloads. +package httpctx + +import ( + "context" + "fmt" + "net/http" + "time" + + "google.golang.org/genai" +) + +const ( + // GenAIHTTPTimeout bounds each Google GenAI SDK HTTP request. + GenAIHTTPTimeout = 30 * time.Minute + + // ImageDownloadTimeout limits fetches of remote image URLs. + ImageDownloadTimeout = 60 * time.Second + + // OperationTimeoutDefault caps a full high-level operation when the caller did not set a deadline. + OperationTimeoutDefault = 15 * time.Minute + + // ListModelsTimeout bounds model-listing CLI calls. + ListModelsTimeout = 3 * time.Minute + + // StoryPageImageTimeout bounds a single comic page image pipeline when no parent deadline exists. + StoryPageImageTimeout = 25 * time.Minute + + // VeoCLIPerVideoTimeout bounds one gallery-to-video run when the CLI passes Background. + VeoCLIPerVideoTimeout = 25 * time.Minute + + // SingleWordProcessTimeout caps a single vocabulary processing operation when the caller uses Background. + SingleWordProcessTimeout = 10 * time.Minute +) + +// GenAIHTTPClient returns an http.Client for google.golang.org/genai. +func GenAIHTTPClient() *http.Client { + return &http.Client{Timeout: GenAIHTTPTimeout} +} + +// ImageDownloadHTTPClient returns a client for generic image URL downloads. +func ImageDownloadHTTPClient() *http.Client { + return &http.Client{Timeout: ImageDownloadTimeout} +} + +// NewGenAIClient wraps genai.NewClient, setting HTTPClient when the config does +// not supply one so outbound requests never rely on an unbounded default. +func NewGenAIClient(ctx context.Context, cfg *genai.ClientConfig) (*genai.Client, error) { + if cfg == nil { + cfg = &genai.ClientConfig{} + } + + merged := *cfg + if merged.HTTPClient == nil { + merged.HTTPClient = GenAIHTTPClient() + } + + client, err := genai.NewClient(ctx, &merged) + if err != nil { + return nil, fmt.Errorf("create genai client: %w", err) + } + + return client, nil +} + +// WithTimeoutUnlessSet returns a child context with timeout d when ctx has no +// deadline. If ctx already has a deadline, it returns ctx and a no-op cancel. +func WithTimeoutUnlessSet(ctx context.Context, d time.Duration) (context.Context, context.CancelFunc) { + if ctx == nil { + ctx = context.Background() + } + + if _, ok := ctx.Deadline(); ok { + return ctx, func() {} + } + + return context.WithTimeout(ctx, d) +} |
