Refactor: remove pkg mem cache
This commit is contained in:
@ -5,10 +5,8 @@ import (
|
||||
"crypto/hmac"
|
||||
"crypto/sha256"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"gralias/models"
|
||||
"gralias/pkg/cache"
|
||||
"gralias/utils"
|
||||
"html/template"
|
||||
"net/http"
|
||||
@ -187,32 +185,5 @@ func makeCookie(username string, remote string) (*http.Cookie, error) {
|
||||
if err := repo.SessionCreate(context.Background(), session); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// set user in session
|
||||
if err := cacheSetSession(sessionToken, session); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return cookie, nil
|
||||
}
|
||||
|
||||
//nolint: unused
|
||||
func cacheGetSession(key string) (*models.Session, error) {
|
||||
userSessionB, err := cache.MemCache.Get(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var us *models.Session
|
||||
if err := json.Unmarshal(userSessionB, &us); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return us, nil
|
||||
}
|
||||
|
||||
func cacheSetSession(key string, session *models.Session) error {
|
||||
sesb, err := json.Marshal(session)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cache.MemCache.Set(key, sesb)
|
||||
cache.MemCache.Expire(key, cfg.SessionLifetime)
|
||||
return nil
|
||||
}
|
||||
|
@ -6,7 +6,6 @@ import (
|
||||
"crypto/sha256"
|
||||
"encoding/base64"
|
||||
"gralias/models"
|
||||
"gralias/pkg/cache"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
@ -71,7 +70,8 @@ func GetSession(next http.Handler) http.Handler {
|
||||
return
|
||||
}
|
||||
if userSession.IsExpired() {
|
||||
cache.MemCache.RemoveKey(sessionToken)
|
||||
repo.SessionDelete(r.Context(), sessionToken)
|
||||
// cache.MemCache.RemoveKey(sessionToken)
|
||||
msg := "session is expired"
|
||||
log.Debug(msg, "error", err, "token", sessionToken)
|
||||
next.ServeHTTP(w, r)
|
||||
@ -81,13 +81,13 @@ func GetSession(next http.Handler) http.Handler {
|
||||
models.CtxUsernameKey, userSession.Username)
|
||||
ctx = context.WithValue(ctx,
|
||||
models.CtxSessionKey, userSession)
|
||||
if err := cacheSetSession(sessionToken,
|
||||
userSession); err != nil {
|
||||
msg := "failed to marshal user session"
|
||||
log.Warn(msg, "error", err)
|
||||
next.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
// if err := cacheSetSession(sessionToken,
|
||||
// userSession); err != nil {
|
||||
// msg := "failed to marshal user session"
|
||||
// log.Warn(msg, "error", err)
|
||||
// next.ServeHTTP(w, r)
|
||||
// return
|
||||
// }
|
||||
next.ServeHTTP(w, r.WithContext(ctx))
|
||||
})
|
||||
}
|
||||
|
@ -1,13 +1,13 @@
|
||||
package llmapi
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"gralias/broker"
|
||||
"gralias/config"
|
||||
"gralias/models"
|
||||
"gralias/pkg/cache"
|
||||
"gralias/repos"
|
||||
"io"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
@ -19,6 +19,7 @@ import (
|
||||
|
||||
var (
|
||||
// botname -> channel
|
||||
repo = repos.NewRepoProvider("sqlite3://../gralias.db")
|
||||
SignalChanMap = make(map[string]chan bool)
|
||||
DoneChanMap = make(map[string]chan bool)
|
||||
// got prompt: control character (\\u0000-\\u001F) found while parsing a string at line 4 column 0
|
||||
@ -49,7 +50,7 @@ func convertToSliceOfStrings(value any) ([]string, error) {
|
||||
}
|
||||
}
|
||||
|
||||
//nolint: unused
|
||||
// nolint: unused
|
||||
func (b *Bot) checkGuesses(tempMap map[string]any, room *models.Room) error {
|
||||
guesses, err := convertToSliceOfStrings(tempMap["guesses"])
|
||||
if err != nil {
|
||||
@ -162,7 +163,8 @@ func (b *Bot) BotMove() {
|
||||
// botJournalName := models.NotifyJournalPrefix + b.RoomID
|
||||
b.log.Debug("got signal", "bot-team", b.Team, "bot-role", b.Role)
|
||||
// get room cards and actions
|
||||
room, err := getRoomByID(b.RoomID)
|
||||
// room, err := getRoomByID(b.RoomID)
|
||||
room, err := repo.RoomGetExtended(context.Background(), b.RoomID)
|
||||
if err != nil {
|
||||
b.log.Error("bot loop", "error", err)
|
||||
return
|
||||
@ -316,7 +318,8 @@ func NewBot(role, team, name, roomID string, cfg *config.Config, recovery bool)
|
||||
bot.LLMParser = NewOpenRouterParser(bot.log)
|
||||
}
|
||||
// add to room
|
||||
room, err := getRoomByID(bot.RoomID)
|
||||
// room, err := getRoomByID(bot.RoomID)
|
||||
room, err := repo.RoomGetExtended(context.Background(), bot.RoomID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -371,35 +374,39 @@ func NewBot(role, team, name, roomID string, cfg *config.Config, recovery bool)
|
||||
}
|
||||
|
||||
func saveBot(bot *Bot) error {
|
||||
key := models.CacheBotPredix + bot.RoomID + bot.BotName
|
||||
data, err := json.Marshal(bot)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cache.MemCache.Set(key, data)
|
||||
return nil
|
||||
// key := models.CacheBotPredix + bot.RoomID + bot.BotName
|
||||
// data, err := json.Marshal(bot)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// // }
|
||||
// cache.MemCache.Set(key, data)
|
||||
botPlayer := bot.ToPlayer()
|
||||
return repo.PlayerAdd(context.Background(), botPlayer)
|
||||
}
|
||||
|
||||
func getRoomByID(roomID string) (*models.Room, error) {
|
||||
roomBytes, err := cache.MemCache.Get(models.CacheRoomPrefix + roomID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resp := &models.Room{}
|
||||
if err := json.Unmarshal(roomBytes, &resp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
// func getRoomByID(roomID string) (*models.Room, error) {
|
||||
// roomBytes, err := cache.MemCache.Get(models.CacheRoomPrefix + roomID)
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
// resp := &models.Room{}
|
||||
// if err := json.Unmarshal(roomBytes, &resp); err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
// return resp, nil
|
||||
// }
|
||||
|
||||
func saveRoom(room *models.Room) error {
|
||||
key := models.CacheRoomPrefix + room.ID
|
||||
data, err := json.Marshal(room)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cache.MemCache.Set(key, data)
|
||||
return nil
|
||||
// key := models.CacheRoomPrefix + room.ID
|
||||
// data, err := json.Marshal(room)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// cache.MemCache.Set(key, data)
|
||||
// ------------
|
||||
// probably need to update other tables
|
||||
// like word_cards or marks;
|
||||
return repo.RoomUpdate(context.Background(), room)
|
||||
}
|
||||
|
||||
func (b *Bot) BuildSimpleGuesserPrompt(room *models.Room) string {
|
||||
|
@ -2,6 +2,7 @@ package llmapi
|
||||
|
||||
import (
|
||||
"gralias/config"
|
||||
"gralias/models"
|
||||
"log/slog"
|
||||
)
|
||||
|
||||
@ -84,3 +85,13 @@ type Bot struct {
|
||||
// SignalsCh chan bool
|
||||
// DoneCh chan bool
|
||||
}
|
||||
|
||||
func (b *Bot) ToPlayer() *models.Player {
|
||||
return &models.Player{
|
||||
Role: models.StrToUserRole(b.Role),
|
||||
Team: models.StrToUserTeam(b.Team),
|
||||
RoomID: &b.RoomID,
|
||||
Username: b.BotName,
|
||||
IsBot: true,
|
||||
}
|
||||
}
|
||||
|
2
main.go
2
main.go
@ -4,7 +4,6 @@ import (
|
||||
"context"
|
||||
"gralias/config"
|
||||
"gralias/handlers"
|
||||
"gralias/pkg/cache"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"os"
|
||||
@ -76,5 +75,4 @@ func main() {
|
||||
if err := server.Shutdown(ctx); err != nil {
|
||||
slog.Error("server shutdown failed", "error", err)
|
||||
}
|
||||
cache.MemCache.BackupNow()
|
||||
}
|
||||
|
146
pkg/cache/impl.go
vendored
146
pkg/cache/impl.go
vendored
@ -1,146 +0,0 @@
|
||||
package cache
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"os"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
const storeFileName = "store.json"
|
||||
|
||||
// var MemCache Cache
|
||||
var (
|
||||
MemCache *MemoryCache
|
||||
)
|
||||
|
||||
func readJSON(fileName string) (map[string][]byte, error) {
|
||||
data := make(map[string][]byte)
|
||||
file, err := os.Open(fileName)
|
||||
if err != nil {
|
||||
return data, err
|
||||
}
|
||||
defer file.Close()
|
||||
decoder := json.NewDecoder(file)
|
||||
if err := decoder.Decode(&data); err != nil {
|
||||
return data, err
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
data, err := readJSON(storeFileName)
|
||||
if err != nil {
|
||||
slog.Error("failed to load store from file")
|
||||
}
|
||||
MemCache = &MemoryCache{
|
||||
data: data,
|
||||
timeMap: make(map[string]time.Time),
|
||||
lock: &sync.RWMutex{},
|
||||
}
|
||||
MemCache.StartExpiryRoutine(time.Minute)
|
||||
MemCache.StartBackupRoutine(time.Minute)
|
||||
}
|
||||
|
||||
type MemoryCache struct {
|
||||
data map[string][]byte
|
||||
timeMap map[string]time.Time
|
||||
lock *sync.RWMutex
|
||||
}
|
||||
|
||||
// Get a value by key from the cache
|
||||
func (mc *MemoryCache) Get(key string) (value []byte, err error) {
|
||||
var ok bool
|
||||
mc.lock.RLock()
|
||||
if value, ok = mc.data[key]; !ok {
|
||||
err = fmt.Errorf("not found data in mc for the key: %v", key)
|
||||
}
|
||||
mc.lock.RUnlock()
|
||||
return value, err
|
||||
}
|
||||
|
||||
// Update a single value in the cache
|
||||
func (mc *MemoryCache) Set(key string, value []byte) {
|
||||
// no async writing
|
||||
mc.lock.Lock()
|
||||
mc.data[key] = value
|
||||
mc.lock.Unlock()
|
||||
}
|
||||
|
||||
func (mc *MemoryCache) Expire(key string, exp int64) {
|
||||
mc.lock.RLock()
|
||||
mc.timeMap[key] = time.Now().Add(time.Duration(exp) * time.Second)
|
||||
mc.lock.RUnlock()
|
||||
}
|
||||
|
||||
func (mc *MemoryCache) GetAll() (resp map[string][]byte) {
|
||||
resp = make(map[string][]byte)
|
||||
mc.lock.RLock()
|
||||
for k, v := range mc.data {
|
||||
resp[k] = v
|
||||
}
|
||||
mc.lock.RUnlock()
|
||||
return
|
||||
}
|
||||
|
||||
func (mc *MemoryCache) GetAllTime() (resp map[string]time.Time) {
|
||||
resp = make(map[string]time.Time)
|
||||
mc.lock.RLock()
|
||||
for k, v := range mc.timeMap {
|
||||
resp[k] = v
|
||||
}
|
||||
mc.lock.RUnlock()
|
||||
return
|
||||
}
|
||||
|
||||
func (mc *MemoryCache) RemoveKey(key string) {
|
||||
mc.lock.RLock()
|
||||
delete(mc.data, key)
|
||||
delete(mc.timeMap, key)
|
||||
mc.lock.RUnlock()
|
||||
}
|
||||
|
||||
func (mc *MemoryCache) BackupNow() {
|
||||
data := mc.GetAll()
|
||||
jsonString, err := json.Marshal(data)
|
||||
if err != nil {
|
||||
slog.Warn("immediate backup failed to marshal", "err", err)
|
||||
return
|
||||
}
|
||||
err = os.WriteFile(storeFileName, jsonString, os.ModePerm)
|
||||
if err != nil {
|
||||
slog.Warn("immediate backup failed to write", "err", err)
|
||||
}
|
||||
}
|
||||
|
||||
func (mc *MemoryCache) StartExpiryRoutine(n time.Duration) {
|
||||
ticker := time.NewTicker(n)
|
||||
go func() {
|
||||
for {
|
||||
<-ticker.C
|
||||
// get all
|
||||
timeData := mc.GetAllTime()
|
||||
// check time
|
||||
currentTS := time.Now()
|
||||
for k, ts := range timeData {
|
||||
if ts.Before(currentTS) {
|
||||
// delete exp keys
|
||||
mc.RemoveKey(k)
|
||||
slog.Debug("remove by expiry", "key", k)
|
||||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
func (mc *MemoryCache) StartBackupRoutine(n time.Duration) {
|
||||
ticker := time.NewTicker(n)
|
||||
go func() {
|
||||
for {
|
||||
<-ticker.C
|
||||
mc.BackupNow()
|
||||
}
|
||||
}()
|
||||
}
|
9
pkg/cache/main.go
vendored
9
pkg/cache/main.go
vendored
@ -1,9 +0,0 @@
|
||||
package cache
|
||||
|
||||
type Cache interface {
|
||||
Get(key string) ([]byte, error)
|
||||
Set(key string, value []byte)
|
||||
Expire(key string, exp int64)
|
||||
GetAll() (resp map[string][]byte)
|
||||
RemoveKey(key string)
|
||||
}
|
@ -84,6 +84,9 @@ func (p *RepoProvider) RoomGetExtended(ctx context.Context, id string) (*models.
|
||||
}
|
||||
room.RedTeam.Color = string(models.UserTeamRed)
|
||||
room.BlueTeam.Color = string(models.UserTeamBlue)
|
||||
if room.BotMap == nil {
|
||||
room.BotMap = make(map[string]models.BotPlayer)
|
||||
}
|
||||
for _, player := range players {
|
||||
if player.Team == models.UserTeamRed {
|
||||
if player.Role == models.UserRoleMime {
|
||||
@ -99,9 +102,6 @@ func (p *RepoProvider) RoomGetExtended(ctx context.Context, id string) (*models.
|
||||
}
|
||||
}
|
||||
if player.IsBot {
|
||||
if room.BotMap == nil {
|
||||
room.BotMap = make(map[string]models.BotPlayer)
|
||||
}
|
||||
room.BotMap[player.Username] = models.BotPlayer{
|
||||
Role: player.Role,
|
||||
Team: player.Team,
|
||||
|
Reference in New Issue
Block a user