This repository has been archived on 2022-11-30. You can view files and clone it, but cannot push or open issues or pull requests.
tacitus/ops/validator.go

153 lines
3.0 KiB
Go
Raw Normal View History

2017-10-10 10:17:00 -07:00
package ops
import (
"github.com/kcotugno/tacitus"
2017-10-05 19:33:50 -07:00
"github.com/kcotugno/tacitus/gdax"
2017-10-05 19:33:50 -07:00
"sort"
"time"
)
2017-10-10 10:14:49 -07:00
type byTradeId []tacitus.Trade
2017-10-05 19:33:50 -07:00
2017-10-10 10:14:49 -07:00
func (t byTradeId) Len() int { return len(t) }
func (t byTradeId) Swap(i, j int) { t[i], t[j] = t[j], t[i] }
func (t byTradeId) Less(i, j int) bool { return t[i].TradeId > t[j].TradeId }
2017-10-05 19:33:50 -07:00
2017-10-10 10:17:00 -07:00
type Validator struct {
Database tacitus.DatabaseClientService
Logger tacitus.Logger
2017-10-10 10:14:49 -07:00
Products []string
2017-10-19 21:55:42 -07:00
done chan struct{}
stopped bool
dirty bool
}
2017-10-10 10:17:00 -07:00
func (v *Validator) Stop() {
2017-10-19 21:55:42 -07:00
if v.done != nil && !v.stopped {
v.done <- struct{}{}
v.stopped = true
}
}
2017-10-10 10:17:00 -07:00
func (v *Validator) Start(frequency time.Duration) {
2017-10-19 21:25:40 -07:00
if v.dirty == true {
return
}
v.dirty = true
v.done = make(chan struct{})
go func() {
2017-10-19 21:25:40 -07:00
ticker := time.NewTicker(frequency)
var done bool
2017-10-19 21:33:20 -07:00
var running bool
emitDone := make(chan struct{})
for !done {
select {
case <-v.done:
2017-10-19 21:57:07 -07:00
v.Logger.Info("validator: STOP")
done = true
2017-10-19 21:25:40 -07:00
ticker.Stop()
case <-ticker.C:
2017-10-19 21:33:20 -07:00
if running {
break
}
running = true
v.emitProducts(emitDone)
case <-emitDone:
running = false
}
}
v.done = nil
}()
}
2017-10-19 21:33:20 -07:00
func (v *Validator) emitProducts(done chan struct{}) {
go func() {
for _, p := range v.Products {
v.validateProduct(p)
}
select {
case done <- struct{}{}:
default:
}
}()
}
2017-10-10 10:17:00 -07:00
func (v *Validator) validateProduct(product string) {
2017-10-10 10:14:49 -07:00
v.Logger.Info("validator: %v", product)
2017-10-05 19:33:50 -07:00
2017-10-10 17:22:00 -07:00
conf, _ := v.Database.ConfirmationService().Confirmation(product, "t")
2017-10-05 21:53:02 -07:00
2017-10-10 17:22:00 -07:00
groups, last_id := v.findMissingGroups(product, conf.LastId)
2017-10-05 19:33:50 -07:00
v.getMissingTrades(product, groups)
2017-10-05 21:53:02 -07:00
conf.Product = product
2017-10-10 17:22:00 -07:00
conf.Type = "t"
conf.LastId = last_id
2017-10-05 21:53:02 -07:00
if conf.Id == 0 {
2017-10-10 10:14:49 -07:00
v.Database.ConfirmationService().CreateConfirmation(conf)
2017-10-05 21:53:02 -07:00
} else {
2017-10-10 10:14:49 -07:00
v.Database.ConfirmationService().UpdateConfirmation(conf)
2017-10-05 21:53:02 -07:00
}
2017-10-10 10:14:49 -07:00
v.Logger.Info("validator: DONE %v", product)
2017-10-05 19:33:50 -07:00
}
2017-10-10 10:17:00 -07:00
func (v *Validator) getMissingTrades(product string, groups [][]int) {
2017-10-05 19:33:50 -07:00
c := gdax.NewPublicClient()
for _, group := range groups {
2017-10-05 21:53:02 -07:00
total := 1 + group[1] - group[0]
2017-10-10 10:14:49 -07:00
v.Logger.Info("validator: retrieving %v missing trade(s): %v", total, group)
2017-10-05 21:53:02 -07:00
2017-10-05 19:33:50 -07:00
for i := group[1]; i >= group[0]; i-- {
ts, _ := c.GetTradesBefore(product, i+1)
2017-10-10 10:14:49 -07:00
sort.Sort(byTradeId(ts))
2017-10-05 19:33:50 -07:00
for _, t := range ts {
if t.TradeId < group[0] && t.TradeId > group[1] {
i = ts[len(ts)-1].TradeId
} else {
2017-10-10 10:14:49 -07:00
v.Database.TradeService().CreateTrade(t)
2017-10-05 19:33:50 -07:00
i = t.TradeId
}
}
}
2017-10-05 21:53:02 -07:00
2017-10-10 10:14:49 -07:00
v.Logger.Info("validator: DONE")
2017-10-05 19:33:50 -07:00
}
}
2017-10-10 10:17:00 -07:00
func (v *Validator) findMissingGroups(product string, starting int) ([][]int, int) {
2017-10-10 10:14:49 -07:00
results, err := v.Database.TradeService().TradesAfterAll(product, starting)
if err != nil {
2017-10-10 10:14:49 -07:00
v.Logger.Info("Error getting all trades: %v", err)
}
var trade tacitus.Trade
missing := [][]int{}
2017-10-05 21:53:02 -07:00
current := starting
for results.Next() {
trade = results.Value().(tacitus.Trade)
2017-10-05 21:53:02 -07:00
if trade.TradeId != current+1 && trade.TradeId != current {
missing = append(missing, []int{current + 1, trade.TradeId - 1})
}
current = trade.TradeId
}
2017-10-05 21:53:02 -07:00
return missing, current
}