165 lines
4.1 KiB
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
|
|
}
|