From 278161782c569b9ee0c3a19e78ad2cd7e2d7ca33 Mon Sep 17 00:00:00 2001 From: maddalax Date: Wed, 16 Oct 2024 14:35:02 -0500 Subject: [PATCH] fix to only call cb for session id who initiated the event --- examples/sse-with-state/event/listener.go | 76 ++++++++------------ examples/sse-with-state/pages/index.go | 7 ++ examples/sse-with-state/partials/index.go | 20 +++--- examples/sse-with-state/partials/repeater.go | 5 +- 4 files changed, 51 insertions(+), 57 deletions(-) diff --git a/examples/sse-with-state/event/listener.go b/examples/sse-with-state/event/listener.go index cd559f0..bbf84eb 100644 --- a/examples/sse-with-state/event/listener.go +++ b/examples/sse-with-state/event/listener.go @@ -1,16 +1,13 @@ package event import ( - "crypto/sha256" "fmt" "github.com/google/uuid" "github.com/maddalax/htmgo/framework/h" "github.com/maddalax/htmgo/framework/service" "github.com/puzpuzpuz/xsync/v3" - "runtime" "sse-with-state/sse" "sse-with-state/state" - "strings" "sync" "sync/atomic" "time" @@ -41,35 +38,6 @@ var serverSideMessageListener = make(chan ServerSideEvent, 100) var lock = sync.Mutex{} 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 { // 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 @@ -104,11 +72,11 @@ func storeHashForSession(sessionId state.SessionId, hash KeyHash) { m[hash] = true } -func PushServerSideEvent(sessionId state.SessionId, event string) { +func PushServerSideEvent(data HandlerData, event string, value map[string]any) { serverSideMessageListener <- ServerSideEvent{ Event: event, - Payload: make(map[string]any), - SessionId: sessionId, + Payload: value, + SessionId: data.SessionId, } } @@ -134,22 +102,38 @@ func StartListener(locator *service.Locator) { select { case sevent := <-serverSideMessageListener: fmt.Printf("received server side event: %s\n", sevent.Event) + // TODO optimize this hashes, ok := serverEventNamesToHash.Load(sevent.Event) - if ok { - for hash := range hashes { + hashesForSession, ok2 := sessionIdToHashes.Load(sevent.SessionId) + + subset := make(map[KeyHash]bool) + for hash := range hashes { + if _, ok := hashesForSession[hash]; ok { + subset[hash] = true + } + } + + if ok && ok2 { + lock.Lock() + callingHandler.Store(true) + wg := sync.WaitGroup{} + for hash := range subset { cb, ok := handlers.Load(hash) if ok { - lock.Lock() - callingHandler.Store(true) - cb(HandlerData{ - SessionId: sevent.SessionId, - Socket: manager.Get(string(sevent.SessionId)), - Manager: manager, - }) - callingHandler.Store(false) - lock.Unlock() + wg.Add(1) + go func(e ServerSideEvent) { + defer wg.Done() + cb(HandlerData{ + SessionId: e.SessionId, + Socket: manager.Get(string(e.SessionId)), + Manager: manager, + }) + }(sevent) } } + wg.Wait() + callingHandler.Store(false) + lock.Unlock() } case event := <-socketMessageListener: diff --git a/examples/sse-with-state/pages/index.go b/examples/sse-with-state/pages/index.go index b85c959..552aa2a 100644 --- a/examples/sse-with-state/pages/index.go +++ b/examples/sse-with-state/pages/index.go @@ -3,6 +3,7 @@ package pages import ( "fmt" "github.com/maddalax/htmgo/framework/h" + "sse-with-state/event" "sse-with-state/partials" "sse-with-state/state" ) @@ -21,6 +22,12 @@ func IndexPage(ctx *h.RequestContext) *h.Page { partials.Repeater(ctx, partials.RepeaterProps{ 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( h.Text("+ Add Item"), ), diff --git a/examples/sse-with-state/partials/index.go b/examples/sse-with-state/partials/index.go index 9e6c33f..a0750f3 100644 --- a/examples/sse-with-state/partials/index.go +++ b/examples/sse-with-state/partials/index.go @@ -19,6 +19,7 @@ func UseState[T any](sessionId state.SessionId, key string, initial T) (func() T type Counter struct { Count func() int Increment func() + Decrement func() } func UseCounter(sessionId state.SessionId, id string) Counter { @@ -28,9 +29,14 @@ func UseCounter(sessionId state.SessionId, id string) Counter { set(get() + 1) } + var decrement = func() { + set(get() - 1) + } + return Counter{ Count: get, Increment: increment, + Decrement: decrement, } } @@ -66,16 +72,10 @@ func CounterForm(ctx *h.RequestContext, props CounterProps) *h.Element { counter.Increment() event.PushElement(data, CounterForm(ctx, props)) }), - //OnMouseOver(ctx, func(data event.HandlerData) { - // counter.Increment() - // updated := CounterForm(ctx, props) - // event.PushElement(data, updated) - //}), - //OnClick(ctx, func(data event.HandlerData) { - // counter.Increment() - // updated := CounterForm(ctx, props) - // event.PushElement(data, updated) - //}), + OnServerSideEvent(ctx, "decrement", func(data event.HandlerData) { + counter.Decrement() + event.PushElement(data, CounterForm(ctx, props)) + }), ), ) } diff --git a/examples/sse-with-state/partials/repeater.go b/examples/sse-with-state/partials/repeater.go index 5c9d6f1..7c2d6b5 100644 --- a/examples/sse-with-state/partials/repeater.go +++ b/examples/sse-with-state/partials/repeater.go @@ -13,6 +13,8 @@ type RepeaterProps struct { DefaultItems []*h.Element Id string currentIndex int + OnAdd func(data event.HandlerData) + OnRemove func(data event.HandlerData, index int) } 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.If(index == 0, h.Disabled()), OnClick(ctx, func(data event.HandlerData) { + props.OnRemove(data, index) props.currentIndex-- event.PushElement(data, h.Div( @@ -59,7 +62,7 @@ func Repeater(ctx *h.RequestContext, props RepeaterProps) *h.Element { h.Class("flex justify-center"), props.AddButton, OnClick(ctx, func(data event.HandlerData) { - event.PushServerSideEvent(data.SessionId, "increment") + props.OnAdd(data) event.PushElement(data, h.Div( h.Attribute("hx-swap-oob", "beforebegin:#"+props.addButtonId()),