Skip to content

Commit

Permalink
Improve error handling if we are disconnected from the IRC server
Browse files Browse the repository at this point in the history
Check IRC connection state before handling the incoming HTTP
connection. Therefore we can remove the locking mechanism.
  • Loading branch information
kmille committed Mar 11, 2021
1 parent 8fca0bc commit fe23e4e
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 22 deletions.
28 changes: 8 additions & 20 deletions irc.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (
"fmt"
"io/ioutil"
"strings"
"sync"
"time"

"github.com/sirupsen/logrus"
Expand All @@ -16,10 +15,7 @@ import (
"github.com/spf13/viper"
)

var (
client *girc.Client
clientLock = &sync.RWMutex{}
)
var client *girc.Client

func ircConnection(config *viper.Viper, channelList []string) {
clientConfig := girc.Config{
Expand Down Expand Up @@ -89,12 +85,10 @@ func ircConnection(config *viper.Viper, channelList []string) {
}
}

clientLock.Lock()
client = girc.New(clientConfig)

client.Handlers.Add(girc.CONNECTED, func(c *girc.Client, e girc.Event) {
log.Info("Sucessfully connected to the IRC server. Starting to join channel.")
clientLock.Unlock()
for _, name := range removeDuplicates(channelList) {
joinChannel(name)
}
Expand All @@ -105,7 +99,7 @@ func ircConnection(config *viper.Viper, channelList []string) {
log.WithFields(log.Fields{
"Event": e.String(),
}).Debug("Received a PRIMSG")
message := "Hi. I'm a CptHook bot. Visit https://github.com/fleaz/CptHook to learn more"
message := "Hi. I'm a CptHook bot. Visit https://github.com/fleaz/CptHook to learn more."
if version == "dev" {
message += fmt.Sprintf(" I was compiled by hand at %v", date)
} else {
Expand All @@ -120,16 +114,13 @@ func ircConnection(config *viper.Viper, channelList []string) {

log.Info("Connecting to IRC server")
for {
// client.Connect() blocks. It returns nil if we call a client.Close() which we never do.
// client.Connect() blocks while we are connected.
// If the the connection is dropped/broken (recognized if we don't get a PONG 60 seconds
// after we sent a PING) an error is returned.
err := client.Connect()
// FIXME: if client.Connect() fails twice without going in state connected our handler is
// not called. This means that the lock is still acquired and we will hang here forever.
clientLock.Lock()
log.Warnf("Connection terminated: %s", err)
log.Warn("Reconnecting in 30 seconds...")
time.Sleep(30 * time.Second)
log.Warnf("Connection terminated. Reason: %s\n", err)
log.Warn("Reconnecting in 10 seconds...")
time.Sleep(10 * time.Second)
}

}
Expand Down Expand Up @@ -164,9 +155,8 @@ func channelReceiver() {
}).Debug("IRC handler received a message")
joinChannel(elem.Channel)
for _, message := range elem.Messages {
clientLock.RLock()
client.Cmd.Message(elem.Channel, message)
clientLock.RUnlock()

}
}
}
Expand All @@ -181,8 +171,6 @@ func joinChannel(newChannel string) {
log.WithFields(log.Fields{
"channel": newChannel,
}).Info("Need to join a new channel")

clientLock.RLock()
client.Cmd.Join(newChannel)
clientLock.RUnlock()

}
20 changes: 18 additions & 2 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import (
)

var (
inputChannel = make(chan input.IRCMessage, 10)
inputChannel = make(chan input.IRCMessage, 30)
version = "dev"
commit = "none"
date = time.Now().Format(time.RFC3339)
Expand Down Expand Up @@ -100,6 +100,22 @@ func loggingMiddleware(next http.HandlerFunc) http.HandlerFunc {
"host": r.Host,
"uri": r.URL,
}).Debug("Received HTTP request")

next.ServeHTTP(w, r)
})
}

func ircCheckMiddleware(next http.HandlerFunc) http.HandlerFunc {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if !client.IsConnected() {
log.WithFields(log.Fields{
"remote": r.RemoteAddr,
"uri": r.URL,
}).Warn("IRC server is disconnected. Dropping incoming HTTP request")
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte("IRC server disconnected"))
return
}
next.ServeHTTP(w, r)
})
}
Expand Down Expand Up @@ -142,7 +158,7 @@ func main() {
configPath := fmt.Sprintf("modules.%s", blockName)
module.Init(viper.Sub(configPath), &inputChannel)
channelList = append(channelList, module.GetChannelList()...)
http.HandleFunc(blockConfig.Endpoint, loggingMiddleware(module.GetHandler()))
http.HandleFunc(blockConfig.Endpoint, loggingMiddleware(ircCheckMiddleware(module.GetHandler())))
}

// Start IRC connection
Expand Down

0 comments on commit fe23e4e

Please sign in to comment.