htmgo/examples/sse-with-state/state/state.go
2024-10-08 12:48:28 -05:00

67 lines
1.4 KiB
Go

package state
import (
"github.com/google/uuid"
"github.com/maddalax/htmgo/framework/h"
"github.com/puzpuzpuz/xsync/v3"
"net/http"
)
type SessionId string
var cache = xsync.NewMapOf[SessionId, *xsync.MapOf[string, any]]()
type State struct {
SessionId SessionId
}
func NewState(ctx *h.RequestContext) *State {
id := GetSessionId(ctx)
cache.Store(id, xsync.NewMapOf[string, any]())
return &State{
SessionId: id,
}
}
func GetSessionId(ctx *h.RequestContext) SessionId {
stateCookie, err := ctx.Request.Cookie("state")
sessionId := ""
if err == nil {
sessionId = stateCookie.Value
} else {
sessionId = uuid.NewString()
}
c := http.Cookie{
Name: "state",
Value: sessionId,
}
ctx.Response.Header().Set("Set-Cookie", c.String())
return SessionId(sessionId)
}
func Update[T any](sessionId SessionId, key string, compute func(prev T) T) T {
actual := Get[T](sessionId, key, *new(T))
next := compute(actual)
Set(sessionId, key, next)
return next
}
func Get[T any](sessionId SessionId, key string, fallback T) T {
actual, _ := cache.LoadOrCompute(sessionId, func() *xsync.MapOf[string, any] {
return xsync.NewMapOf[string, any]()
})
value, exists := actual.Load(key)
if exists {
return value.(T)
}
return fallback
}
func Set(sessionId SessionId, key string, value any) {
actual, _ := cache.LoadOrCompute(sessionId, func() *xsync.MapOf[string, any] {
return xsync.NewMapOf[string, any]()
})
actual.Store(key, value)
}