fix to only call cb for session id who initiated the event

This commit is contained in:
maddalax 2024-10-16 14:35:02 -05:00
parent 64fd4cfeab
commit 278161782c
4 changed files with 51 additions and 57 deletions

View file

@ -1,16 +1,13 @@
package event package event
import ( import (
"crypto/sha256"
"fmt" "fmt"
"github.com/google/uuid" "github.com/google/uuid"
"github.com/maddalax/htmgo/framework/h" "github.com/maddalax/htmgo/framework/h"
"github.com/maddalax/htmgo/framework/service" "github.com/maddalax/htmgo/framework/service"
"github.com/puzpuzpuz/xsync/v3" "github.com/puzpuzpuz/xsync/v3"
"runtime"
"sse-with-state/sse" "sse-with-state/sse"
"sse-with-state/state" "sse-with-state/state"
"strings"
"sync" "sync"
"sync/atomic" "sync/atomic"
"time" "time"
@ -41,35 +38,6 @@ var serverSideMessageListener = make(chan ServerSideEvent, 100)
var lock = sync.Mutex{} var lock = sync.Mutex{}
var callingHandler = atomic.Bool{} var callingHandler = atomic.Bool{}
func getCallerHash() string {
pc := make([]uintptr, 1000) // Adjust the size if you need a deeper stack trace
n := runtime.Callers(2, pc) // Skip 2: runtime.Callers() and printCallers()
frames := runtime.CallersFrames(pc[:n])
calls := make([]string, 0)
hitBegin := false
for {
frame, more := frames.Next()
calls = append(calls, fmt.Sprintf("%s:%d", frame.Function, frame.Line))
if strings.Contains(frame.Function, "runtime.goexit") {
hitBegin = true
}
if !more {
break
}
}
if !hitBegin {
fmt.Printf("hitBegin: %v\n", hitBegin)
panic("unable to add handler, stack trace too deep, maximum 1000, unable to find runtime.goexit")
}
joined := strings.Join(calls, ",")
hash := sha256.Sum256([]byte(joined))
return fmt.Sprintf("%x", hash)
}
func AddServerSideHandler(ctx *h.RequestContext, event string, handler Handler) *h.AttributeMapOrdered { func AddServerSideHandler(ctx *h.RequestContext, event string, handler Handler) *h.AttributeMapOrdered {
// If we are already in a handler, we don't want to add another handler // If we are already in a handler, we don't want to add another handler
// this can happen if the handler renders another element that has a handler // this can happen if the handler renders another element that has a handler
@ -104,11 +72,11 @@ func storeHashForSession(sessionId state.SessionId, hash KeyHash) {
m[hash] = true m[hash] = true
} }
func PushServerSideEvent(sessionId state.SessionId, event string) { func PushServerSideEvent(data HandlerData, event string, value map[string]any) {
serverSideMessageListener <- ServerSideEvent{ serverSideMessageListener <- ServerSideEvent{
Event: event, Event: event,
Payload: make(map[string]any), Payload: value,
SessionId: sessionId, SessionId: data.SessionId,
} }
} }
@ -134,23 +102,39 @@ func StartListener(locator *service.Locator) {
select { select {
case sevent := <-serverSideMessageListener: case sevent := <-serverSideMessageListener:
fmt.Printf("received server side event: %s\n", sevent.Event) fmt.Printf("received server side event: %s\n", sevent.Event)
// TODO optimize this
hashes, ok := serverEventNamesToHash.Load(sevent.Event) hashes, ok := serverEventNamesToHash.Load(sevent.Event)
if ok { hashesForSession, ok2 := sessionIdToHashes.Load(sevent.SessionId)
subset := make(map[KeyHash]bool)
for hash := range hashes { for hash := range hashes {
cb, ok := handlers.Load(hash) if _, ok := hashesForSession[hash]; ok {
if ok { subset[hash] = true
}
}
if ok && ok2 {
lock.Lock() lock.Lock()
callingHandler.Store(true) callingHandler.Store(true)
wg := sync.WaitGroup{}
for hash := range subset {
cb, ok := handlers.Load(hash)
if ok {
wg.Add(1)
go func(e ServerSideEvent) {
defer wg.Done()
cb(HandlerData{ cb(HandlerData{
SessionId: sevent.SessionId, SessionId: e.SessionId,
Socket: manager.Get(string(sevent.SessionId)), Socket: manager.Get(string(e.SessionId)),
Manager: manager, Manager: manager,
}) })
}(sevent)
}
}
wg.Wait()
callingHandler.Store(false) callingHandler.Store(false)
lock.Unlock() lock.Unlock()
} }
}
}
case event := <-socketMessageListener: case event := <-socketMessageListener:

View file

@ -3,6 +3,7 @@ package pages
import ( import (
"fmt" "fmt"
"github.com/maddalax/htmgo/framework/h" "github.com/maddalax/htmgo/framework/h"
"sse-with-state/event"
"sse-with-state/partials" "sse-with-state/partials"
"sse-with-state/state" "sse-with-state/state"
) )
@ -21,6 +22,12 @@ func IndexPage(ctx *h.RequestContext) *h.Page {
partials.Repeater(ctx, partials.RepeaterProps{ partials.Repeater(ctx, partials.RepeaterProps{
Id: "repeater-1", Id: "repeater-1",
OnAdd: func(data event.HandlerData) {
event.PushServerSideEvent(data, "increment", map[string]any{})
},
OnRemove: func(data event.HandlerData, index int) {
event.PushServerSideEvent(data, "decrement", map[string]any{})
},
AddButton: h.Button( AddButton: h.Button(
h.Text("+ Add Item"), h.Text("+ Add Item"),
), ),

View file

@ -19,6 +19,7 @@ func UseState[T any](sessionId state.SessionId, key string, initial T) (func() T
type Counter struct { type Counter struct {
Count func() int Count func() int
Increment func() Increment func()
Decrement func()
} }
func UseCounter(sessionId state.SessionId, id string) Counter { func UseCounter(sessionId state.SessionId, id string) Counter {
@ -28,9 +29,14 @@ func UseCounter(sessionId state.SessionId, id string) Counter {
set(get() + 1) set(get() + 1)
} }
var decrement = func() {
set(get() - 1)
}
return Counter{ return Counter{
Count: get, Count: get,
Increment: increment, Increment: increment,
Decrement: decrement,
} }
} }
@ -66,16 +72,10 @@ func CounterForm(ctx *h.RequestContext, props CounterProps) *h.Element {
counter.Increment() counter.Increment()
event.PushElement(data, CounterForm(ctx, props)) event.PushElement(data, CounterForm(ctx, props))
}), }),
//OnMouseOver(ctx, func(data event.HandlerData) { OnServerSideEvent(ctx, "decrement", func(data event.HandlerData) {
// counter.Increment() counter.Decrement()
// updated := CounterForm(ctx, props) event.PushElement(data, CounterForm(ctx, props))
// event.PushElement(data, updated) }),
//}),
//OnClick(ctx, func(data event.HandlerData) {
// counter.Increment()
// updated := CounterForm(ctx, props)
// event.PushElement(data, updated)
//}),
), ),
) )
} }

View file

@ -13,6 +13,8 @@ type RepeaterProps struct {
DefaultItems []*h.Element DefaultItems []*h.Element
Id string Id string
currentIndex int currentIndex int
OnAdd func(data event.HandlerData)
OnRemove func(data event.HandlerData, index int)
} }
func (props *RepeaterProps) itemId(index int) string { func (props *RepeaterProps) itemId(index int) string {
@ -33,6 +35,7 @@ func repeaterItem(ctx *h.RequestContext, item *h.Element, index int, props *Repe
h.ClassIf(index == 0, "opacity-0 disabled"), h.ClassIf(index == 0, "opacity-0 disabled"),
h.If(index == 0, h.Disabled()), h.If(index == 0, h.Disabled()),
OnClick(ctx, func(data event.HandlerData) { OnClick(ctx, func(data event.HandlerData) {
props.OnRemove(data, index)
props.currentIndex-- props.currentIndex--
event.PushElement(data, event.PushElement(data,
h.Div( h.Div(
@ -59,7 +62,7 @@ func Repeater(ctx *h.RequestContext, props RepeaterProps) *h.Element {
h.Class("flex justify-center"), h.Class("flex justify-center"),
props.AddButton, props.AddButton,
OnClick(ctx, func(data event.HandlerData) { OnClick(ctx, func(data event.HandlerData) {
event.PushServerSideEvent(data.SessionId, "increment") props.OnAdd(data)
event.PushElement(data, event.PushElement(data,
h.Div( h.Div(
h.Attribute("hx-swap-oob", "beforebegin:#"+props.addButtonId()), h.Attribute("hx-swap-oob", "beforebegin:#"+props.addButtonId()),