mirror of
https://github.com/hanzo-fi/stack.git
synced 2026-10-30 20:34:43 +00:00
136 lines
3.1 KiB
Go
136 lines
3.1 KiB
Go
package engine
|
|
|
|
import (
|
|
"context"
|
|
"sync"
|
|
|
|
"github.com/pkg/errors"
|
|
|
|
"github.com/formancehq/ledger/internal/storage/ledgerstore"
|
|
|
|
"github.com/ThreeDotsLabs/watermill/message"
|
|
"github.com/formancehq/ledger/internal/engine/command"
|
|
"github.com/formancehq/ledger/internal/opentelemetry/metrics"
|
|
"github.com/formancehq/ledger/internal/storage/driver"
|
|
"github.com/formancehq/stack/libs/go-libs/logging"
|
|
"github.com/sirupsen/logrus"
|
|
)
|
|
|
|
type option func(r *Resolver)
|
|
|
|
func WithMessagePublisher(publisher message.Publisher) option {
|
|
return func(r *Resolver) {
|
|
r.publisher = publisher
|
|
}
|
|
}
|
|
|
|
func WithMetricsRegistry(registry metrics.GlobalRegistry) option {
|
|
return func(r *Resolver) {
|
|
r.metricsRegistry = registry
|
|
}
|
|
}
|
|
|
|
func WithCompiler(compiler *command.Compiler) option {
|
|
return func(r *Resolver) {
|
|
r.compiler = compiler
|
|
}
|
|
}
|
|
|
|
func WithLogger(logger logging.Logger) option {
|
|
return func(r *Resolver) {
|
|
r.logger = logger
|
|
}
|
|
}
|
|
|
|
var defaultOptions = []option{
|
|
WithMetricsRegistry(metrics.NewNoOpRegistry()),
|
|
WithCompiler(command.NewCompiler(1024)),
|
|
WithLogger(logging.NewLogrus(logrus.New())),
|
|
}
|
|
|
|
type Resolver struct {
|
|
storageDriver *driver.Driver
|
|
lock sync.RWMutex
|
|
metricsRegistry metrics.GlobalRegistry
|
|
//TODO(gfyrag): add a routine to clean old ledger
|
|
ledgers map[string]*Ledger
|
|
compiler *command.Compiler
|
|
logger logging.Logger
|
|
publisher message.Publisher
|
|
}
|
|
|
|
func NewResolver(storageDriver *driver.Driver, options ...option) *Resolver {
|
|
r := &Resolver{
|
|
storageDriver: storageDriver,
|
|
ledgers: map[string]*Ledger{},
|
|
}
|
|
for _, opt := range append(defaultOptions, options...) {
|
|
opt(r)
|
|
}
|
|
|
|
return r
|
|
}
|
|
|
|
func (r *Resolver) startLedgerUsingStore(ctx context.Context, name string, store *ledgerstore.Store) *Ledger {
|
|
ledger := New(store, r.publisher, r.compiler)
|
|
ledger.Start(logging.ContextWithLogger(context.Background(), r.logger))
|
|
r.ledgers[name] = ledger
|
|
r.metricsRegistry.ActiveLedgers().Add(ctx, +1)
|
|
|
|
return ledger
|
|
}
|
|
|
|
func (r *Resolver) GetLedger(ctx context.Context, name string) (*Ledger, error) {
|
|
if name == "" {
|
|
return nil, errors.New("empty name")
|
|
}
|
|
r.lock.RLock()
|
|
ledger, ok := r.ledgers[name]
|
|
r.lock.RUnlock()
|
|
|
|
if !ok {
|
|
r.lock.Lock()
|
|
defer r.lock.Unlock()
|
|
|
|
ledger, ok = r.ledgers[name]
|
|
if ok {
|
|
return ledger, nil
|
|
}
|
|
|
|
store, err := r.storageDriver.GetLedgerStore(ctx, name)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
ledger = r.startLedgerUsingStore(ctx, name, store)
|
|
}
|
|
|
|
return ledger, nil
|
|
}
|
|
|
|
func (r *Resolver) CreateLedger(ctx context.Context, name string, configuration driver.LedgerConfiguration) (*Ledger, error) {
|
|
r.lock.Lock()
|
|
defer r.lock.Unlock()
|
|
|
|
store, err := r.storageDriver.CreateLedgerStore(ctx, name, configuration)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return r.startLedgerUsingStore(ctx, name, store), nil
|
|
}
|
|
|
|
func (r *Resolver) CloseLedgers(ctx context.Context) error {
|
|
r.logger.Info("Close all ledgers")
|
|
defer func() {
|
|
r.logger.Info("All ledgers closed")
|
|
}()
|
|
for name, ledger := range r.ledgers {
|
|
r.logger.Infof("Close ledger %s", name)
|
|
ledger.Close(logging.ContextWithLogger(ctx, r.logger.WithField("ledger", name)))
|
|
delete(r.ledgers, name)
|
|
}
|
|
|
|
return nil
|
|
}
|