163 lines
3.4 KiB
Go
163 lines
3.4 KiB
Go
package components
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
"time"
|
|
|
|
"git.loyso.art/frx/eway/internal/config"
|
|
"git.loyso.art/frx/eway/internal/interconnect/eway"
|
|
"git.loyso.art/frx/eway/internal/storage"
|
|
xbadger "git.loyso.art/frx/eway/internal/storage/badger"
|
|
|
|
"github.com/BurntSushi/toml"
|
|
"github.com/dgraph-io/badger/v4"
|
|
"github.com/rs/zerolog"
|
|
"github.com/samber/do"
|
|
)
|
|
|
|
// Yeah, singleton is not good UNLESS you're really lazy
|
|
var diInjector *do.Injector
|
|
|
|
func GetEwayClient() (eway.Client, error) {
|
|
return do.Invoke[eway.Client](diInjector)
|
|
}
|
|
|
|
func GetRepository() (storage.Repository, error) {
|
|
adapter, err := do.Invoke[*storageRepositoryAdapter](diInjector)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return adapter.entity, nil
|
|
}
|
|
|
|
func GetLogger() (zerolog.Logger, error) {
|
|
return do.Invoke[zerolog.Logger](diInjector)
|
|
}
|
|
|
|
func SetupDI(ctx context.Context, cfgpath string, verbose bool, logAsJSON bool) error {
|
|
cfg, err := parseSettings(cfgpath)
|
|
if err != nil {
|
|
// if no settings provided allow cli to run without them.
|
|
if errors.Is(err, os.ErrNotExist) {
|
|
return nil
|
|
}
|
|
|
|
return err
|
|
}
|
|
|
|
diInjector = do.New()
|
|
|
|
do.Provide(diInjector, func(i *do.Injector) (zerolog.Logger, error) {
|
|
tsSet := func(wr *zerolog.ConsoleWriter) {
|
|
wr.TimeFormat = time.RFC3339
|
|
}
|
|
|
|
var writer io.Writer = zerolog.NewConsoleWriter(tsSet)
|
|
if logAsJSON {
|
|
writer = os.Stdout
|
|
}
|
|
|
|
log := zerolog.
|
|
New(writer).
|
|
With().
|
|
Timestamp().
|
|
Str("app", "converter").
|
|
Logger()
|
|
if verbose {
|
|
|
|
return log.Level(zerolog.DebugLevel), nil
|
|
}
|
|
|
|
return log.Level(zerolog.InfoLevel), nil
|
|
})
|
|
|
|
do.Provide[eway.Client](diInjector, func(i *do.Injector) (eway.Client, error) {
|
|
log, err := GetLogger()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("getting logger: %w", err)
|
|
}
|
|
|
|
client, err := eway.New(ctx, eway.Config(cfg.Eway), log)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("making new eway client: %w", err)
|
|
}
|
|
|
|
return client, nil
|
|
})
|
|
|
|
do.Provide[*badgerDBAdapter](diInjector, func(i *do.Injector) (*badgerDBAdapter, error) {
|
|
db, err := xbadger.Open(ctx, cfg.Badger.Dir, cfg.Badger.Debug, zerolog.Nop())
|
|
if err != nil {
|
|
return nil, fmt.Errorf("getting db: %w", err)
|
|
}
|
|
|
|
out := &badgerDBAdapter{entity: db}
|
|
return out, nil
|
|
})
|
|
|
|
do.Provide[*storageRepositoryAdapter](diInjector, func(i *do.Injector) (*storageRepositoryAdapter, error) {
|
|
db, err := getDB()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
client, err := xbadger.NewClient(db)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("getting badger client: %w", err)
|
|
}
|
|
|
|
out := &storageRepositoryAdapter{entity: client}
|
|
return out, nil
|
|
})
|
|
|
|
return nil
|
|
}
|
|
|
|
func Shutdown() error {
|
|
if diInjector == nil {
|
|
return nil
|
|
}
|
|
|
|
return diInjector.Shutdown()
|
|
}
|
|
|
|
func getDB() (*badger.DB, error) {
|
|
adapter, err := do.Invoke[*badgerDBAdapter](diInjector)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return adapter.entity, nil
|
|
}
|
|
|
|
type settings struct {
|
|
Badger config.Badger `toml:"badger"`
|
|
Log config.Log `toml:"log"`
|
|
Eway config.Eway `toml:"eway"`
|
|
}
|
|
|
|
func parseSettings(cfgpath string) (cfg settings, err error) {
|
|
_, err = toml.DecodeFile(cfgpath, &cfg)
|
|
if err != nil {
|
|
return cfg, fmt.Errorf("parsing file: %w", err)
|
|
}
|
|
|
|
return cfg, nil
|
|
}
|
|
|
|
type entityCloserAdapter[T io.Closer] struct {
|
|
entity T
|
|
}
|
|
|
|
func (a entityCloserAdapter[T]) Shutdown() error {
|
|
return a.entity.Close()
|
|
}
|
|
|
|
type storageRepositoryAdapter entityCloserAdapter[storage.Repository]
|
|
type badgerDBAdapter entityCloserAdapter[*badger.DB]
|