149 lines
3.2 KiB
Go
149 lines
3.2 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) 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
|
|
}
|
|
|
|
log := zerolog.New(zerolog.NewConsoleWriter(tsSet)).With().Timestamp().Str("app", "converter").Logger()
|
|
|
|
return log, 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]
|