// package store -- хранилище данных бота package store import ( "fmt" "github.com/syndtr/goleveldb/leveldb" "github.com/syndtr/goleveldb/leveldb/util" "wartank/pkg/components/safebool" "wartank/pkg/types" ) const ( strStore = "store" ) // Store -- хранилище данных type Store struct { app types.ИСервер db *leveldb.DB isWork *safebool.SafeBool } // NewStore - -возвращает новый объект хранилища func NewStore(app types.ИСервер) (*Store, error) { if app == nil { return nil, fmt.Errorf("NewStore(): IApp is nil") } sf := &Store{ app: app, isWork: safebool.NewSafeBool(), } if err := sf.open(); err != nil { return nil, fmt.Errorf("NewStore(): in open store, err=%w", err) } sf.isWork.Уст() go sf.close() sf.app.Wg().Add(strStore) sf.app.Slog().Infof("NewStore(): run") return sf, nil } // Открытие хранилища func (sf *Store) open() error { db, err := leveldb.OpenFile("store", nil) if err != nil { return fmt.Errorf("open(): in open store, err=%w", err) } sf.db = db return nil } // Get -- возвращает запись по ключу func (sf *Store) Get(key string) (string, error) { if !sf.isWork.Получ() { return "", fmt.Errorf("Store.Get(): store is close") } binData, err := sf.db.Get([]byte(key), nil) if err != nil { return "", fmt.Errorf("Store.Get(): in get by key(%q), err=%w", key, err) } return string(binData), nil } // Put -- помещает запись по ключу func (sf *Store) Put(key string, val string) error { if !sf.isWork.Получ() { return fmt.Errorf("Store.Put(): store is close") } if err := sf.db.Put([]byte(key), []byte(val), nil); err != nil { return fmt.Errorf("Store.Put(): in put key(%q), err=\n\t%w", key, err) } return nil } func (sf *Store) Find(prefix string) (map[string]string, error) { dictOut := make(map[string]string) iter := sf.db.NewIterator(&util.Range{Start: []byte(prefix)}, nil) for iter.Next() { key := iter.Key() val := iter.Value() dictOut[string(key)] = string(val) } iter.Release() err := iter.Error() if err != nil { return nil, fmt.Errorf("Store.Find(): in find by prefix(%q), err=\n\t%w", prefix, err) } return dictOut, nil } func (sf *Store) close() { <-sf.app.Done() if !sf.isWork.Получ() { return } sf.app.Wg().Done(strStore) sf.isWork.Сброс() sf.app.Slog().Infof("NewStore(): close") }