mirror of
https://github.com/fiatjaf/nak.git
synced 2026-10-05 15:18:23 +00:00
group chat: handle events synchronously in select, drop goroutine and mutex
This commit is contained in:
@@ -276,68 +276,32 @@ var group = &cli.Command{
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// stored events arrive newest-first before EOSE, so we buffer them
|
||||||
|
// from the end and print them in chronological order once EOSE
|
||||||
|
// arrives; live events are printed as they come.
|
||||||
eosed := false
|
eosed := false
|
||||||
var mu sync.Mutex
|
messages := make([]string, 200)
|
||||||
messages := make([]struct {
|
|
||||||
message string
|
|
||||||
rendered bool
|
|
||||||
}, 200)
|
|
||||||
base := len(messages)
|
base := len(messages)
|
||||||
|
|
||||||
// must be called with mu held
|
|
||||||
tryRender := func(i int) {
|
|
||||||
// if all messages before these are loaded we can render this,
|
|
||||||
// otherwise we render whatever we can and stop
|
|
||||||
for m, msg := range messages[base:] {
|
|
||||||
if msg.rendered {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if msg.message == "" {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
messages[base+m].rendered = true
|
|
||||||
stdout(msg.message)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case evt := <-sub.Events:
|
case evt := <-sub.Events:
|
||||||
mu.Lock()
|
meta := sys.FetchProfileMetadata(ctx, evt.PubKey)
|
||||||
var i int
|
line := color.HiBlueString(meta.ShortName()) + " " + color.HiCyanString(evt.CreatedAt.Time().Format(time.DateTime)) + ": " + evt.Content
|
||||||
if eosed {
|
if eosed {
|
||||||
i = len(messages)
|
stdout(line)
|
||||||
messages = append(messages, struct {
|
|
||||||
message string
|
|
||||||
rendered bool
|
|
||||||
}{})
|
|
||||||
} else if base > 0 {
|
} else if base > 0 {
|
||||||
base--
|
base--
|
||||||
i = base
|
messages[base] = line
|
||||||
} else {
|
|
||||||
// pre-EOSE buffer is full (relay returned more than the limit); drop.
|
|
||||||
mu.Unlock()
|
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
mu.Unlock()
|
// else: pre-EOSE buffer is full (relay returned more than the limit); drop.
|
||||||
|
|
||||||
go func() {
|
|
||||||
meta := sys.FetchProfileMetadata(ctx, evt.PubKey)
|
|
||||||
line := color.HiBlueString(meta.ShortName()) + " " + color.HiCyanString(evt.CreatedAt.Time().Format(time.DateTime)) + ": " + evt.Content
|
|
||||||
mu.Lock()
|
|
||||||
messages[i].message = line
|
|
||||||
if eosed {
|
|
||||||
tryRender(i)
|
|
||||||
}
|
|
||||||
mu.Unlock()
|
|
||||||
}()
|
|
||||||
case reason := <-sub.ClosedReason:
|
case reason := <-sub.ClosedReason:
|
||||||
stdout("closed:" + color.YellowString(reason))
|
stdout("closed:" + color.YellowString(reason))
|
||||||
case <-sub.EndOfStoredEvents:
|
case <-sub.EndOfStoredEvents:
|
||||||
mu.Lock()
|
|
||||||
eosed = true
|
eosed = true
|
||||||
tryRender(len(messages) - 1)
|
for _, msg := range messages[base:] {
|
||||||
mu.Unlock()
|
stdout(msg)
|
||||||
|
}
|
||||||
case <-sub.Context.Done():
|
case <-sub.Context.Done():
|
||||||
return fmt.Errorf("subscription ended: %w", context.Cause(sub.Context))
|
return fmt.Errorf("subscription ended: %w", context.Cause(sub.Context))
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user