summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/lrstanley/girc/handler.go
diff options
context:
space:
mode:
authorWim <wim@42.be>2017-12-02 23:58:02 +0100
committerWim <wim@42.be>2017-12-02 23:58:02 +0100
commit788d3b32ac50430ee38feb996d068860beaa679e (patch)
tree51d0fdf1b9fa70c25cda534a2bfe866ac57804ae /vendor/github.com/lrstanley/girc/handler.go
parent1d414cf2fdbbf642307bea81756d95b6793a0f9d (diff)
downloadmatterbridge-msglm-788d3b32ac50430ee38feb996d068860beaa679e.tar.gz
matterbridge-msglm-788d3b32ac50430ee38feb996d068860beaa679e.tar.bz2
matterbridge-msglm-788d3b32ac50430ee38feb996d068860beaa679e.zip
Update vendor lrstanley/girc and readme
Diffstat (limited to 'vendor/github.com/lrstanley/girc/handler.go')
-rw-r--r--vendor/github.com/lrstanley/girc/handler.go131
1 files changed, 67 insertions, 64 deletions
diff --git a/vendor/github.com/lrstanley/girc/handler.go b/vendor/github.com/lrstanley/girc/handler.go
index f0c737f2..6c082708 100644
--- a/vendor/github.com/lrstanley/girc/handler.go
+++ b/vendor/github.com/lrstanley/girc/handler.go
@@ -29,11 +29,12 @@ func (c *Client) RunHandlers(event *Event) {
}
}
- // Regular wildcard handlers.
- c.Handlers.exec(ALL_EVENTS, c, event.Copy())
+ // Background handlers first.
+ c.Handlers.exec(ALL_EVENTS, true, c, event.Copy())
+ c.Handlers.exec(event.Command, true, c, event.Copy())
- // Then regular handlers.
- c.Handlers.exec(event.Command, c, event.Copy())
+ c.Handlers.exec(ALL_EVENTS, false, c, event.Copy())
+ c.Handlers.exec(event.Command, false, c, event.Copy())
// Check if it's a CTCP.
if ctcp := decodeCTCP(event.Copy()); ctcp != nil {
@@ -144,7 +145,7 @@ func (c *Caller) cuid(cmd string, n int) (cuid, uid string) {
// cuidToID allows easy mapping between a generated cuid and the caller
// external/internal handler maps.
func (c *Caller) cuidToID(input string) (cmd, uid string) {
- i := strings.IndexByte(input, 0x3A)
+ i := strings.IndexByte(input, ':')
if i < 0 {
return "", ""
}
@@ -160,9 +161,9 @@ type execStack struct {
// exec executes all handlers pertaining to specified event. Internal first,
// then external.
//
-// Please note that there is no specific order/priority for which the
-// handler types themselves or the handlers are executed.
-func (c *Caller) exec(command string, client *Client, event *Event) {
+// Please note that there is no specific order/priority for which the handlers
+// are executed.
+func (c *Caller) exec(command string, bg bool, client *Client, event *Event) {
// Build a stack of handlers which can be executed concurrently.
var stack []execStack
@@ -170,13 +171,21 @@ func (c *Caller) exec(command string, client *Client, event *Event) {
// Get internal handlers first.
if _, ok := c.internal[command]; ok {
for cuid := range c.internal[command] {
+ if (strings.HasSuffix(cuid, ":bg") && !bg) || (!strings.HasSuffix(cuid, ":bg") && bg) {
+ continue
+ }
+
stack = append(stack, execStack{c.internal[command][cuid], cuid})
}
}
- // Aaand then external handlers.
+ // Then external handlers.
if _, ok := c.external[command]; ok {
for cuid := range c.external[command] {
+ if (strings.HasSuffix(cuid, ":bg") && !bg) || (!strings.HasSuffix(cuid, ":bg") && bg) {
+ continue
+ }
+
stack = append(stack, execStack{c.external[command][cuid], cuid})
}
}
@@ -189,18 +198,29 @@ func (c *Caller) exec(command string, client *Client, event *Event) {
wg.Add(len(stack))
for i := 0; i < len(stack); i++ {
go func(index int) {
- c.debug.Printf("executing handler %s for event %s (%d of %d)", stack[index].cuid, command, index+1, len(stack))
+ defer wg.Done()
+ c.debug.Printf("[%d/%d] exec %s => %s", index+1, len(stack), stack[index].cuid, command)
start := time.Now()
- // If they want to catch any panics, add to defer stack.
+ if bg {
+ go func() {
+ if client.Config.RecoverFunc != nil {
+ defer recoverHandlerPanic(client, event, stack[index].cuid, 3)
+ }
+
+ stack[index].Execute(client, *event)
+ c.debug.Printf("[%d/%d] done %s == %s", index+1, len(stack), stack[index].cuid, time.Since(start))
+ }()
+
+ return
+ }
+
if client.Config.RecoverFunc != nil {
defer recoverHandlerPanic(client, event, stack[index].cuid, 3)
}
stack[index].Execute(client, *event)
-
- c.debug.Printf("execution of %s took %s (%d of %d)", stack[index].cuid, time.Since(start), index+1, len(stack))
- wg.Done()
+ c.debug.Printf("[%d/%d] done %s == %s", index+1, len(stack), stack[index].cuid, time.Since(start))
}(i)
}
@@ -281,9 +301,9 @@ func (c *Caller) remove(cuid string) (success bool) {
// sregister is much like Caller.register(), except that it safely locks
// the Caller mutex.
-func (c *Caller) sregister(internal bool, cmd string, handler Handler) (cuid string) {
+func (c *Caller) sregister(internal, bg bool, cmd string, handler Handler) (cuid string) {
c.mu.Lock()
- cuid = c.register(internal, cmd, handler)
+ cuid = c.register(internal, bg, cmd, handler)
c.mu.Unlock()
return cuid
@@ -291,30 +311,34 @@ func (c *Caller) sregister(internal bool, cmd string, handler Handler) (cuid str
// register will register a handler in the internal tracker. Unsafe (you
// must lock c.mu yourself!)
-func (c *Caller) register(internal bool, cmd string, handler Handler) (cuid string) {
+func (c *Caller) register(internal, bg bool, cmd string, handler Handler) (cuid string) {
var uid string
cmd = strings.ToUpper(cmd)
+ cuid, uid = c.cuid(cmd, 20)
+ if bg {
+ uid += ":bg"
+ cuid += ":bg"
+ }
+
if internal {
if _, ok := c.internal[cmd]; !ok {
c.internal[cmd] = map[string]Handler{}
}
- cuid, uid = c.cuid(cmd, 20)
c.internal[cmd][uid] = handler
} else {
if _, ok := c.external[cmd]; !ok {
c.external[cmd] = map[string]Handler{}
}
- cuid, uid = c.cuid(cmd, 20)
c.external[cmd][uid] = handler
}
_, file, line, _ := runtime.Caller(3)
- c.debug.Printf("registering handler for %q with cuid %q (internal: %t) from: %s:%d", cmd, cuid, internal, file, line)
+ c.debug.Printf("reg %q => %s [int:%t bg:%t] %s:%d", uid, cmd, internal, bg, file, line)
return cuid
}
@@ -323,31 +347,20 @@ func (c *Caller) register(internal bool, cmd string, handler Handler) (cuid stri
// given event. cuid is the handler uid which can be used to remove the
// handler with Caller.Remove().
func (c *Caller) AddHandler(cmd string, handler Handler) (cuid string) {
- return c.sregister(false, cmd, handler)
+ return c.sregister(false, false, cmd, handler)
}
// Add registers the handler function for the given event. cuid is the
// handler uid which can be used to remove the handler with Caller.Remove().
func (c *Caller) Add(cmd string, handler func(client *Client, event Event)) (cuid string) {
- return c.sregister(false, cmd, HandlerFunc(handler))
+ return c.sregister(false, false, cmd, HandlerFunc(handler))
}
// AddBg registers the handler function for the given event and executes it
// in a go-routine. cuid is the handler uid which can be used to remove the
// handler with Caller.Remove().
func (c *Caller) AddBg(cmd string, handler func(client *Client, event Event)) (cuid string) {
- return c.sregister(false, cmd, HandlerFunc(func(client *Client, event Event) {
- // Setting up background-based handlers this way allows us to get
- // clean call stacks for use with panic recovery.
- go func() {
- // If they want to catch any panics, add to defer stack.
- if client.Config.RecoverFunc != nil {
- defer recoverHandlerPanic(client, &event, "goroutine", 3)
- }
-
- handler(client, event)
- }()
- }))
+ return c.sregister(false, true, cmd, HandlerFunc(handler))
}
// AddTmp adds a "temporary" handler, which is good for one-time or few-time
@@ -361,47 +374,37 @@ func (c *Caller) AddBg(cmd string, handler func(client *Client, event Event)) (c
//
// Additionally, AddTmp has a useful option, deadline. When set to greater
// than 0, deadline will be the amount of time that passes before the handler
-// is removed from the stack, regardless if the handler returns true or not.
+// is removed from the stack, regardless of if the handler returns true or not.
// This is useful in that it ensures that the handler is cleaned up if the
// server does not respond appropriately, or takes too long to respond.
//
// Note that handlers supplied with AddTmp are executed in a goroutine to
-// ensure that they are not blocking other handlers. Additionally, use cuid
-// with Caller.Remove() to prematurely remove the handler from the stack,
-// bypassing the timeout or waiting for the handler to return that it wants
-// to be removed from the stack.
+// ensure that they are not blocking other handlers. However, if you are
+// creating a temporary handler from another handler, it should be a
+// background handler.
+//
+// Use cuid with Caller.Remove() to prematurely remove the handler from the
+// stack, bypassing the timeout or waiting for the handler to return that it
+// wants to be removed from the stack.
func (c *Caller) AddTmp(cmd string, deadline time.Duration, handler func(client *Client, event Event) bool) (cuid string, done chan struct{}) {
- var uid string
- cuid, uid = c.cuid(cmd, 20)
-
done = make(chan struct{})
- c.mu.Lock()
- if _, ok := c.external[cmd]; !ok {
- c.external[cmd] = map[string]Handler{}
- }
- c.external[cmd][uid] = HandlerFunc(func(client *Client, event Event) {
- // Setting up background-based handlers this way allows us to get
- // clean call stacks for use with panic recovery.
- go func() {
- // If they want to catch any panics, add to defer stack.
- if client.Config.RecoverFunc != nil {
- defer recoverHandlerPanic(client, &event, "tmp-goroutine", 3)
- }
-
- remove := handler(client, event)
- if remove {
- if ok := c.Remove(cuid); ok {
- close(done)
- }
+ cuid = c.sregister(false, true, cmd, HandlerFunc(func(client *Client, event Event) {
+ remove := handler(client, event)
+ if remove {
+ if ok := c.Remove(cuid); ok {
+ close(done)
}
- }()
- })
- c.mu.Unlock()
+ }
+ }))
if deadline > 0 {
go func() {
- <-time.After(deadline)
+ select {
+ case <-time.After(deadline):
+ case <-done:
+ }
+
if ok := c.Remove(cuid); ok {
close(done)
}