diff options
Diffstat (limited to 'internal/chat/chan.go')
| -rw-r--r-- | internal/chat/chan.go | 69 |
1 files changed, 69 insertions, 0 deletions
diff --git a/internal/chat/chan.go b/internal/chat/chan.go new file mode 100644 index 0000000..ae78bb6 --- /dev/null +++ b/internal/chat/chan.go @@ -0,0 +1,69 @@ +package chat + +import ( + "context" + "log/slog" + "sync" + "time" +) + +type Channel struct { + Name string + Users map[*User]struct{} + Events chan any + mu sync.RWMutex +} + +func (c *Channel) Listen(ctx context.Context) { + for { + select { + case <-ctx.Done(): + return + case ev := <-c.Events: + c.processEvent(ev) + } + } +} + +func (c *Channel) processEvent(ev any) { + slog.Info("channel event", slog.String("channel", c.Name), slog.Any("event", ev)) + + for u := range c.Users { + select { + case u.Events <- ev: + default: + } + } +} + +func (c *Channel) Join(u *User) { + c.mu.Lock() + defer c.mu.Unlock() + + if _, ok := c.Users[u]; ok { + return + } + c.Events <- UserJoined{ + User: u, + Time: time.Now(), + Chan: c, + } + + c.Users[u] = struct{}{} +} + +func (c *Channel) Leave(u *User) { + c.mu.Lock() + defer c.mu.Unlock() + + if _, ok := c.Users[u]; !ok { + return + } + c.Events <- UserLeft{ + User: u, + Time: time.Now(), + Chan: c, + } + + delete(c.Users, u) +} |
