Zippytal-Node/zoneChatTracking.go

165 lines
4.1 KiB
Go

package localserver
import (
"encoding/binary"
"os"
"path/filepath"
"sync"
"github.com/dgraph-io/badger/v3"
)
type ZoneChatTrackingDB struct {
ZoneID string
db func(cb func(*badger.DB) (err error)) (err error)
lock *sync.RWMutex
}
func NewZoneChatTracking(zoneId, chatId string, members ...string) (*ZoneChatTrackingDB, error) {
if _, dirErr := os.ReadDir(filepath.Join(dataPath, "data", "zones", zoneId, "chats", chatId, "__tracking__")); os.IsNotExist(dirErr) {
_ = os.MkdirAll(filepath.Join(dataPath, "data", "zones", zoneId, "chats", chatId, "__tracking__"), 0700)
}
db := func(f func(*badger.DB) (err error)) (err error) {
db, err := badger.Open(badger.DefaultOptions(filepath.Join(dataPath, "data", "zones", zoneId, "chats", chatId, "__tracking__")).WithLogger(dbLogger))
if err != nil {
return
}
defer db.Close()
err = f(db)
return
}
lock := new(sync.RWMutex)
if err := db(func(d *badger.DB) (err error) {
err = d.Update(func(txn *badger.Txn) error {
b := make([]byte, bufferSize)
binary.BigEndian.PutUint64(b, 0)
for _, member := range members {
if _, rerr := txn.Get([]byte(member)); rerr == badger.ErrKeyNotFound {
_ = txn.Set([]byte(member), b)
} else if rerr != nil {
return rerr
}
}
return nil
})
if err != nil {
return
}
return
}); err != nil {
return nil, err
}
return &ZoneChatTrackingDB{zoneId, db, lock}, nil
}
func (zctdb *ZoneChatTrackingDB) Initialize(lastIndex uint64, users ...string) (err error) {
for _, user := range users {
if err = zctdb.SetUserLastIndex(user, lastIndex); err != nil {
return
}
}
return
}
func (zctdb *ZoneChatTrackingDB) updateDBCallbackFolder(newChatId string) {
db := func(f func(*badger.DB) (err error)) (err error) {
db, err := badger.Open(badger.DefaultOptions(filepath.Join(dataPath, "data", "zones", zctdb.ZoneID, "chats", newChatId, "__tracking__")).WithLogger(dbLogger))
if err != nil {
return
}
defer db.Close()
err = f(db)
return
}
zctdb.db = db
}
func (zctdb *ZoneChatTrackingDB) RevertTrackingLastIndex(lastIndex uint64) (err error) {
zctdb.lock.Lock()
defer zctdb.lock.Unlock()
err = zctdb.db(func(d *badger.DB) (err error) {
keys := [][]byte{}
err = d.View(func(txn *badger.Txn) error {
opt := badger.DefaultIteratorOptions
it := txn.NewIterator(opt)
defer it.Close()
for it.Rewind(); it.Valid(); it.Next() {
item := it.Item()
if err = item.Value(func(val []byte) error {
li := binary.BigEndian.Uint64(val)
if li >= lastIndex {
keys = append(keys, item.Key())
}
return nil
}); err != nil {
return err
}
}
return nil
})
if err != nil {
return
}
err = d.Update(func(txn *badger.Txn) error {
for _, key := range keys {
b := make([]byte, bufferSize)
binary.BigEndian.PutUint64(b, lastIndex)
if updateErr := txn.Set(key, b); updateErr != nil {
return updateErr
}
}
return nil
})
return
})
return
}
func (zctdb *ZoneChatTrackingDB) SetUserLastIndex(userId string, lastIndex uint64) (err error) {
zctdb.lock.Lock()
defer zctdb.lock.Unlock()
err = zctdb.db(func(d *badger.DB) (err error) {
err = d.Update(func(txn *badger.Txn) error {
b := make([]byte, bufferSize)
binary.BigEndian.PutUint64(b, lastIndex)
updateErr := txn.Set([]byte(userId), b)
return updateErr
})
return
})
return
}
func (zctdb *ZoneChatTrackingDB) GetUserLastIndex(userId string) (index uint, err error) {
zctdb.lock.Lock()
defer zctdb.lock.Unlock()
err = zctdb.db(func(d *badger.DB) (err error) {
err = d.Update(func(txn *badger.Txn) error {
item, rerr := txn.Get([]byte(userId))
if rerr != nil {
return rerr
}
_ = item.Value(func(val []byte) error {
index = uint(binary.BigEndian.Uint64(val))
return nil
})
return nil
})
return
})
return
}
func (zctdb *ZoneChatTrackingDB) DeleteUserTracking(userId string) (err error) {
zctdb.lock.Lock()
defer zctdb.lock.Unlock()
err = zctdb.db(func(d *badger.DB) (err error) {
err = d.Update(func(txn *badger.Txn) error {
updateErr := txn.Delete([]byte(userId))
return updateErr
})
return
})
return
}