One guarded handler slot for a bundle's event and heartbeat handlers, so a reload never races the consumer's loop
Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
This commit is contained in:
@@ -160,7 +160,7 @@ func TestALongRunningBundleThatExitsIsStartedAgain(t *testing.T) {
|
||||
func fmtSprintf(format string, args ...any) string { return fmt.Sprintf(format, args...) }
|
||||
func errorf(format string, args ...any) error { return fmt.Errorf(format, args...) }
|
||||
|
||||
// A bundle loaded again sets its heartbeat handler while the consumer's loop hands a word on: no data race (-race),
|
||||
// A bundle loaded again sets its event and heartbeat handlers while the consumer's loop hands a word or an event on: no data race (-race),
|
||||
// and the heartbeat is asked of the bus only while some bundle holds a handler.
|
||||
func TestAHeartbeatHandlerSetAgainWhileWordsAreHandedOnIsNotARace(t *testing.T) {
|
||||
m := &moduleEvents{}
|
||||
@@ -170,16 +170,23 @@ func TestAHeartbeatHandlerSetAgainWhileWordsAreHandedOnIsNotARace(t *testing.T)
|
||||
if m.beatAsked() {
|
||||
t.Fatal("a heartbeat is asked while no bundle gave a handler")
|
||||
}
|
||||
took := &deliverSlot{}
|
||||
took.set(func(json.RawMessage) error { return nil })
|
||||
m.delivers = []*deliverSlot{took}
|
||||
var got atomic.Int32
|
||||
done := make(chan struct{})
|
||||
go func() {
|
||||
defer close(done)
|
||||
for i := 0; i < 200; i++ {
|
||||
slot.set(func(json.RawMessage) { got.Add(1) })
|
||||
took.set(func(json.RawMessage) error { got.Add(1); return nil })
|
||||
}
|
||||
}()
|
||||
for i := 0; i < 200; i++ {
|
||||
all.handBeat(m, bus.Beat{At: time.Now()})
|
||||
if err := all.handOut("mod", m, bus.Envelope{Key: "a.b", Body: json.RawMessage(`{}`)}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
<-done
|
||||
if !m.beatAsked() {
|
||||
|
||||
Reference in New Issue
Block a user