mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-05-13 15:09:42 +00:00
Feature: Faster start & stop times (#648)
* Updates starting and stopping routines to be a bit more parallel with less waiting required * Removes stop, removes debugging output * linting and test fixes * Add extra kill switch for exiting on exchange loading delay * Fixes fun math * breaks loop instead of switch. Moves param warns higher * Removes unceccary gos. passes in cfg to remove data race * Removes os signal processing. Fixes bad master merge
This commit is contained in:
@@ -2,17 +2,18 @@ package engine
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/thrasher-corp/gocryptotrader/communications"
|
||||
"github.com/thrasher-corp/gocryptotrader/communications/base"
|
||||
"github.com/thrasher-corp/gocryptotrader/engine/subsystem"
|
||||
"github.com/thrasher-corp/gocryptotrader/log"
|
||||
)
|
||||
|
||||
// commsManager starts the NTP manager
|
||||
type commsManager struct {
|
||||
started int32
|
||||
stopped int32
|
||||
shutdown chan struct{}
|
||||
relayMsg chan base.Event
|
||||
comms *communications.Communications
|
||||
@@ -23,8 +24,8 @@ func (c *commsManager) Started() bool {
|
||||
}
|
||||
|
||||
func (c *commsManager) Start() (err error) {
|
||||
if atomic.AddInt32(&c.started, 1) != 1 {
|
||||
return errors.New("communications manager already started")
|
||||
if !atomic.CompareAndSwapInt32(&c.started, 0, 1) {
|
||||
return fmt.Errorf("communications manager %w", subsystem.ErrSubSystemAlreadyStarted)
|
||||
}
|
||||
|
||||
defer func() {
|
||||
@@ -56,13 +57,11 @@ func (c *commsManager) GetStatus() (map[string]base.CommsStatus, error) {
|
||||
|
||||
func (c *commsManager) Stop() error {
|
||||
if atomic.LoadInt32(&c.started) == 0 {
|
||||
return errors.New("communications manager not started")
|
||||
return fmt.Errorf("communications manager %w", subsystem.ErrSubSystemNotStarted)
|
||||
}
|
||||
|
||||
if atomic.AddInt32(&c.stopped, 1) != 1 {
|
||||
return errors.New("communications manager is already stopped")
|
||||
}
|
||||
|
||||
defer func() {
|
||||
atomic.CompareAndSwapInt32(&c.started, 1, 0)
|
||||
}()
|
||||
close(c.shutdown)
|
||||
log.Debugln(log.CommunicationMgr, "Communications manager shutting down...")
|
||||
return nil
|
||||
@@ -82,8 +81,6 @@ func (c *commsManager) PushEvent(evt base.Event) {
|
||||
func (c *commsManager) run() {
|
||||
defer func() {
|
||||
// TO-DO shutdown comms connections for connected services (Slack etc)
|
||||
atomic.CompareAndSwapInt32(&c.stopped, 1, 0)
|
||||
atomic.CompareAndSwapInt32(&c.started, 1, 0)
|
||||
log.Debugln(log.CommunicationMgr, "Communications manager shutdown.")
|
||||
}()
|
||||
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
package engine
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/thrasher-corp/gocryptotrader/config"
|
||||
"github.com/thrasher-corp/gocryptotrader/connchecker"
|
||||
"github.com/thrasher-corp/gocryptotrader/engine/subsystem"
|
||||
"github.com/thrasher-corp/gocryptotrader/log"
|
||||
)
|
||||
|
||||
// connectionManager manages the connchecker
|
||||
type connectionManager struct {
|
||||
started int32
|
||||
stopped int32
|
||||
conn *connchecker.Checker
|
||||
}
|
||||
|
||||
@@ -23,8 +23,8 @@ func (c *connectionManager) Started() bool {
|
||||
|
||||
// Start starts an instance of the connection manager
|
||||
func (c *connectionManager) Start(conf *config.ConnectionMonitorConfig) error {
|
||||
if atomic.AddInt32(&c.started, 1) != 1 {
|
||||
return errors.New("connection manager already started")
|
||||
if !atomic.CompareAndSwapInt32(&c.started, 0, 1) {
|
||||
return fmt.Errorf("connection manager %w", subsystem.ErrSubSystemAlreadyStarted)
|
||||
}
|
||||
|
||||
log.Debugln(log.ConnectionMgr, "Connection manager starting...")
|
||||
@@ -44,17 +44,14 @@ func (c *connectionManager) Start(conf *config.ConnectionMonitorConfig) error {
|
||||
// Stop stops the connection manager
|
||||
func (c *connectionManager) Stop() error {
|
||||
if atomic.LoadInt32(&c.started) == 0 {
|
||||
return errors.New("connection manager not started")
|
||||
}
|
||||
|
||||
if atomic.AddInt32(&c.stopped, 1) != 1 {
|
||||
return errors.New("connection manager is already stopped")
|
||||
return fmt.Errorf("connection manager %w", subsystem.ErrSubSystemNotStarted)
|
||||
}
|
||||
defer func() {
|
||||
atomic.CompareAndSwapInt32(&c.started, 1, 0)
|
||||
}()
|
||||
|
||||
log.Debugln(log.ConnectionMgr, "Connection manager shutting down...")
|
||||
c.conn.Shutdown()
|
||||
atomic.CompareAndSwapInt32(&c.stopped, 1, 0)
|
||||
atomic.CompareAndSwapInt32(&c.started, 1, 0)
|
||||
log.Debugln(log.ConnectionMgr, "Connection manager stopped.")
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"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"
|
||||
)
|
||||
@@ -19,7 +20,6 @@ var (
|
||||
|
||||
type databaseManager struct {
|
||||
started int32
|
||||
stopped int32
|
||||
shutdown chan struct{}
|
||||
}
|
||||
|
||||
@@ -28,8 +28,8 @@ func (a *databaseManager) Started() bool {
|
||||
}
|
||||
|
||||
func (a *databaseManager) Start(bot *Engine) (err error) {
|
||||
if atomic.AddInt32(&a.started, 1) != 1 {
|
||||
return errors.New("database manager already started")
|
||||
if !atomic.CompareAndSwapInt32(&a.started, 0, 1) {
|
||||
return fmt.Errorf("database manager %w", subsystem.ErrSubSystemAlreadyStarted)
|
||||
}
|
||||
|
||||
defer func() {
|
||||
@@ -78,12 +78,11 @@ func (a *databaseManager) Start(bot *Engine) (err error) {
|
||||
|
||||
func (a *databaseManager) Stop() error {
|
||||
if atomic.LoadInt32(&a.started) == 0 {
|
||||
return errors.New("database manager not started")
|
||||
}
|
||||
|
||||
if atomic.AddInt32(&a.stopped, 1) != 1 {
|
||||
return errors.New("database manager is already stopping")
|
||||
return fmt.Errorf("database manager %w", subsystem.ErrSubSystemNotStarted)
|
||||
}
|
||||
defer func() {
|
||||
atomic.CompareAndSwapInt32(&a.started, 1, 0)
|
||||
}()
|
||||
|
||||
err := dbConn.SQL.Close()
|
||||
if err != nil {
|
||||
@@ -97,16 +96,11 @@ func (a *databaseManager) Stop() error {
|
||||
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()
|
||||
atomic.CompareAndSwapInt32(&a.stopped, 1, 0)
|
||||
atomic.CompareAndSwapInt32(&a.started, 1, 0)
|
||||
|
||||
bot.ServicesWG.Done()
|
||||
|
||||
log.Debugln(log.DatabaseMgr, "Database manager shutdown.")
|
||||
}()
|
||||
|
||||
@@ -115,7 +109,7 @@ func (a *databaseManager) run(bot *Engine) {
|
||||
case <-a.shutdown:
|
||||
return
|
||||
case <-t.C:
|
||||
a.checkConnection()
|
||||
go a.checkConnection()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -396,17 +396,16 @@ func (bot *Engine) Start() error {
|
||||
}
|
||||
|
||||
gctlog.Debugln(gctlog.Global, "Setting up exchanges..")
|
||||
bot.SetupExchanges()
|
||||
if bot.exchangeManager.Len() == 0 {
|
||||
return errors.New("no exchanges are loaded")
|
||||
err := bot.SetupExchanges()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if bot.Settings.EnableCommsRelayer {
|
||||
if err := bot.CommsManager.Start(); err != nil {
|
||||
if err = bot.CommsManager.Start(); err != nil {
|
||||
gctlog.Errorf(gctlog.Global, "Communications manager unable to start: %v\n", err)
|
||||
}
|
||||
}
|
||||
var err error
|
||||
if bot.Settings.EnableCoinmarketcapAnalysis ||
|
||||
bot.Settings.EnableCurrencyConverter ||
|
||||
bot.Settings.EnableCurrencyLayer ||
|
||||
@@ -556,6 +555,7 @@ func (bot *Engine) Stop() {
|
||||
gctlog.Errorf(gctlog.DispatchMgr, "Dispatch system unable to stop. Error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
if bot.Settings.EnableCoinmarketcapAnalysis ||
|
||||
bot.Settings.EnableCurrencyConverter ||
|
||||
bot.Settings.EnableCurrencyLayer ||
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"sync"
|
||||
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"github.com/thrasher-corp/gocryptotrader/config"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
||||
@@ -224,83 +225,62 @@ func (bot *Engine) LoadExchange(name string, useWG bool, wg *sync.WaitGroup) err
|
||||
return ErrExchangeFailedToLoad
|
||||
}
|
||||
|
||||
exch.SetDefaults()
|
||||
var localWG sync.WaitGroup
|
||||
localWG.Add(1)
|
||||
go func() {
|
||||
exch.SetDefaults()
|
||||
localWG.Done()
|
||||
}()
|
||||
exchCfg, err := bot.Config.GetExchangeConfig(name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if bot.Settings.EnableAllPairs {
|
||||
if exchCfg.CurrencyPairs != nil {
|
||||
bot.dryrunParamInteraction("enableallpairs")
|
||||
assets := exchCfg.CurrencyPairs.GetAssetTypes()
|
||||
for x := range assets {
|
||||
var pairs currency.Pairs
|
||||
pairs, err = exchCfg.CurrencyPairs.GetPairs(assets[x], false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
exchCfg.CurrencyPairs.StorePairs(assets[x], pairs, true)
|
||||
if bot.Settings.EnableAllPairs &&
|
||||
exchCfg.CurrencyPairs != nil {
|
||||
assets := exchCfg.CurrencyPairs.GetAssetTypes()
|
||||
for x := range assets {
|
||||
var pairs currency.Pairs
|
||||
pairs, err = exchCfg.CurrencyPairs.GetPairs(assets[x], false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
exchCfg.CurrencyPairs.StorePairs(assets[x], pairs, true)
|
||||
}
|
||||
}
|
||||
|
||||
if bot.Settings.EnableExchangeVerbose {
|
||||
bot.dryrunParamInteraction("exchangeverbose")
|
||||
exchCfg.Verbose = true
|
||||
}
|
||||
|
||||
if bot.Settings.EnableExchangeWebsocketSupport {
|
||||
bot.dryrunParamInteraction("exchangewebsocketsupport")
|
||||
if exchCfg.Features != nil {
|
||||
if exchCfg.Features.Supports.Websocket {
|
||||
exchCfg.Features.Enabled.Websocket = true
|
||||
}
|
||||
if exchCfg.Features != nil {
|
||||
if bot.Settings.EnableExchangeWebsocketSupport &&
|
||||
exchCfg.Features.Supports.Websocket {
|
||||
exchCfg.Features.Enabled.Websocket = true
|
||||
}
|
||||
}
|
||||
|
||||
if bot.Settings.EnableExchangeAutoPairUpdates {
|
||||
bot.dryrunParamInteraction("exchangeautopairupdates")
|
||||
if exchCfg.Features != nil {
|
||||
if exchCfg.Features.Supports.RESTCapabilities.AutoPairUpdates {
|
||||
exchCfg.Features.Enabled.AutoPairUpdates = true
|
||||
}
|
||||
if bot.Settings.EnableExchangeAutoPairUpdates &&
|
||||
exchCfg.Features.Supports.RESTCapabilities.AutoPairUpdates {
|
||||
exchCfg.Features.Enabled.AutoPairUpdates = true
|
||||
}
|
||||
}
|
||||
|
||||
if bot.Settings.DisableExchangeAutoPairUpdates {
|
||||
bot.dryrunParamInteraction("exchangedisableautopairupdates")
|
||||
if exchCfg.Features != nil {
|
||||
if bot.Settings.DisableExchangeAutoPairUpdates {
|
||||
if exchCfg.Features.Supports.RESTCapabilities.AutoPairUpdates {
|
||||
exchCfg.Features.Enabled.AutoPairUpdates = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if bot.Settings.HTTPUserAgent != "" {
|
||||
bot.dryrunParamInteraction("httpuseragent")
|
||||
exchCfg.HTTPUserAgent = bot.Settings.HTTPUserAgent
|
||||
}
|
||||
|
||||
if bot.Settings.HTTPProxy != "" {
|
||||
bot.dryrunParamInteraction("httpproxy")
|
||||
exchCfg.ProxyAddress = bot.Settings.HTTPProxy
|
||||
}
|
||||
|
||||
if bot.Settings.HTTPTimeout != exchange.DefaultHTTPTimeout {
|
||||
bot.dryrunParamInteraction("httptimeout")
|
||||
exchCfg.HTTPTimeout = bot.Settings.HTTPTimeout
|
||||
}
|
||||
|
||||
if bot.Settings.EnableExchangeHTTPDebugging {
|
||||
bot.dryrunParamInteraction("exchangehttpdebugging")
|
||||
exchCfg.HTTPDebugging = bot.Settings.EnableExchangeHTTPDebugging
|
||||
}
|
||||
|
||||
if bot.Settings.EnableAllExchanges {
|
||||
bot.dryrunParamInteraction("enableallexchanges")
|
||||
}
|
||||
|
||||
localWG.Wait()
|
||||
if !bot.Settings.EnableExchangeHTTPRateLimiter {
|
||||
log.Warnf(log.ExchangeSys,
|
||||
"Loaded exchange %s rate limiting has been turned off.\n",
|
||||
@@ -324,7 +304,6 @@ func (bot *Engine) LoadExchange(name string, useWG bool, wg *sync.WaitGroup) err
|
||||
}
|
||||
|
||||
bot.exchangeManager.add(exch)
|
||||
|
||||
base := exch.GetBase()
|
||||
if base.API.AuthenticatedSupport ||
|
||||
base.API.AuthenticatedWebsocketSupport {
|
||||
@@ -363,25 +342,65 @@ func (bot *Engine) LoadExchange(name string, useWG bool, wg *sync.WaitGroup) err
|
||||
}
|
||||
|
||||
// SetupExchanges sets up the exchanges used by the Bot
|
||||
func (bot *Engine) SetupExchanges() {
|
||||
func (bot *Engine) SetupExchanges() error {
|
||||
var wg sync.WaitGroup
|
||||
configs := bot.Config.GetAllExchangeConfigs()
|
||||
if bot.Settings.EnableAllPairs {
|
||||
bot.dryrunParamInteraction("enableallpairs")
|
||||
}
|
||||
if bot.Settings.EnableAllExchanges {
|
||||
bot.dryrunParamInteraction("enableallexchanges")
|
||||
}
|
||||
if bot.Settings.EnableExchangeVerbose {
|
||||
bot.dryrunParamInteraction("exchangeverbose")
|
||||
}
|
||||
if bot.Settings.EnableExchangeWebsocketSupport {
|
||||
bot.dryrunParamInteraction("exchangewebsocketsupport")
|
||||
}
|
||||
if bot.Settings.EnableExchangeAutoPairUpdates {
|
||||
bot.dryrunParamInteraction("exchangeautopairupdates")
|
||||
}
|
||||
if bot.Settings.DisableExchangeAutoPairUpdates {
|
||||
bot.dryrunParamInteraction("exchangedisableautopairupdates")
|
||||
}
|
||||
if bot.Settings.HTTPUserAgent != "" {
|
||||
bot.dryrunParamInteraction("httpuseragent")
|
||||
}
|
||||
if bot.Settings.HTTPProxy != "" {
|
||||
bot.dryrunParamInteraction("httpproxy")
|
||||
}
|
||||
if bot.Settings.HTTPTimeout != exchange.DefaultHTTPTimeout {
|
||||
bot.dryrunParamInteraction("httptimeout")
|
||||
}
|
||||
if bot.Settings.EnableExchangeHTTPDebugging {
|
||||
bot.dryrunParamInteraction("exchangehttpdebugging")
|
||||
}
|
||||
|
||||
for x := range configs {
|
||||
if !configs[x].Enabled && !bot.Settings.EnableAllExchanges {
|
||||
log.Debugf(log.ExchangeSys, "%s: Exchange support: Disabled\n", configs[x].Name)
|
||||
continue
|
||||
}
|
||||
err := bot.LoadExchange(configs[x].Name, true, &wg)
|
||||
if err != nil {
|
||||
log.Errorf(log.ExchangeSys, "LoadExchange %s failed: %s\n", configs[x].Name, err)
|
||||
continue
|
||||
}
|
||||
log.Debugf(log.ExchangeSys,
|
||||
"%s: Exchange support: Enabled (Authenticated API support: %s - Verbose mode: %s).\n",
|
||||
configs[x].Name,
|
||||
common.IsEnabled(configs[x].API.AuthenticatedSupport),
|
||||
common.IsEnabled(configs[x].Verbose),
|
||||
)
|
||||
wg.Add(1)
|
||||
cfg := configs[x]
|
||||
go func(currCfg config.ExchangeConfig) {
|
||||
defer wg.Done()
|
||||
err := bot.LoadExchange(currCfg.Name, true, &wg)
|
||||
if err != nil {
|
||||
log.Errorf(log.ExchangeSys, "LoadExchange %s failed: %s\n", currCfg.Name, err)
|
||||
return
|
||||
}
|
||||
log.Debugf(log.ExchangeSys,
|
||||
"%s: Exchange support: Enabled (Authenticated API support: %s - Verbose mode: %s).\n",
|
||||
currCfg.Name,
|
||||
common.IsEnabled(currCfg.API.AuthenticatedSupport),
|
||||
common.IsEnabled(currCfg.Verbose),
|
||||
)
|
||||
}(cfg)
|
||||
}
|
||||
wg.Wait()
|
||||
if len(bot.exchangeManager.exchanges) == 0 {
|
||||
return errors.New("no exchanges are loaded")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"github.com/thrasher-corp/gocryptotrader/communications/base"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
"github.com/thrasher-corp/gocryptotrader/engine/subsystem"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
|
||||
"github.com/thrasher-corp/gocryptotrader/log"
|
||||
@@ -137,7 +138,7 @@ func (o *orderManager) Start(bot *Engine) error {
|
||||
return errors.New("cannot start with nil bot")
|
||||
}
|
||||
if !atomic.CompareAndSwapInt32(&o.started, 0, 1) {
|
||||
return errors.New("could not start order manager")
|
||||
return fmt.Errorf("order manager %w", subsystem.ErrSubSystemAlreadyStarted)
|
||||
}
|
||||
log.Debugln(log.OrderBook, "Order manager starting...")
|
||||
|
||||
@@ -152,14 +153,10 @@ func (o *orderManager) Start(bot *Engine) error {
|
||||
// Stop will attempt to shutdown the orderManager
|
||||
func (o *orderManager) Stop() error {
|
||||
if atomic.LoadInt32(&o.started) == 0 {
|
||||
return errors.New("order manager not started")
|
||||
return fmt.Errorf("order manager %w", subsystem.ErrSubSystemNotStarted)
|
||||
}
|
||||
|
||||
if !atomic.CompareAndSwapInt32(&o.stopped, 0, 1) {
|
||||
return errors.New("order manager is already stopped")
|
||||
}
|
||||
defer func() {
|
||||
atomic.CompareAndSwapInt32(&o.stopped, 1, 0)
|
||||
atomic.CompareAndSwapInt32(&o.started, 1, 0)
|
||||
}()
|
||||
|
||||
@@ -191,7 +188,7 @@ func (o *orderManager) run() {
|
||||
o.gracefulShutdown()
|
||||
return
|
||||
case <-tick.C:
|
||||
o.processOrders()
|
||||
go o.processOrders()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,7 +30,6 @@ type orderStore struct {
|
||||
|
||||
type orderManager struct {
|
||||
started int32
|
||||
stopped int32
|
||||
shutdown chan struct{}
|
||||
orderStore orderStore
|
||||
cfg orderManagerConfig
|
||||
|
||||
@@ -2,9 +2,11 @@ package engine
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/thrasher-corp/gocryptotrader/engine/subsystem"
|
||||
"github.com/thrasher-corp/gocryptotrader/log"
|
||||
"github.com/thrasher-corp/gocryptotrader/portfolio"
|
||||
)
|
||||
@@ -15,9 +17,9 @@ var (
|
||||
)
|
||||
|
||||
type portfolioManager struct {
|
||||
started int32
|
||||
stopped int32
|
||||
shutdown chan struct{}
|
||||
started int32
|
||||
processing int32
|
||||
shutdown chan struct{}
|
||||
}
|
||||
|
||||
func (p *portfolioManager) Started() bool {
|
||||
@@ -39,9 +41,12 @@ func (p *portfolioManager) Start() error {
|
||||
return nil
|
||||
}
|
||||
func (p *portfolioManager) Stop() error {
|
||||
if atomic.AddInt32(&p.stopped, 1) != 1 {
|
||||
return errors.New("portfolio manager is already stopped")
|
||||
if atomic.LoadInt32(&p.started) == 0 {
|
||||
return fmt.Errorf("portfolio manager %w", subsystem.ErrSubSystemNotStarted)
|
||||
}
|
||||
defer func() {
|
||||
atomic.CompareAndSwapInt32(&p.started, 1, 0)
|
||||
}()
|
||||
|
||||
log.Debugln(log.PortfolioMgr, "Portfolio manager shutting down...")
|
||||
close(p.shutdown)
|
||||
@@ -53,25 +58,26 @@ func (p *portfolioManager) run() {
|
||||
Bot.ServicesWG.Add(1)
|
||||
tick := time.NewTicker(Bot.Settings.PortfolioManagerDelay)
|
||||
defer func() {
|
||||
atomic.CompareAndSwapInt32(&p.stopped, 1, 0)
|
||||
atomic.CompareAndSwapInt32(&p.started, 1, 0)
|
||||
tick.Stop()
|
||||
Bot.ServicesWG.Done()
|
||||
log.Debugf(log.PortfolioMgr, "Portfolio manager shutdown.")
|
||||
}()
|
||||
|
||||
p.processPortfolio()
|
||||
go p.processPortfolio()
|
||||
for {
|
||||
select {
|
||||
case <-p.shutdown:
|
||||
return
|
||||
case <-tick.C:
|
||||
p.processPortfolio()
|
||||
go p.processPortfolio()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (p *portfolioManager) processPortfolio() {
|
||||
if !atomic.CompareAndSwapInt32(&p.processing, 0, 1) {
|
||||
return
|
||||
}
|
||||
pf := portfolio.GetPortfolio()
|
||||
data := pf.GetPortfolioGroupedCoin()
|
||||
for key, value := range data {
|
||||
@@ -90,4 +96,5 @@ func (p *portfolioManager) processPortfolio() {
|
||||
value)
|
||||
}
|
||||
SeedExchangeAccountInfo(Bot.GetAllEnabledExchangeAccountInfo().Data)
|
||||
atomic.CompareAndSwapInt32(&p.processing, 1, 0)
|
||||
}
|
||||
|
||||
@@ -1,20 +1,21 @@
|
||||
package subsystem
|
||||
|
||||
const (
|
||||
// ErrSubSystemAlreadyStarted message to return when a subsystem is already started
|
||||
ErrSubSystemAlreadyStarted = "manager already started"
|
||||
// ErrSubSystemAlreadyStopped message to return when a subsystem is already stopped
|
||||
ErrSubSystemAlreadyStopped = "already stopped"
|
||||
// ErrSubSystemNotStarted message to return when subsystem not started
|
||||
ErrSubSystemNotStarted = "not started"
|
||||
import "errors"
|
||||
|
||||
const (
|
||||
// MsgSubSystemStarting message to return when subsystem is starting up
|
||||
MsgSubSystemStarting = "manager starting..."
|
||||
// MsgSubSystemStarted message to return when subsystem has started
|
||||
MsgSubSystemStarted = "started."
|
||||
|
||||
// MsgSubSystemShuttingDown message to return when a subsystem is shutting down
|
||||
MsgSubSystemShuttingDown = "shutting down..."
|
||||
// MsgSubSystemShutdown message to return when a subsystem has shutdown
|
||||
MsgSubSystemShutdown = "manager shutdown."
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrSubSystemAlreadyStarted message to return when a subsystem is already started
|
||||
ErrSubSystemAlreadyStarted = errors.New("manager already started")
|
||||
// ErrSubSystemNotStarted message to return when subsystem not started
|
||||
ErrSubSystemNotStarted = errors.New("not started")
|
||||
)
|
||||
|
||||
@@ -22,10 +22,9 @@ func TestNewCurrencyPairSyncer(t *testing.T) {
|
||||
Bot.Settings.DisableExchangeAutoPairUpdates = true
|
||||
Bot.Settings.EnableExchangeWebsocketSupport = true
|
||||
|
||||
Bot.SetupExchanges()
|
||||
|
||||
err = Bot.SetupExchanges()
|
||||
if err != nil {
|
||||
t.Log("failed to start exchange syncer")
|
||||
t.Log(err)
|
||||
}
|
||||
|
||||
Bot.ExchangeCurrencyPairManager, err = NewCurrencyPairSyncer(CurrencyPairSyncerConfig{
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/thrasher-corp/gocryptotrader/engine/subsystem"
|
||||
"github.com/thrasher-corp/gocryptotrader/log"
|
||||
ntpclient "github.com/thrasher-corp/gocryptotrader/ntpclient"
|
||||
)
|
||||
@@ -20,50 +21,41 @@ var (
|
||||
|
||||
// ntpManager starts the NTP manager
|
||||
type ntpManager struct {
|
||||
started int32
|
||||
stopped int32
|
||||
inititalCheck bool
|
||||
shutdown chan struct{}
|
||||
started int32
|
||||
initialCheck bool
|
||||
shutdown chan struct{}
|
||||
}
|
||||
|
||||
func (n *ntpManager) Started() bool {
|
||||
return atomic.LoadInt32(&n.started) == 1
|
||||
}
|
||||
|
||||
func (n *ntpManager) Start() (err error) {
|
||||
if atomic.AddInt32(&n.started, 1) != 1 {
|
||||
return errors.New("NTP manager already started")
|
||||
func (n *ntpManager) Start() error {
|
||||
if !atomic.CompareAndSwapInt32(&n.started, 0, 1) {
|
||||
return fmt.Errorf("NTP manager %w", subsystem.ErrSubSystemAlreadyStarted)
|
||||
}
|
||||
|
||||
var disable bool
|
||||
defer func() {
|
||||
if err != nil || disable {
|
||||
atomic.CompareAndSwapInt32(&n.started, 1, 0)
|
||||
}
|
||||
}()
|
||||
|
||||
if Bot.Config.NTPClient.Level == -1 {
|
||||
err = errors.New("NTP client disabled")
|
||||
return
|
||||
atomic.CompareAndSwapInt32(&n.started, 1, 0)
|
||||
return errors.New("NTP client disabled")
|
||||
}
|
||||
|
||||
log.Debugln(log.TimeMgr, "NTP manager starting...")
|
||||
if Bot.Config.NTPClient.Level == 0 && *Bot.Config.Logging.Enabled {
|
||||
// Initial NTP check (prompts user on how we should proceed)
|
||||
n.inititalCheck = true
|
||||
|
||||
n.initialCheck = true
|
||||
// Sometimes the NTP client can have transient issues due to UDP, try
|
||||
// the default retry limits before giving up
|
||||
check:
|
||||
for i := 0; i < NTPRetryLimit; i++ {
|
||||
err = n.processTime()
|
||||
err := n.processTime()
|
||||
switch err {
|
||||
case nil:
|
||||
break
|
||||
break check
|
||||
case errNTPDisabled:
|
||||
log.Debugln(log.TimeMgr, "NTP manager: User disabled NTP prompts. Exiting.")
|
||||
disable = true
|
||||
err = nil
|
||||
return
|
||||
atomic.CompareAndSwapInt32(&n.started, 1, 0)
|
||||
return nil
|
||||
default:
|
||||
if i == NTPRetryLimit-1 {
|
||||
return err
|
||||
@@ -79,15 +71,13 @@ func (n *ntpManager) Start() (err error) {
|
||||
|
||||
func (n *ntpManager) Stop() error {
|
||||
if atomic.LoadInt32(&n.started) == 0 {
|
||||
return errors.New("NTP manager not started")
|
||||
return fmt.Errorf("NTP manager %w", subsystem.ErrSubSystemNotStarted)
|
||||
}
|
||||
|
||||
if atomic.AddInt32(&n.stopped, 1) != 1 {
|
||||
return errors.New("NTP manager is already stopped")
|
||||
}
|
||||
|
||||
close(n.shutdown)
|
||||
defer func() {
|
||||
atomic.CompareAndSwapInt32(&n.started, 1, 0)
|
||||
}()
|
||||
log.Debugln(log.TimeMgr, "NTP manager shutting down...")
|
||||
close(n.shutdown)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -95,8 +85,6 @@ func (n *ntpManager) run() {
|
||||
t := time.NewTicker(NTPCheckInterval)
|
||||
defer func() {
|
||||
t.Stop()
|
||||
atomic.CompareAndSwapInt32(&n.stopped, 1, 0)
|
||||
atomic.CompareAndSwapInt32(&n.started, 1, 0)
|
||||
log.Debugln(log.TimeMgr, "NTP manager shutdown.")
|
||||
}()
|
||||
|
||||
@@ -105,7 +93,10 @@ func (n *ntpManager) run() {
|
||||
case <-n.shutdown:
|
||||
return
|
||||
case <-t.C:
|
||||
n.processTime()
|
||||
err := n.processTime()
|
||||
if err != nil {
|
||||
log.Error(log.TimeMgr, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -116,15 +107,20 @@ func (n *ntpManager) FetchNTPTime() time.Time {
|
||||
|
||||
func (n *ntpManager) processTime() error {
|
||||
NTPTime := n.FetchNTPTime()
|
||||
|
||||
currentTime := time.Now()
|
||||
NTPcurrentTimeDifference := NTPTime.Sub(currentTime)
|
||||
diff := NTPTime.Sub(currentTime)
|
||||
configNTPTime := *Bot.Config.NTPClient.AllowedDifference
|
||||
configNTPNegativeTime := (*Bot.Config.NTPClient.AllowedNegativeDifference - (*Bot.Config.NTPClient.AllowedNegativeDifference * 2))
|
||||
if NTPcurrentTimeDifference > configNTPTime || NTPcurrentTimeDifference < configNTPNegativeTime {
|
||||
log.Warnf(log.TimeMgr, "NTP manager: Time out of sync (NTP): %v | (time.Now()): %v | (Difference): %v | (Allowed): +%v / %v\n", NTPTime, currentTime, NTPcurrentTimeDifference, configNTPTime, configNTPNegativeTime)
|
||||
if n.inititalCheck {
|
||||
n.inititalCheck = false
|
||||
negDiff := *Bot.Config.NTPClient.AllowedNegativeDifference
|
||||
configNTPNegativeTime := -negDiff
|
||||
if diff > configNTPTime || diff < configNTPNegativeTime {
|
||||
log.Warnf(log.TimeMgr, "NTP manager: Time out of sync (NTP): %v | (time.Now()): %v | (Difference): %v | (Allowed): +%v / %v\n",
|
||||
NTPTime,
|
||||
currentTime,
|
||||
diff,
|
||||
configNTPTime,
|
||||
configNTPNegativeTime)
|
||||
if n.initialCheck {
|
||||
n.initialCheck = false
|
||||
disable, err := Bot.Config.DisableNTPCheck(os.Stdin)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to disable NTP check: %s", err)
|
||||
|
||||
Reference in New Issue
Block a user