forked from thrasher-corp/gocryptotrader
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdatabase.go
132 lines (110 loc) · 3.11 KB
/
database.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 engine
import (
"errors"
"fmt"
"sync/atomic"
"time"
"github.com/thrasher-corp/gocryptotrader/database"
dbpsql "github.com/thrasher-corp/gocryptotrader/database/drivers/postgres"
dbsqlite3 "github.com/thrasher-corp/gocryptotrader/database/drivers/sqlite3"
"github.com/thrasher-corp/gocryptotrader/engine/subsystem"
"github.com/thrasher-corp/gocryptotrader/log"
"github.com/thrasher-corp/sqlboiler/boil"
)
var (
dbConn *database.Instance
)
type databaseManager struct {
started int32
shutdown chan struct{}
}
func (a *databaseManager) Started() bool {
return atomic.LoadInt32(&a.started) == 1
}
func (a *databaseManager) Start(bot *Engine) (err error) {
if !atomic.CompareAndSwapInt32(&a.started, 0, 1) {
return fmt.Errorf("database manager %w", subsystem.ErrSubSystemAlreadyStarted)
}
defer func() {
if err != nil {
atomic.CompareAndSwapInt32(&a.started, 1, 0)
}
}()
log.Debugln(log.DatabaseMgr, "Database manager starting...")
a.shutdown = make(chan struct{})
if bot.Config.Database.Enabled {
if bot.Config.Database.Driver == database.DBPostgreSQL {
log.Debugf(log.DatabaseMgr,
"Attempting to establish database connection to host %s/%s utilising %s driver\n",
bot.Config.Database.Host,
bot.Config.Database.Database,
bot.Config.Database.Driver)
dbConn, err = dbpsql.Connect()
} else if bot.Config.Database.Driver == database.DBSQLite ||
bot.Config.Database.Driver == database.DBSQLite3 {
log.Debugf(log.DatabaseMgr,
"Attempting to establish database connection to %s utilising %s driver\n",
bot.Config.Database.Database,
bot.Config.Database.Driver)
dbConn, err = dbsqlite3.Connect()
}
if err != nil {
return fmt.Errorf("database failed to connect: %v Some features that utilise a database will be unavailable", err)
}
dbConn.Connected = true
DBLogger := database.Logger{}
if bot.Config.Database.Verbose {
boil.DebugMode = true
boil.DebugWriter = DBLogger
}
go a.run(bot)
return nil
}
return errors.New("database support disabled")
}
func (a *databaseManager) Stop() error {
if atomic.LoadInt32(&a.started) == 0 {
return fmt.Errorf("database manager %w", subsystem.ErrSubSystemNotStarted)
}
defer func() {
atomic.CompareAndSwapInt32(&a.started, 1, 0)
}()
err := dbConn.SQL.Close()
if err != nil {
log.Errorf(log.DatabaseMgr, "Failed to close database: %v", err)
}
close(a.shutdown)
return nil
}
func (a *databaseManager) run(bot *Engine) {
log.Debugln(log.DatabaseMgr, "Database manager started.")
bot.ServicesWG.Add(1)
t := time.NewTicker(time.Second * 2)
defer func() {
t.Stop()
bot.ServicesWG.Done()
log.Debugln(log.DatabaseMgr, "Database manager shutdown.")
}()
for {
select {
case <-a.shutdown:
return
case <-t.C:
go a.checkConnection()
}
}
}
func (a *databaseManager) checkConnection() {
dbConn.Mu.Lock()
defer dbConn.Mu.Unlock()
err := dbConn.SQL.Ping()
if err != nil {
log.Errorf(log.DatabaseMgr, "Database connection error: %v\n", err)
dbConn.Connected = false
return
}
if !dbConn.Connected {
log.Info(log.DatabaseMgr, "Database connection reestablished")
dbConn.Connected = true
}
}