Documentation
¶
Overview ¶
Package tbd provides TBD, a value might be computed some time later.
A TBD *MUST* be "resolved" by a "resolver" or whoever use it might run into deadlock.
Index ¶
- func Err[T any](t TBD[T]) error
- func Value[T any](t TBD[T]) T
- type GeneralImpl
- type TBD
- func Bind[T any](v TBD[T], resolver task.Task) TBD[T]
- func Convert[S, D any](src TBD[S], f func(S) (D, error)) TBD[D]
- func Create[T any]() (TBD[T], func(T, error) error)
- func EzConvert[S, D any](s TBD[S], f func(S) D) TBD[D]
- func New[T any]() (TBD[T], func(T) error, func(error) error)
- func Reject[T any](e error) TBD[T]
- func Resolve[T any](v T) TBD[T]
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
Types ¶
type GeneralImpl ¶
type GeneralImpl[T any] struct { // contains filtered or unexported fields }
GeneralImpl is helper to write your own TBD implementation.
You *MUST NOT* use it directly as resolving it with Resolve(), Reject() or Determine() on a resolved GeneralImpl leads to panic, due to closing a closed channel. You have to ensure that it is not resolved multiple times, likely by protecting it with sync.Once. Take a look at source code of New, Create or forge.Generaotr.TBD for example.
func CreateImpl ¶
func CreateImpl[T any]() *GeneralImpl[T]
CreateImpl creates a GeneralImpl and initializes it.
You *MUST NOT* use it directly. See documentation of GeneralImpl for detail.
func (*GeneralImpl[T]) Determine ¶
func (i *GeneralImpl[T]) Determine(v T, e error) error
Determine tries to resolves it without validating if it is resolved.
Determining a resolved GeneralImpl leads to panic.
func (*GeneralImpl[T]) Get ¶
func (i *GeneralImpl[T]) Get(ctx context.Context) (ret T, err error)
Get implements TBD.
func (*GeneralImpl[T]) Reject ¶
func (i *GeneralImpl[T]) Reject(e error) error
Reject tries to resolves it without validating if it is resolved.
Rejecting a resolved GeneralImpl leads to panic.
func (*GeneralImpl[T]) Resolve ¶
func (i *GeneralImpl[T]) Resolve(v T) error
Resolve tries to resolves it without validating if it is resolved.
Resolving a resolved GeneralImpl leads to panic.
func (*GeneralImpl[T]) Resolved ¶
func (i *GeneralImpl[T]) Resolved() <-chan struct{}
Resolved implements TBD.
type TBD ¶
type TBD[T any] interface { // Indicates if it is resolved. Resolved() <-chan struct{} // Wait and get the value. Can be used as a generator. Get(context.Context) (T, error) }
TBD represents a value might be computed some time later.
It is a placeholder for the value. There must be a resolver who give it the result, no matter a value or an error. Once the result is provided, the channel returned by Resolved() is closed.
func Convert ¶
Convert creates a TBD that will be resolved by converting src to new value.
Returned TBD will be resolved when you get the value after src is resolved.
Improtant Note ¶
In general, chainning TBD (like Convert) is a bad idea: Returned TBD is double-locked: it self is locked and the src is also locked. The performance and memory usage is much more than using forge.Chain. You may write following code instead to get better performance:
forge.Convert(src.Get, f).TBD()
If f is simple and fast, you could use pure Generator:
forge.Convert(src.Get, f)
ONLY USE THIS IF f IS SIMPLE AND FAST, because code above calls f every time you get value from returned Generator. To fix this, use cached generator:
forge.Cache(forge.Convert(src.Get, f))
func New ¶
New creates a TBD and provides 2 functions to resolve it.
Example ¶
response, res, rej := New[*http.Response]()
resolver := task.Task(func(ctx context.Context) error {
req, err := http.NewRequestWithContext(ctx, "GET", "https://google.com", nil)
if err != nil {
return rej(err)
}
resp, err := http.DefaultClient.Do(req)
if err != nil {
return rej(err)
}
return res(resp)
})
saveToDB := func(ctx context.Context) error {
resp, err := response.Get(ctx)
if err != nil {
return err
}
// parse the response and save it to db
_ = resp
return nil
}
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt)
defer stop()
err := task.Iter(resolver, saveToDB).Run(ctx)
fmt.Print(err)