Skip to content

Commit

Permalink
market,dex: SuspendMarket methods for OrderRouter and DEX mgr
Browse files Browse the repository at this point in the history
Add (*OrderRouter).SuspendMarket, called from the DEX manager in the new
server/dex.(*DEX) SuspendMarket method.

server/admin: suspend and market info routes
  • Loading branch information
chappjc committed May 7, 2020
1 parent ec465ec commit 21146a4
Show file tree
Hide file tree
Showing 7 changed files with 423 additions and 29 deletions.
76 changes: 65 additions & 11 deletions server/admin/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"fmt"
"net/http"
"strconv"
"strings"
"time"

"decred.org/dcrdex/dex/encode"
Expand Down Expand Up @@ -42,22 +43,75 @@ func (s *Server) apiConfig(w http.ResponseWriter, _ *http.Request) {
writeJSON(w, s.core.ConfigMsg())
}

func (s *Server) apiSuspend(w http.ResponseWriter, r *http.Request) {
suspTimeStr := chi.URLParam(r, timePathKey)
suspTimeMs, err := strconv.ParseInt(suspTimeStr, 10, 64)
if err != nil {
http.Error(w, fmt.Sprintf("invalid time %q: %v", suspTimeStr, err), http.StatusBadRequest)
// apiMarketInfo is the handler for the '/market/{marketName}' API request.
func (s *Server) apiMarketInfo(w http.ResponseWriter, r *http.Request) {
mkt := strings.ToLower(chi.URLParam(r, marketNameKey))
found, running := s.core.MarketRunning(mkt)
if !found {
http.Error(w, fmt.Sprintf("unknown market %q", mkt), http.StatusBadRequest)
return
}

suspTime := encode.UnixTimeMilli(suspTimeMs)
if time.Until(suspTime) < 0 {
http.Error(w, fmt.Sprintf("specified trade suspension time is in the past: %v", suspTime),
http.StatusBadRequest)
writeJSON(w, &MarketStatus{
Name: mkt,
Running: running,
})
}

// hander for route '/market/{marketName}/suspend?t=13241234&persist=false'
func (s *Server) apiSuspend(w http.ResponseWriter, r *http.Request) {
// Ensure the market exists and is running.
mkt := strings.ToLower(chi.URLParam(r, marketNameKey))
found, running := s.core.MarketRunning(mkt)
if !found {
http.Error(w, fmt.Sprintf("unknown market %q", mkt), http.StatusBadRequest)
return
}
if !running {
http.Error(w, fmt.Sprintf("market %q not running", mkt), http.StatusBadRequest)
return
}

// Validate the suspend time provided in the "t" query. If not specified,
// the zero time.Time is used to indicate ASAP.
var suspTime time.Time
if tSuspendStr := r.URL.Query().Get("t"); tSuspendStr != "" {
suspTimeMs, err := strconv.ParseInt(tSuspendStr, 10, 64)
if err != nil {
http.Error(w, fmt.Sprintf("invalid suspend time %q: %v", tSuspendStr, err), http.StatusBadRequest)
return
}

marketSuspEpochs := s.core.Suspend(suspTime)
suspTime = encode.UnixTimeMilli(suspTimeMs)
if time.Until(suspTime) < 0 {
http.Error(w, fmt.Sprintf("specified market suspend time is in the past: %v", suspTime),
http.StatusBadRequest)
return
}
}

// Validate the persist book flag provided in the "persist" query. If not
// specified, persist the books, do not purge.
persistBook := true
if persistBookStr := r.URL.Query().Get("persist"); persistBookStr != "" {
var err error
persistBook, err = strconv.ParseBool(persistBookStr)
if err != nil {
http.Error(w, fmt.Sprintf("invalid persist book boolean %q: %v", persistBookStr, err), http.StatusBadRequest)
return
}
}

suspEpoch := s.core.SuspendMarket(mkt, suspTime, persistBook)
if suspEpoch == nil {
// Should not happen.
http.Error(w, "failed to suspend market "+mkt, http.StatusInternalServerError)
return
}

writeJSON(w, marketSuspEpochs)
writeJSON(w, &SuspendResult{
Market: mkt,
FinalEpoch: suspEpoch.Idx,
SuspendTime: APITime{suspEpoch.End},
})
}
12 changes: 9 additions & 3 deletions server/admin/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ const (
// is closed.
rpcTimeoutSeconds = 10

timePathKey = "epochMs"
marketNameKey = "market"
)

var (
Expand All @@ -39,7 +39,9 @@ var (
// SvrCore is satisfied by core.Core.
type SvrCore interface {
ConfigMsg() json.RawMessage
Suspend(time.Time, ...time.Time) map[string]*market.SuspendEpoch
MarketRunning(mktName string) (found, running bool)
Suspend(tSusp time.Time, persistBooks bool) map[string]*market.SuspendEpoch
SuspendMarket(name string, tSusp time.Time, persistBooks bool) *market.SuspendEpoch
}

// Server is a multi-client https server.
Expand Down Expand Up @@ -115,7 +117,11 @@ func NewServer(cfg *SrvConfig) (*Server, error) {
r.Use(middleware.AllowContentType("application/json"))
r.Get("/ping", s.apiPing)
r.Get("/config", s.apiConfig)
r.Get("/suspend/{"+timePathKey+"}", s.apiSuspend)

r.Route("/market/{"+marketNameKey+"}", func(rm chi.Router) {
rm.Get("/", s.apiMarketInfo)
rm.Get("/suspend", s.apiSuspend)
})
})

return s, nil
Expand Down
Loading

0 comments on commit 21146a4

Please sign in to comment.