@@ -3,86 +3,81 @@ package main
3
3
import (
4
4
"database/sql"
5
5
"os"
6
- "time"
6
+ "os/signal"
7
+ "syscall"
7
8
8
9
"github.com/evalphobia/logrus_sentry"
9
10
_ "github.com/lib/pq"
10
11
"github.com/nyaruka/ezconf"
12
+ indexer "github.com/nyaruka/rp-indexer"
11
13
"github.com/nyaruka/rp-indexer/indexers"
12
14
log "github.com/sirupsen/logrus"
13
15
)
14
16
15
- type config struct {
16
- ElasticURL string `help:"the url for our elastic search instance"`
17
- DB string `help:"the connection string for our database"`
18
- Index string `help:"the alias for our contact index"`
19
- Poll int `help:"the number of seconds to wait between checking for updated contacts"`
20
- Rebuild bool `help:"whether to rebuild the index, swapping it when complete, then exiting (default false)"`
21
- Cleanup bool `help:"whether to remove old indexes after a rebuild"`
22
- LogLevel string `help:"the log level, one of error, warn, info, debug"`
23
- SentryDSN string `help:"the sentry configuration to log errors to, if any"`
24
- }
25
-
26
17
func main () {
27
- config := config {
28
- ElasticURL : "http://localhost:9200" ,
29
- DB : "postgres://localhost/temba?sslmode=disable" ,
30
- Index : "contacts" ,
31
- Poll : 5 ,
32
- Rebuild : false ,
33
- Cleanup : false ,
34
- LogLevel : "info" ,
35
- }
36
- loader := ezconf .NewLoader (& config , "indexer" , "Indexes RapidPro contacts to ElasticSearch" , []string {"indexer.toml" })
18
+ cfg := indexer .NewDefaultConfig ()
19
+ loader := ezconf .NewLoader (cfg , "indexer" , "Indexes RapidPro contacts to ElasticSearch" , []string {"indexer.toml" })
37
20
loader .MustLoad ()
38
21
39
22
// configure our logger
40
23
log .SetOutput (os .Stdout )
41
24
log .SetFormatter (& log.TextFormatter {})
42
25
43
- level , err := log .ParseLevel (config .LogLevel )
26
+ level , err := log .ParseLevel (cfg .LogLevel )
44
27
if err != nil {
45
28
log .Fatalf ("Invalid log level '%s'" , level )
46
29
}
47
30
log .SetLevel (level )
48
31
49
32
// if we have a DSN entry, try to initialize it
50
- if config .SentryDSN != "" {
51
- hook , err := logrus_sentry .NewSentryHook (config .SentryDSN , []log.Level {log .PanicLevel , log .FatalLevel , log .ErrorLevel })
33
+ if cfg .SentryDSN != "" {
34
+ hook , err := logrus_sentry .NewSentryHook (cfg .SentryDSN , []log.Level {log .PanicLevel , log .FatalLevel , log .ErrorLevel })
52
35
hook .Timeout = 0
53
36
hook .StacktraceConfiguration .Enable = true
54
37
hook .StacktraceConfiguration .Skip = 4
55
38
hook .StacktraceConfiguration .Context = 5
56
39
if err != nil {
57
- log .Fatalf ("invalid sentry DSN: '%s': %s" , config .SentryDSN , err )
40
+ log .Fatalf ("invalid sentry DSN: '%s': %s" , cfg .SentryDSN , err )
58
41
}
59
42
log .StandardLogger ().Hooks .Add (hook )
60
43
}
61
44
62
- db , err := sql .Open ("postgres" , config .DB )
45
+ db , err := sql .Open ("postgres" , cfg .DB )
63
46
if err != nil {
64
- log .Fatal ( err )
47
+ log .Fatalf ( "unable to connect to database" )
65
48
}
66
49
67
- ci := indexers .NewContactIndexer (config .ElasticURL , config .Index , 500 )
68
-
69
- for {
70
- _ , err := ci .Index (db , config .Rebuild , config .Cleanup )
50
+ idxrs := []indexers.Indexer {
51
+ indexers .NewContactIndexer (cfg .ElasticURL , cfg .Index , 500 ),
52
+ }
71
53
72
- if err != nil {
73
- if config . Rebuild {
74
- log . WithField ( " index" , config . Index ). WithError ( err ). Fatal ( "error during rebuilding" )
75
- } else {
76
- log . WithField ( "index" , config . Index ). WithError ( err ). Error ( "error during indexing" )
77
- }
54
+ if cfg . Rebuild {
55
+ // if rebuilding, just do a complete index and quit. In future when we support multiple indexers,
56
+ // the rebuild argument can be become the name of the index to rebuild, e.g. --rebuild=contacts
57
+ idxr := idxrs [ 0 ]
58
+ if _ , err := idxr . Index ( db , true , cfg . Cleanup ); err != nil {
59
+ log . WithField ( "indexer" , idxr . Name ()). WithError ( err ). Fatal ( "error during rebuilding" )
78
60
}
61
+ } else {
62
+ d := indexer .NewDaemon (cfg , db , idxrs )
63
+ d .Start ()
79
64
80
- // if we were rebuilding then we're done
81
- if config .Rebuild {
82
- os .Exit (0 )
83
- }
65
+ handleSignals (d )
66
+ }
67
+ }
84
68
85
- // sleep a bit before starting again
86
- time .Sleep (time .Second * 5 )
69
+ // handleSignals takes care of trapping quit, interrupt or terminate signals and doing the right thing
70
+ func handleSignals (d * indexer.Daemon ) {
71
+ sigs := make (chan os.Signal , 1 )
72
+ signal .Notify (sigs , syscall .SIGINT , syscall .SIGTERM , syscall .SIGQUIT )
73
+
74
+ for {
75
+ sig := <- sigs
76
+ switch sig {
77
+ case syscall .SIGINT , syscall .SIGTERM , syscall .SIGQUIT :
78
+ log .WithField ("signal" , sig ).Info ("received exit signal, exiting" )
79
+ d .Stop ()
80
+ return
81
+ }
87
82
}
88
83
}
0 commit comments