store.go 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. // package store -- хранилище данных бота
  2. package store
  3. import (
  4. "fmt"
  5. "github.com/syndtr/goleveldb/leveldb"
  6. "github.com/syndtr/goleveldb/leveldb/util"
  7. "wartank/pkg/components/safebool"
  8. "wartank/pkg/types"
  9. )
  10. const (
  11. strStore = "store"
  12. )
  13. // Store -- хранилище данных
  14. type Store struct {
  15. app types.IServer
  16. db *leveldb.DB
  17. isWork *safebool.SafeBool
  18. }
  19. // NewStore - -возвращает новый объект хранилища
  20. func NewStore(app types.IServer) (*Store, error) {
  21. if app == nil {
  22. return nil, fmt.Errorf("NewStore(): IApp is nil")
  23. }
  24. sf := &Store{
  25. app: app,
  26. isWork: safebool.NewSafeBool(),
  27. }
  28. if err := sf.open(); err != nil {
  29. return nil, fmt.Errorf("NewStore(): in open store, err=%w", err)
  30. }
  31. sf.isWork.Set()
  32. go sf.close()
  33. sf.app.Wg().Add(strStore)
  34. sf.app.Slog().Infof("NewStore(): run")
  35. return sf, nil
  36. }
  37. // Открытие хранилища
  38. func (sf *Store) open() error {
  39. db, err := leveldb.OpenFile("store", nil)
  40. if err != nil {
  41. return fmt.Errorf("open(): in open store, err=%w", err)
  42. }
  43. sf.db = db
  44. return nil
  45. }
  46. // Get -- возвращает запись по ключу
  47. func (sf *Store) Get(key string) (string, error) {
  48. if !sf.isWork.Get() {
  49. return "", fmt.Errorf("Store.Get(): store is close")
  50. }
  51. binData, err := sf.db.Get([]byte(key), nil)
  52. if err != nil {
  53. return "", fmt.Errorf("Store.Get(): in get by key(%q), err=%w", key, err)
  54. }
  55. return string(binData), nil
  56. }
  57. // Put -- помещает запись по ключу
  58. func (sf *Store) Put(key string, val string) error {
  59. if !sf.isWork.Get() {
  60. return fmt.Errorf("Store.Put(): store is close")
  61. }
  62. if err := sf.db.Put([]byte(key), []byte(val), nil); err != nil {
  63. return fmt.Errorf("Store.Put(): in put key(%q), err=\n\t%w", key, err)
  64. }
  65. return nil
  66. }
  67. func (sf *Store) Find(prefix string) (map[string]string, error) {
  68. dictOut := make(map[string]string)
  69. iter := sf.db.NewIterator(&util.Range{Start: []byte(prefix)}, nil)
  70. for iter.Next() {
  71. key := iter.Key()
  72. val := iter.Value()
  73. dictOut[string(key)] = string(val)
  74. }
  75. iter.Release()
  76. err := iter.Error()
  77. if err != nil {
  78. return nil, fmt.Errorf("Store.Find(): in find by prefix(%q), err=\n\t%w", prefix, err)
  79. }
  80. return dictOut, nil
  81. }
  82. func (sf *Store) close() {
  83. <-sf.app.Done()
  84. if !sf.isWork.Get() {
  85. return
  86. }
  87. sf.app.Wg().Done(strStore)
  88. sf.isWork.Reset()
  89. sf.app.Slog().Infof("NewStore(): close")
  90. }