Changeset 218 in code for trunk


Ignore:
Timestamp:
Apr 4, 2020, 3:33:09 PM (5 years ago)
Author:
delthas
Message:

Send one NOTICE on new upstream disconnect/connect errors

In order to notify the user when we are disconnected from a network
(either due to an error, or due a QUIT), and when we fail reconnecting,
this commit adds support for sending a short NOTICE message from the
service user to all relevant downstreams.

The last error is stored, and cleared on successful connection, to
ensure that the user is *not* flooded with identical connection error
messages, which can often happen when a server is down.

No lock is needed on lastError because it is only read and modified from
the user goroutine.

Closes: https://todo.sr.ht/~emersion/soju/27

Location:
trunk
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/service.go

    r202 r218  
    2020        handle   func(dc *downstreamConn, params []string) error
    2121        children serviceCommandSet
     22}
     23
     24func sendServiceNOTICE(dc *downstreamConn, text string) {
     25        dc.SendMessage(&irc.Message{
     26                Prefix:  &irc.Prefix{Name: serviceNick},
     27                Command: "NOTICE",
     28                Params:  []string{dc.nick, text},
     29        })
    2230}
    2331
  • trunk/upstream.go

    r217 r218  
    104104
    105105func (uc *upstreamConn) forEachDownstream(f func(*downstreamConn)) {
    106         uc.user.forEachDownstream(func(dc *downstreamConn) {
    107                 if dc.network != nil && dc.network != uc.network {
    108                         return
    109                 }
    110                 f(dc)
    111         })
     106        uc.network.forEachDownstream(f)
    112107}
    113108
  • trunk/user.go

    r215 r218  
    22
    33import (
     4        "fmt"
    45        "sync"
    56        "time"
     
    1516}
    1617
     18type eventUpstreamConnectionError struct {
     19        net *network
     20        err error
     21}
     22
    1723type eventUpstreamConnected struct {
    1824        uc *upstreamConn
     
    2127type eventUpstreamDisconnected struct {
    2228        uc *upstreamConn
     29}
     30
     31type eventUpstreamError struct {
     32        uc  *upstreamConn
     33        err error
    2334}
    2435
     
    4253        stopped chan struct{}
    4354
    44         history map[string]uint64
     55        history   map[string]uint64
     56        lastError error
    4557
    4658        lock sync.Mutex
     
    5668                history: make(map[string]uint64),
    5769        }
     70}
     71
     72func (net *network) forEachDownstream(f func(*downstreamConn)) {
     73        net.user.forEachDownstream(func(dc *downstreamConn) {
     74                if dc.network != nil && dc.network != net {
     75                        return
     76                }
     77                f(dc)
     78        })
    5879}
    5980
     
    7899                if err != nil {
    79100                        net.user.srv.Logger.Printf("failed to connect to upstream server %q: %v", net.Addr, err)
     101                        net.user.events <- eventUpstreamConnectionError{net, fmt.Errorf("failed to connect: %v", err)}
    80102                        continue
    81103                }
     
    84106                if err := uc.runUntilRegistered(); err != nil {
    85107                        uc.logger.Printf("failed to register: %v", err)
     108                        net.user.events <- eventUpstreamConnectionError{net, fmt.Errorf("failed to register: %v", err)}
    86109                        uc.Close()
    87110                        continue
     
    91114                if err := uc.readMessages(net.user.events); err != nil {
    92115                        uc.logger.Printf("failed to handle messages: %v", err)
     116                        net.user.events <- eventUpstreamError{uc, fmt.Errorf("failed to handle messages: %v", err)}
    93117                }
    94118                uc.Close()
     
    201225
    202226                        uc.updateAway()
     227
     228                        uc.forEachDownstream(func(dc *downstreamConn) {
     229                                sendServiceNOTICE(dc, fmt.Sprintf("connected to %s", uc.network.Name))
     230                        })
     231                        uc.network.lastError = nil
    203232                case eventUpstreamDisconnected:
    204233                        uc := e.uc
     
    215244
    216245                        uc.endPendingLISTs(true)
     246
     247                        if uc.network.lastError == nil {
     248                                uc.forEachDownstream(func(dc *downstreamConn) {
     249                                        sendServiceNOTICE(dc, fmt.Sprintf("disconnected from %s", uc.network.Name))
     250                                })
     251                        }
     252                case eventUpstreamConnectionError:
     253                        net := e.net
     254
     255                        if net.lastError == nil || net.lastError.Error() != e.err.Error() {
     256                                net.forEachDownstream(func(dc *downstreamConn) {
     257                                        sendServiceNOTICE(dc, fmt.Sprintf("failed connecting/registering to %s: %v", net.Name, e.err))
     258                                })
     259                        }
     260                        net.lastError = e.err
     261                case eventUpstreamError:
     262                        uc := e.uc
     263
     264                        uc.forEachDownstream(func(dc *downstreamConn) {
     265                                sendServiceNOTICE(dc, fmt.Sprintf("disconnected from %s: %v", uc.network.Name, e.err))
     266                        })
     267                        uc.network.lastError = e.err
    217268                case eventUpstreamMessage:
    218269                        msg, uc := e.msg, e.uc
Note: See TracChangeset for help on using the changeset viewer.