polling
This commit is contained in:
parent
70255bc2a2
commit
f5e83ef690
21
config.yml
21
config.yml
@ -2,6 +2,7 @@ directories:
|
|||||||
- path: /tmp/foo
|
- path: /tmp/foo
|
||||||
recursive: false
|
recursive: false
|
||||||
events: ["CLOSE_WRITE", "MOVED_TO"]
|
events: ["CLOSE_WRITE", "MOVED_TO"]
|
||||||
|
pollingInterval: 60
|
||||||
regex: "/[^\\.][^/]+.xml$"
|
regex: "/[^\\.][^/]+.xml$"
|
||||||
actions:
|
actions:
|
||||||
- type: http
|
- type: http
|
||||||
@ -12,25 +13,31 @@ directories:
|
|||||||
ContentType: application/xml
|
ContentType: application/xml
|
||||||
# content: PLAIN IS FILECONTENT
|
# content: PLAIN IS FILECONTENT
|
||||||
onError:
|
onError:
|
||||||
type: move
|
- type: move
|
||||||
to: /tmp/error/{{ filename }}
|
to: /tmp/error/{{ filename }}
|
||||||
stop: true
|
stop: true
|
||||||
|
|
||||||
|
onSuccess:
|
||||||
|
- type: delete
|
||||||
|
|
||||||
|
- path: /tmp/foo
|
||||||
|
recursive: false
|
||||||
|
events: ["CLOSE_WRITE", "MOVED_TO"]
|
||||||
|
regex: "/[^\\.][^/]+.(png|jpe?g|pdf)$"
|
||||||
|
actions:
|
||||||
- type: http
|
- type: http
|
||||||
method: post
|
method: post
|
||||||
url: http://localhost:8080/api/v1/_/renz_einfo/operation-file
|
url: http://localhost:8080/api/v1/_/renz_einfo/operation-file
|
||||||
header:
|
header:
|
||||||
Token: abc
|
Token: Ksi02vcaHHasd1sjYxiq4J
|
||||||
ContentType: application/json
|
Content-Type: application/json
|
||||||
content: |
|
content: |
|
||||||
{
|
{
|
||||||
"filename": "{{ .Name }}"
|
"filename": "{{ filename }}"
|
||||||
}
|
}
|
||||||
onError:
|
onError:
|
||||||
type: move
|
- type: move
|
||||||
to: /tmp/error/{{ filename }}
|
to: /tmp/error/{{ filename }}
|
||||||
stop: true
|
stop: true
|
||||||
|
|
||||||
- type: delete
|
|
||||||
- type: log
|
- type: log
|
||||||
|
|
||||||
|
1
go.mod
1
go.mod
@ -3,6 +3,7 @@ module gitbase.de/apairon/fstrigger
|
|||||||
go 1.16
|
go 1.16
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/davecgh/go-spew v1.1.1
|
||||||
github.com/flosch/pongo2/v4 v4.0.2
|
github.com/flosch/pongo2/v4 v4.0.2
|
||||||
github.com/rjeczalik/notify v0.9.2
|
github.com/rjeczalik/notify v0.9.2
|
||||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
|
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
|
||||||
|
2
go.sum
2
go.sum
@ -1,3 +1,5 @@
|
|||||||
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/flosch/pongo2/v4 v4.0.2 h1:gv+5Pe3vaSVmiJvh/BZa82b7/00YUGm0PIyVVLop0Hw=
|
github.com/flosch/pongo2/v4 v4.0.2 h1:gv+5Pe3vaSVmiJvh/BZa82b7/00YUGm0PIyVVLop0Hw=
|
||||||
github.com/flosch/pongo2/v4 v4.0.2/go.mod h1:B5ObFANs/36VwxxlgKpdchIJHMvHB562PW+BWPhwZD8=
|
github.com/flosch/pongo2/v4 v4.0.2/go.mod h1:B5ObFANs/36VwxxlgKpdchIJHMvHB562PW+BWPhwZD8=
|
||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
|
113
main.go
113
main.go
@ -31,14 +31,15 @@ type ActionConfig struct {
|
|||||||
To *string
|
To *string
|
||||||
|
|
||||||
Stop bool
|
Stop bool
|
||||||
OnSuccess *ActionConfig `yaml:"onSuccess"`
|
OnSuccess []ActionConfig `yaml:"onSuccess"`
|
||||||
OnError *ActionConfig `yaml:"onError"`
|
OnError []ActionConfig `yaml:"onError"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type DirectoryConfig struct {
|
type DirectoryConfig struct {
|
||||||
Path string
|
Path string
|
||||||
Recursive bool
|
Recursive bool
|
||||||
Events []string
|
Events []string
|
||||||
|
PollingInterval *int64 `yaml:"pollingInterval"`
|
||||||
Regex *string
|
Regex *string
|
||||||
_regex *regexp.Regexp
|
_regex *regexp.Regexp
|
||||||
Actions []ActionConfig
|
Actions []ActionConfig
|
||||||
@ -50,8 +51,25 @@ type Config struct {
|
|||||||
|
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
|
|
||||||
|
type pollInfo struct {
|
||||||
|
path string
|
||||||
|
event notify.Event
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p pollInfo) Path() string {
|
||||||
|
return p.path
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p pollInfo) Event() notify.Event {
|
||||||
|
return p.event
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p pollInfo) Sys() interface{} {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func startWatcher(directory *DirectoryConfig) {
|
func startWatcher(directory *DirectoryConfig) {
|
||||||
c := make(chan notify.EventInfo, 10)
|
c := make(chan notify.EventInfo, 1000)
|
||||||
monitoredEvents := []notify.Event{}
|
monitoredEvents := []notify.Event{}
|
||||||
for _, e := range directory.Events {
|
for _, e := range directory.Events {
|
||||||
switch e {
|
switch e {
|
||||||
@ -98,15 +116,29 @@ func startWatcher(directory *DirectoryConfig) {
|
|||||||
go func(directory *DirectoryConfig, monitoredEvents []notify.Event) {
|
go func(directory *DirectoryConfig, monitoredEvents []notify.Event) {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
|
|
||||||
log.Printf("watching %s for %v\n", directory.Path, directory.Events)
|
log.Printf("watching %s for %v, regex %s\n", directory.Path, directory.Events, *directory.Regex)
|
||||||
|
|
||||||
if err := notify.Watch(directory.Path, c, monitoredEvents...); err != nil {
|
if err := notify.Watch(directory.Path, c, monitoredEvents...); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
defer notify.Stop(c)
|
defer notify.Stop(c)
|
||||||
|
|
||||||
|
firstRun := true
|
||||||
for {
|
for {
|
||||||
eventInfo := <-c
|
var eventInfo notify.EventInfo
|
||||||
|
if directory.PollingInterval != nil {
|
||||||
|
if !firstRun {
|
||||||
|
select {
|
||||||
|
case eventInfo = <-c: // event
|
||||||
|
case <-time.After(time.Second * time.Duration(*directory.PollingInterval)): // timeout for polling
|
||||||
|
}
|
||||||
|
}
|
||||||
|
firstRun = false // do polling as init
|
||||||
|
} else {
|
||||||
|
eventInfo = <-c
|
||||||
|
}
|
||||||
|
|
||||||
|
if eventInfo != nil {
|
||||||
p := eventInfo.Path()
|
p := eventInfo.Path()
|
||||||
log.Printf("path: %s; event: %s\n", p, eventInfo.Event().String())
|
log.Printf("path: %s; event: %s\n", p, eventInfo.Event().String())
|
||||||
if directory._regex == nil || directory._regex.MatchString(p) {
|
if directory._regex == nil || directory._regex.MatchString(p) {
|
||||||
@ -120,6 +152,30 @@ func startWatcher(directory *DirectoryConfig) {
|
|||||||
log.Printf("path: %s; no regex match\n", p)
|
log.Printf("path: %s; no regex match\n", p)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if directory.PollingInterval != nil && len(c) == 0 {
|
||||||
|
// polling only while queue is empty
|
||||||
|
files, err := ioutil.ReadDir(directory.Path)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("path: %s; polling error: %s", directory.Path, err)
|
||||||
|
}
|
||||||
|
for _, f := range files {
|
||||||
|
p := directory.Path + "/" + f.Name()
|
||||||
|
if directory._regex == nil || directory._regex.MatchString(p) {
|
||||||
|
pollI := pollInfo{
|
||||||
|
path: p,
|
||||||
|
event: 0,
|
||||||
|
}
|
||||||
|
select {
|
||||||
|
case c <- pollI:
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log.Printf("path: %s; no regex match (polling)\n", p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}(directory, monitoredEvents)
|
}(directory, monitoredEvents)
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -143,21 +199,29 @@ func runAction(action *ActionConfig, eventInfo notify.EventInfo) (contin bool, e
|
|||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("path: %s; action: %s; error %s", eventInfo.Path(), action.Type, err)
|
log.Printf("path: %s; action: %s; error %s", eventInfo.Path(), action.Type, err)
|
||||||
if action.OnError != nil {
|
for _, aE := range action.OnError {
|
||||||
_c, errE := runAction(action.OnError, eventInfo)
|
_c, errE := runAction(&aE, eventInfo)
|
||||||
contin = contin && _c
|
contin = contin && _c
|
||||||
if errE != nil {
|
if errE != nil {
|
||||||
log.Printf("path: %s; action: %s; onError %s, error %s", eventInfo.Path(), action.Type, action.OnError.Type, errE)
|
log.Printf("path: %s; action: %s; onError %s, error %s", eventInfo.Path(), action.Type, aE.Type, errE)
|
||||||
|
}
|
||||||
|
if !contin {
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if err == nil && action.OnSuccess != nil {
|
} else {
|
||||||
_c, errS := runAction(action.OnSuccess, eventInfo)
|
for _, aS := range action.OnSuccess {
|
||||||
|
_c, errS := runAction(&aS, eventInfo)
|
||||||
contin = contin && _c
|
contin = contin && _c
|
||||||
if errS != nil {
|
if errS != nil {
|
||||||
log.Printf("path: %s; action: %s; onSuccess %s, error %s", eventInfo.Path(), action.Type, action.OnError.Type, errS)
|
log.Printf("path: %s; action: %s; onSuccess %s, error %s", eventInfo.Path(), action.Type, aS.Type, errS)
|
||||||
}
|
|
||||||
err = errS
|
err = errS
|
||||||
}
|
}
|
||||||
|
if !contin {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return contin, err
|
return contin, err
|
||||||
}
|
}
|
||||||
@ -165,11 +229,19 @@ func runAction(action *ActionConfig, eventInfo notify.EventInfo) (contin bool, e
|
|||||||
func actionHttp(action *ActionConfig, eventInfo notify.EventInfo) error {
|
func actionHttp(action *ActionConfig, eventInfo notify.EventInfo) error {
|
||||||
method := "POST"
|
method := "POST"
|
||||||
if action.Method != nil {
|
if action.Method != nil {
|
||||||
method = strings.ToUpper(*action.Method)
|
m, err := tpl2String(*action.Method, action, eventInfo)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
method = strings.ToUpper(m)
|
||||||
}
|
}
|
||||||
if action.URL == nil {
|
if action.URL == nil {
|
||||||
return fmt.Errorf("missing url in http action")
|
return fmt.Errorf("missing url in http action")
|
||||||
}
|
}
|
||||||
|
url, err := tpl2String(*action.URL, action, eventInfo)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
postData := bytes.NewBuffer([]byte{})
|
postData := bytes.NewBuffer([]byte{})
|
||||||
if method != "GET" {
|
if method != "GET" {
|
||||||
@ -180,11 +252,18 @@ func actionHttp(action *ActionConfig, eventInfo notify.EventInfo) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
postData = bytes.NewBuffer(postBytes)
|
postData = bytes.NewBuffer(postBytes)
|
||||||
|
} else {
|
||||||
|
p, err := tpl2String(*action.Content, action, eventInfo)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
log.Println("BODY: ", p)
|
||||||
|
postData = bytes.NewBufferString(p)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Printf("%s %s", method, *action.URL)
|
log.Printf("%s %s", method, url)
|
||||||
req, err := http.NewRequest(method, *action.URL, postData)
|
req, err := http.NewRequest(method, url, postData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -224,8 +303,7 @@ func actionMove(action *ActionConfig, eventInfo notify.EventInfo) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func actionDelete(action *ActionConfig, eventInfo notify.EventInfo) error {
|
func actionDelete(action *ActionConfig, eventInfo notify.EventInfo) error {
|
||||||
log.Println("DELETE")
|
return os.Remove(eventInfo.Path())
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func actionLog(action *ActionConfig, eventInfo notify.EventInfo) error {
|
func actionLog(action *ActionConfig, eventInfo notify.EventInfo) error {
|
||||||
@ -268,6 +346,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, directory := range conf.Directories {
|
for _, directory := range conf.Directories {
|
||||||
|
directory := directory
|
||||||
startWatcher(&directory)
|
startWatcher(&directory)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user