Skip to content
skyl

Option

Configures a Client. Applied in order.

Option is skyl's functional-option type. Every option is a function that mutates a *Client during construction, and they are applied in the order you pass them.

Reference#

type Option func(*Client)

Caveats

  • Options are applied in order, so a later one overrides an earlier one of the same kind.
  • Invalid values are ignored, not rejected. A negative retry count or a non-positive delay leaves the default in place — there is no error return.
  • Options configure the Client, never the transport. HTTP concerns are provider options.

The options#

OptionDefaultBounds
WithMaxRetries(n)3How many times a retryable failure is retried
WithRetryDelay(base, max)500ms / 30sskyl's computed backoff
WithRetryAfterCap(d)5mA provider's own Retry-After hint
WithTimeout(d)10mA single attempt
WithHook(h)noneNothing — it registers an observer

Usage#

A production configuration

goCompiles
client := skyl.New(p,
	skyl.WithMaxRetries(5),
	skyl.WithRetryDelay(time.Second, time.Minute),
	skyl.WithRetryAfterCap(2*time.Minute),
	skyl.WithTimeout(90*time.Second),
	skyl.WithHook(telemetry.Hook),
)
client := skyl.New(p,
	skyl.WithMaxRetries(5),
	skyl.WithRetryDelay(time.Second, time.Minute),
	skyl.WithRetryAfterCap(2*time.Minute),
	skyl.WithTimeout(90*time.Second),
	skyl.WithHook(telemetry.Hook),
)

Reusable option sets

// Options are values, so a policy is just a slice.
func policy(env string) []skyl.Option {
	switch env {
	case "test":
		// Same retry count, negligible wall-clock.
		return []skyl.Option{
			skyl.WithMaxRetries(3),
			skyl.WithRetryDelay(time.Millisecond, 10*time.Millisecond),
			skyl.WithRetryAfterCap(50 * time.Millisecond),
		}
	default:
		return []skyl.Option{
			skyl.WithMaxRetries(4),
			skyl.WithTimeout(2 * time.Minute),
		}
	}
}

client := skyl.New(p, policy(os.Getenv("APP_ENV"))...)
// Options are values, so a policy is just a slice.
func policy(env string) []skyl.Option {
	switch env {
	case "test":
		// Same retry count, negligible wall-clock.
		return []skyl.Option{
			skyl.WithMaxRetries(3),
			skyl.WithRetryDelay(time.Millisecond, 10*time.Millisecond),
			skyl.WithRetryAfterCap(50 * time.Millisecond),
		}
	default:
		return []skyl.Option{
			skyl.WithMaxRetries(4),
			skyl.WithTimeout(2 * time.Minute),
		}
	}
}

client := skyl.New(p, policy(os.Getenv("APP_ENV"))...)

Writing your own option

goCompiles
// Option is an exported func type, so you can compose your own from the
// built-in ones — useful for encoding a house style once.
func WithHouseDefaults() skyl.Option {
	return func(c *skyl.Client) {
		skyl.WithMaxRetries(4)(c)
		skyl.WithTimeout(90 * time.Second)(c)
	}
}
// Option is an exported func type, so you can compose your own from the
// built-in ones — useful for encoding a house style once.
func WithHouseDefaults() skyl.Option {
	return func(c *skyl.Client) {
		skyl.WithMaxRetries(4)(c)
		skyl.WithTimeout(90 * time.Second)(c)
	}
}

Troubleshooting#

My option had no effect

Either the value was invalid and silently ignored — check for a negative or zero argument — or a later option of the same kind overrode it.

There is no WithHTTPClient

Correct: the HTTP client is a provider option, because the adapter performs the request. Use openai.WithHTTPClient(hc), gemini.WithHTTPClient(hc), and so on.

There is no WithBaseURL either

Same reason. A base URL identifies one vendor's host, so it belongs to the adapter: openai.WithBaseURL(...).

Edit this page on GitHub