New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
server/db: Update lot sizes when necessary. #1212
Conversation
Something wrong with the second commit still. Is config cached? Also not sure the best placement, or if this is racing for something. |
Thanks for this @JoeGruffins! I'm gonna review this first thing. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
DB setup looks good. I think we need to do the actual book purge in a different spot though, before (*Market).Run
and probably even before NewMarket
, where book orders get loaded and coins locked and checked and other stuff.
server/market/market.go
Outdated
fmt.Println("********************************************") | ||
fmt.Println("hello resume") | ||
// Ask storage if lot size changed during | ||
// suspend and purge orders if needed. | ||
for _, mkt := range m.storage.MarketsNeedOrderPurge() { | ||
if mkt != m.marketInfo.Name { | ||
log.Warnf("unexpected market found in purgable markets %s", mkt) | ||
continue | ||
} | ||
log.Debugf("Lot size changed, purging orders for mkt %s", m.marketInfo.Name) | ||
m.PurgeBook() | ||
break // Should not be duplicates, but be safe. | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This would be the place where we might address hot/live market config changes that require market suspend/resume without shutdown. In this PR we just want to deal with dex startup, not resume, detecting lot size changes.
There are a few ways to approach that, but each would use storage.FlushBook
before NewMarket
to avoid ever loading incompatible orders and locking coins etc. only to immediately undo it with Market.PurgeBook
- In the DEX manager (
server/dex.NewDEX
), callstorage.FlushBook
before even constructing theMarket
s. i.e.
// server/dex/dex.go, after db.Open, before NewMarket
// Before creating markets, purge books for markets where lot size changed.
for _, staleMarket := range storage.MarketsNeedOrderPurge() {
base, quote := assetsIDsForMarket(staleMarket) // find it in cfg.Markets, ignoring case
storage.FlushBook(base, quote) // TODO: log and check err
}
OR
- Modify
NewMarket
to do thestorage.FlushBook
rather thanstorage.BookOrders
. The need to do this could be communicated via thestorage.MarketsNeedOrderPurge
method or more simply as a flag toNewMarket
in themarket.Config
struct. i.e.
// server/market/market.go in NewMarket
// Load existing book orders from the DB, or purge them if instructed.
base, quote := mktInfo.Base, mktInfo.Quote
var bookOrders []*order.LimitOrder
if cfg.FlushBook {
storage.FlushBook(base, quote) // TODO: check error and log counts of unbooked orders
} else {
var err error
bookOrders, err = storage.BookOrders(base, quote)
if err != nil {
return nil, err
}
log.Infof("Loaded %d stored book orders.", len(bookOrders))
}
OR
- Simplest, just clear the book in
NewArchiver
(also before callingNewMarket
). For that,NewArchiver
itself would callFlushBook
. i.e.
// server/driver/db/pg.go in NewArchiver
// Ensure all tables required by the current market configuration are ready.
purgeMarkets, err := prepareTables(ctx, db, cfg.MarketCfg)
if err != nil {
return nil, err
}
for _, staleMarket := range purgeMarkets {
mkt := mktMap[staleMarket]
if mkt == nil { // shouldn't happen
return nil, fmt.Errorf("unrecognized market %v", staleMarket)
}
unbookedSells, unbookedBuys, err := archiver.FlushBook(mkt.Base, mkt.Quote)
if err != nil {
return nil, fmt.Errorf("failed to flush book for market %v: %w", staleMarket, err)
}
log.Infof("Flushed %d sell orders and %d buy orders from market %v with a changed lot size.",
len(unbookedSells), len(unbookedBuys))
}
With this last option, there'd be no need for the marketsNeedOrderPurge
field or the call-once MarketsNeedOrderPurge
method.
To me, the question is a philosophical: should the decision to purge booked orders with a newly-incompatible lot size be the job of DEX
manager logic (option 1), the Market
constructor (option 2), or the Archiver
constructor (option 3). I'm leaning toward #3 since it's the Archiver that knows when lot size changed and booked orders are no longer valid.
I think any of these approaches would accommodate a --allowlotsizechange
flag, if we wanted to make it harder for an operator to mess up and accidentally purge a book.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for the great comments.
In this PR we just want to deal with dex startup
Oh! The issue does say that. So, suspend persisted, shutdown completely, change markets.json manually, and startup.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There sure are a lot of ifs ands or buts in this.
You got the DB update of lot_size
down just right.
Just needs a little tweak to the purge call if the operator forgets to purge before shutdown. 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That reminds me I need to carefully review Swapper functionality w.r.t. lot size (shouldn't be any, but I don't recall), otherwise it's going to be a burden to change lot size with active swaps.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Went with your third option, which doesn't require any changes outside of the database code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually testing with active swaps, completed swaps, and booked orders, doesn't seem to cause any errors.
e7de909
to
d0d1b1b
Compare
account discovery pr #1201 is merged. Also the btc-fee PR is fixed up and rebased. Would this PR be messy based on master instead of btc-fee? We can keep it on btc-fee assuming that gets in pretty soon, but this PR looks good to merge now. EDIT: it wasn't too bad on master. With your branch checked out I did |
No longer panic when lot size changes. If lot sizes changed, update them in the db. Then, flush all persisted orders belonging to that market.
1328fae
to
1207a20
Compare
depends on #1202
closes #1174