-
Notifications
You must be signed in to change notification settings - Fork 66
/
main.go
132 lines (118 loc) · 3.11 KB
/
main.go
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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
package main
import (
"context"
"fmt"
"os"
"os/signal"
"runtime/debug"
"syscall"
"github.com/cybertec-postgresql/pg_timetable/internal/api"
"github.com/cybertec-postgresql/pg_timetable/internal/config"
"github.com/cybertec-postgresql/pg_timetable/internal/log"
"github.com/cybertec-postgresql/pg_timetable/internal/pgengine"
"github.com/cybertec-postgresql/pg_timetable/internal/scheduler"
)
/**
* pg_timetable is the daemon application responsible to execute scheduled SQL tasks that cannot be triggered by the
* PostgreSQL server (PostgreSQL does not support time triggers).
*
* This application may run on the same machine as PostgreSQL server and must grant full access permission to the
* timetable tables.
*/
var pge *pgengine.PgEngine
// SetupCloseHandler creates a 'listener' on a new goroutine which will notify the
// program if it receives an interrupt from the OS. We then handle this by calling
// our clean up procedure and exiting the program.
func SetupCloseHandler(cancel context.CancelFunc) {
c := make(chan os.Signal, 2)
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
go func() {
<-c
cancel()
exitCode = ExitCodeUserCancel
}()
}
const (
ExitCodeOK int = iota
ExitCodeConfigError
ExitCodeDBEngineError
ExitCodeUpgradeError
ExitCodeUserCancel
ExitCodeShutdownCommand
ExitCodeFatalError
)
var exitCode = ExitCodeOK
// version output variables
var (
commit = "000000"
version = "master"
date = "unknown"
dbapi = "00629"
)
func printVersion() {
fmt.Printf(`pg_timetable:
Version: %s
DB Schema: %s
Git Commit: %s
Built: %s
`, version, dbapi, commit, date)
}
func main() {
cmdOpts, err := config.NewConfig(os.Stdout)
if err != nil {
if cmdOpts != nil && cmdOpts.VersionOnly() {
printVersion()
return
}
fmt.Println("Configuration error: ", err)
exitCode = ExitCodeConfigError
return
}
if cmdOpts.Version {
printVersion()
}
logger := log.Init(cmdOpts.Logging)
ctx, cancel := context.WithCancel(context.Background())
SetupCloseHandler(cancel)
defer func() {
cancel()
if err := recover(); err != nil {
exitCode = ExitCodeFatalError
logger.WithField("callstack", string(debug.Stack())).Error(err)
}
os.Exit(exitCode)
}()
apiserver := api.Init(cmdOpts.RESTApi, logger)
if pge, err = pgengine.New(ctx, *cmdOpts, logger); err != nil {
logger.WithError(err).Error("Connection failed")
exitCode = ExitCodeDBEngineError
return
}
defer pge.Finalize()
if cmdOpts.Start.Upgrade {
if err := pge.MigrateDb(ctx); err != nil {
logger.WithError(err).Error("Upgrade failed")
exitCode = ExitCodeUpgradeError
return
}
} else {
if upgrade, err := pge.CheckNeedMigrateDb(ctx); upgrade || err != nil {
if upgrade {
logger.Error("You need to upgrade your database before proceeding, use --upgrade option")
}
if err != nil {
logger.WithError(err).Error("Migration check failed")
}
exitCode = ExitCodeUpgradeError
return
}
}
if cmdOpts.Start.Init {
return
}
sch := scheduler.New(pge, logger)
apiserver.APIHandler = sch
if sch.Run(ctx) == scheduler.ShutdownStatus {
exitCode = ExitCodeShutdownCommand
}
}