Changeset 103 in code for trunk/user.go


Ignore:
Timestamp:
Mar 16, 2020, 11:44:59 AM (5 years ago)
Author:
contact
Message:

Per-user dispatcher goroutine

This allows message handlers to read upstream/downstream connection
information without causing any race condition.

References: https://todo.sr.ht/~emersion/soju/1

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/user.go

    r101 r103  
    44        "sync"
    55        "time"
     6
     7        "gopkg.in/irc.v3"
    68)
     9
     10type upstreamIncomingMessage struct {
     11        msg *irc.Message
     12        uc  *upstreamConn
     13}
     14
     15type downstreamIncomingMessage struct {
     16        msg *irc.Message
     17        dc  *downstreamConn
     18}
    719
    820type network struct {
     
    4153                net.user.lock.Unlock()
    4254
    43                 if err := uc.readMessages(); err != nil {
     55                if err := uc.readMessages(net.user.upstreamIncoming); err != nil {
    4456                        uc.logger.Printf("failed to handle messages: %v", err)
    4557                }
     
    5668        srv *Server
    5769
     70        upstreamIncoming   chan upstreamIncomingMessage
     71        downstreamIncoming chan downstreamIncomingMessage
     72
    5873        lock            sync.Mutex
    5974        networks        []*network
     
    6378func newUser(srv *Server, record *User) *user {
    6479        return &user{
    65                 User: *record,
    66                 srv:  srv,
     80                User:               *record,
     81                srv:                srv,
     82                upstreamIncoming:   make(chan upstreamIncomingMessage, 64),
     83                downstreamIncoming: make(chan downstreamIncomingMessage, 64),
    6784        }
    6885}
     
    120137        }
    121138        u.lock.Unlock()
     139
     140        for {
     141                select {
     142                case upstreamMsg := <-u.upstreamIncoming:
     143                        msg, uc := upstreamMsg.msg, upstreamMsg.uc
     144                        if err := uc.handleMessage(msg); err != nil {
     145                                uc.logger.Printf("failed to handle message %q: %v", msg, err)
     146                        }
     147                case downstreamMsg := <-u.downstreamIncoming:
     148                        msg, dc := downstreamMsg.msg, downstreamMsg.dc
     149                        err := dc.handleMessage(msg)
     150                        if ircErr, ok := err.(ircError); ok {
     151                                ircErr.Message.Prefix = dc.srv.prefix()
     152                                dc.SendMessage(ircErr.Message)
     153                        } else if err != nil {
     154                                dc.logger.Printf("failed to handle message %q: %v", msg, err)
     155                                dc.Close()
     156                        }
     157                }
     158        }
    122159}
    123160
Note: See TracChangeset for help on using the changeset viewer.