1
0
mirror of https://github.com/MontFerret/ferret.git synced 2025-02-01 13:07:49 +02:00

118 lines
2.3 KiB
Go
Raw Normal View History

2018-09-26 22:03:06 -04:00
package common
import (
"context"
2018-10-14 20:06:27 +03:00
"sync"
2018-09-26 22:03:06 -04:00
"github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values"
)
type (
// LazyValueFactory represents a value initializer
LazyValueFactory func(ctx context.Context) (core.Value, error)
2018-09-26 22:03:06 -04:00
// LazyValue represents a value with late initialization
2018-09-26 22:03:06 -04:00
LazyValue struct {
mu sync.Mutex
factory LazyValueFactory
2018-09-26 22:03:06 -04:00
ready bool
value core.Value
err error
}
)
func NewLazyValue(factory LazyValueFactory) *LazyValue {
2018-09-26 22:03:06 -04:00
lz := new(LazyValue)
lz.ready = false
lz.factory = factory
lz.value = values.None
return lz
}
2018-10-14 20:06:27 +03:00
// Ready indicates whether the value is ready.
// @returns (Boolean) - Boolean value indicating whether the value is ready.
2018-09-27 00:26:56 -04:00
func (lv *LazyValue) Ready() bool {
lv.mu.Lock()
defer lv.mu.Unlock()
2018-09-27 00:26:56 -04:00
return lv.ready
}
2018-10-14 20:06:27 +03:00
// Read returns an underlying value.
// Not thread safe. Should not mutated.
// @returns (Value) - Underlying value if successfully loaded, otherwise error
func (lv *LazyValue) Read(ctx context.Context) (core.Value, error) {
lv.mu.Lock()
defer lv.mu.Unlock()
2018-09-26 22:03:06 -04:00
if !lv.ready {
lv.load(ctx)
2018-09-26 22:03:06 -04:00
}
return lv.value, lv.err
}
// Mutate safely mutates an underlying value.
2018-10-14 20:06:27 +03:00
// Loads a value if it's not ready.
// Thread safe.
func (lv *LazyValue) Mutate(ctx context.Context, mutator func(v core.Value, err error)) {
lv.mu.Lock()
defer lv.mu.Unlock()
if !lv.ready {
lv.load(ctx)
}
mutator(lv.value, lv.err)
}
// MutateIfReady safely mutates an underlying value only if it's ready.
func (lv *LazyValue) MutateIfReady(mutator func(v core.Value, err error)) {
lv.mu.Lock()
defer lv.mu.Unlock()
if lv.ready {
mutator(lv.value, lv.err)
}
}
// Reload resets the storage and loads data.
func (lv *LazyValue) Reload(ctx context.Context) {
lv.mu.Lock()
defer lv.mu.Unlock()
lv.resetInternal()
lv.load(ctx)
}
2018-10-14 20:06:27 +03:00
// Reset resets the storage.
// Next call of Read will trigger the factory function again.
2018-09-26 22:03:06 -04:00
func (lv *LazyValue) Reset() {
lv.mu.Lock()
defer lv.mu.Unlock()
2018-09-26 22:03:06 -04:00
lv.resetInternal()
}
func (lv *LazyValue) resetInternal() {
2018-09-26 22:03:06 -04:00
lv.ready = false
lv.value = values.None
lv.err = nil
}
func (lv *LazyValue) load(ctx context.Context) {
val, err := lv.factory(ctx)
if err == nil {
lv.value = val
lv.err = nil
} else {
lv.value = values.None
lv.err = err
}
lv.ready = true
}