From 075b9252b7e12f46b6d06ddb48842a3a28c00204 Mon Sep 17 00:00:00 2001 From: ppom <> Date: Wed, 12 Jul 2023 17:45:16 +0200 Subject: [PATCH] fix #24 --- app/pipe.go | 4 ++-- app/reaction.go | 21 ++++++++++++--------- app/startup.go | 4 ++++ config/reaction.test.yml | 1 + config/reaction.yml | 6 +++++- go.mod | 2 +- 6 files changed, 25 insertions(+), 13 deletions(-) diff --git a/app/pipe.go b/app/pipe.go index 5718242..fa02e8a 100644 --- a/app/pipe.go +++ b/app/pipe.go @@ -50,9 +50,9 @@ func (a *ActionStore) Quit() { a.mutex.Lock() defer a.mutex.Unlock() for _, actions := range a.store { - for _, sigs := range actions { + for action, sigs := range actions { for sig := range sigs { - close(sig) + sig <- action.OnExit } } } diff --git a/app/reaction.go b/app/reaction.go index e052506..7ed5380 100644 --- a/app/reaction.go +++ b/app/reaction.go @@ -76,6 +76,7 @@ func sleep(d time.Duration) chan bool { func (a *Action) exec(match string, advance time.Duration) { defer wgActions.Done() + doExec := true // Wait for either end of sleep time, or actionStore requesting stop if a.afterDuration != 0 && a.afterDuration > advance { @@ -83,24 +84,26 @@ func (a *Action) exec(match string, advance time.Duration) { select { case <-sleep(a.afterDuration - advance): // no-op - case _, _ = <-stopAction: + case doExec = <-stopAction: // no-op } // Let's not wait for the lock go actionStore.Unregister(a, match, stopAction) } - computedCommand := make([]string, 0, len(a.Cmd)) - for _, item := range a.Cmd { - computedCommand = append(computedCommand, strings.ReplaceAll(item, a.filter.patternWithBraces, match)) - } + if doExec { + computedCommand := make([]string, 0, len(a.Cmd)) + for _, item := range a.Cmd { + computedCommand = append(computedCommand, strings.ReplaceAll(item, a.filter.patternWithBraces, match)) + } - log.Printf("INFO %s.%s.%s: run %s\n", a.filter.stream.name, a.filter.name, a.name, computedCommand) + log.Printf("INFO %s.%s.%s: run %s\n", a.filter.stream.name, a.filter.name, a.name, computedCommand) - cmd := exec.Command(computedCommand[0], computedCommand[1:]...) + cmd := exec.Command(computedCommand[0], computedCommand[1:]...) - if ret := cmd.Run(); ret != nil { - log.Printf("ERROR %s.%s.%s: run %s, code %s\n", a.filter.stream.name, a.filter.name, a.name, computedCommand, ret) + if ret := cmd.Run(); ret != nil { + log.Printf("ERROR %s.%s.%s: run %s, code %s\n", a.filter.stream.name, a.filter.name, a.name, computedCommand, ret) + } } } diff --git a/app/startup.go b/app/startup.go index 5868eb7..6ead2cf 100644 --- a/app/startup.go +++ b/app/startup.go @@ -56,6 +56,8 @@ type Action struct { After string `yaml:"after"` afterDuration time.Duration `yaml:"-"` + + OnExit bool `yaml:"onexit"` } type LogEntry struct { @@ -144,6 +146,8 @@ func (c *Conf) setup() { log.Fatalln("FATAL Bad configuration: Failed to parse after time in ", stream.name, ".", filter.name, ".", action.name, ":", err) } action.afterDuration = afterDuration + } else if action.OnExit { + log.Fatalln("FATAL Bad configuration: Cannot have `onexit:true` without an `after` directive in", stream.name, ".", filter.name, ".", action.name) } if filter.longuestActionDuration == nil || filter.longuestActionDuration.Milliseconds() < action.afterDuration.Milliseconds() { filter.longuestActionDuration = &action.afterDuration diff --git a/config/reaction.test.yml b/config/reaction.test.yml index 3d5e999..2892acf 100644 --- a/config/reaction.test.yml +++ b/config/reaction.test.yml @@ -17,3 +17,4 @@ streams: sleepdamn: cmd: [ "echo", "sleep", "" ] after: 8m + onexit: true diff --git a/config/reaction.yml b/config/reaction.yml index 001e0be..1c39c43 100644 --- a/config/reaction.yml +++ b/config/reaction.yml @@ -1,5 +1,4 @@ --- -# TODO heavily comment this file # definitions are just a place to put chunks of conf you want to reuse in another place # they're not readed by reaction definitions: @@ -42,3 +41,8 @@ streams: # if after is defined, the action will not take place immediately, but after a specified duration. # same format as retry-period after: 48h + # let's say reaction is quitting. does it run all those pending commands which had an `after` duration set? + # if you want reaction to run those pending commands before exiting, you can set this: + # onexit: true + # (defaults to false) + # here it is not useful because we will flush the chain containing the bans anyway (see ./reaction.service) diff --git a/go.mod b/go.mod index d740d48..ccd1bc3 100644 --- a/go.mod +++ b/go.mod @@ -3,5 +3,5 @@ module framagit.org/ppom/reaction go 1.19 require ( - gopkg.in/yaml.v3 v3.0.1 // indirect + gopkg.in/yaml.v3 v3.0.1 )