summaryrefslogtreecommitdiff
path: root/main.go
blob: 515407f4559b3adcc24ebb686aaa446eaca30346 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
package main

import (
	"bufio"
	"fmt"
	"log"
	"os"
	"path/filepath"
	"regexp"
	"strings"
	"time"

	"github.com/robfig/cron/v3"
)

type inputLine struct {
	Schedule string
	Task     string
}

var lastSeenInput = map[inputLine]struct{}{}

func main() {
	p, err := inputFilePath()
	if err != nil {
		log.Fatalf("getting input file: %s", err)
	}

	c := cron.New()

	for {
		input, err := readInput(p)
		if err != nil {
			log.Printf("reading input: %s", err)
		}
		changed := inputChanged(lastSeenInput, input)
		if changed {
			fmt.Println("changed!")
			lastSeenInput = input
			c.Stop()
			c := cron.New()
			err := addJobs(c)
			if err != nil {
				log.Printf("adding jobs: %s", err)
			}
			c.Start()
		} else {
			fmt.Println("not changed!")
		}

		time.Sleep(time.Minute) // re-read the input file every minute
	}

}

func inputFilePath() (string, error) {
	args := os.Args
	if len(args) != 2 {
		return "", fmt.Errorf("expected one argument (input file path), got %d", len(args)-1)
	}
	p := filepath.Clean(args[1])

	// While we're here, check that the input path actually exists and
	// is stat-able.
	if _, err := os.Stat(p); err != nil {
		return "", fmt.Errorf("cannot stat input file: %w", err)
	}

	return p, nil
}

var inputFileRe = regexp.MustCompile(`([^\s]+\s+[^\s]+\s+[^\s]+\s+[^\s]+\s+[^\s]+)\s+(.*)`)

func readInput(p string) (map[inputLine]struct{}, error) {
	input := map[inputLine]struct{}{}

	f, err := os.Open(p)
	if err != nil {
		return nil, fmt.Errorf("opening '%s': %w", p, err)
	}
	defer f.Close()

	scanner := bufio.NewScanner(f)
	for scanner.Scan() {
		line := strings.TrimSpace(scanner.Text())
		if line == "" {
			continue
		}

		matches := inputFileRe.FindStringSubmatch(line)
		if matches == nil || len(matches) != 1+2 {
			log.Printf("failed to parse input line: '%s'", line)
		}

		input[inputLine{Schedule: matches[1], Task: matches[2]}] = struct{}{}
	}

	if err := scanner.Err(); err != nil {
		return nil, fmt.Errorf("scanning: %w", err)
	}

	return input, nil
}

func inputChanged(old, new map[inputLine]struct{}) bool {
	if len(new) != len(old) {
		return true
	}
	for k := range old {
		if _, ok := new[k]; !ok {
			return true
		}
	}
	return false
}

func addJobs(c *cron.Cron) error { return nil }