fix to only call cb for session id who initiated the event
This commit is contained in:
parent
64fd4cfeab
commit
278161782c
4 changed files with 51 additions and 57 deletions
|
|
@ -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,22 +102,38 @@ 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)
|
||||||
for hash := range hashes {
|
|
||||||
|
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)
|
cb, ok := handlers.Load(hash)
|
||||||
if ok {
|
if ok {
|
||||||
lock.Lock()
|
wg.Add(1)
|
||||||
callingHandler.Store(true)
|
go func(e ServerSideEvent) {
|
||||||
cb(HandlerData{
|
defer wg.Done()
|
||||||
SessionId: sevent.SessionId,
|
cb(HandlerData{
|
||||||
Socket: manager.Get(string(sevent.SessionId)),
|
SessionId: e.SessionId,
|
||||||
Manager: manager,
|
Socket: manager.Get(string(e.SessionId)),
|
||||||
})
|
Manager: manager,
|
||||||
callingHandler.Store(false)
|
})
|
||||||
lock.Unlock()
|
}(sevent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
wg.Wait()
|
||||||
|
callingHandler.Store(false)
|
||||||
|
lock.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
case event := <-socketMessageListener:
|
case event := <-socketMessageListener:
|
||||||
|
|
|
||||||
|
|
@ -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"),
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -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)
|
|
||||||
//}),
|
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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()),
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue