Skip to content

clientlifecycle

Build an expensive thing once, share it, and never cache the failure.

clientlifecycle holds one small state machine: the rule for turning a Builder[T] — anything expensive and failure-prone, typically a credential resolution — into a Resolver[T] that concurrent callers can share safely.

It exists because that rule was being written repeatedly across the estate, each copy subtly different and each one tested from scratch. It is written once here, raced once here, and depended on everywhere.

src := clientlifecycle.Memoised(func(ctx context.Context) (aws.Config, error) {
    return config.LoadDefaultConfig(ctx)
})

cfg, err := src.Get(ctx)   // first call resolves; the rest share the result

It costs nothing to depend on

This module has no third-party dependencies at all — not few, none. A test asserts it rather than leaving it to review, because every provider client module in the estate depends on this one, so anything arriving here is inherited everywhere.

Three strategies, and the choice is yours

Strategy Holds the value Take it when
Memoised forever the value refreshes itself, and you are content to hold it
PerCall never you decline to hold a credential longer than an operation needs
Invalidatable until told otherwise the value cannot renew itself, and building it is expensive

Which one to take is a property of your posture and your provider, not something this package decides for you. Choosing a strategy walks the three questions that settle it.

Start here

Where this comes from

The state machine is decision D-4 of org spec 0002; this module is P-4 of org spec 0003, and the invalidatable strategy is P-16.