Start public interface in limited mode before initial sync #51
parent
9a33c338dd
commit
d6b9cd496b
|
@ -118,6 +118,8 @@ type BlockbookInfo struct {
|
|||
Version string `json:"version"`
|
||||
GitCommit string `json:"gitcommit"`
|
||||
BuildTime string `json:"buildtime"`
|
||||
SyncMode bool `json:"syncMode"`
|
||||
InitialSync bool `json:"initialsync"`
|
||||
InSync bool `json:"inSync"`
|
||||
BestHeight uint32 `json:"bestHeight"`
|
||||
LastBlockTime time.Time `json:"lastBlockTime"`
|
||||
|
|
|
@ -547,6 +547,8 @@ func (w *Worker) GetSystemInfo(internal bool) (*SystemInfo, error) {
|
|||
Version: vi.Version,
|
||||
GitCommit: vi.GitCommit,
|
||||
BuildTime: vi.BuildTime,
|
||||
SyncMode: w.is.SyncMode,
|
||||
InitialSync: w.is.InitialSync,
|
||||
InSync: ss,
|
||||
BestHeight: bh,
|
||||
LastBlockTime: st,
|
||||
|
|
33
blockbook.go
33
blockbook.go
|
@ -267,19 +267,9 @@ func main() {
|
|||
}()
|
||||
}
|
||||
|
||||
if *synchronize {
|
||||
if err := syncWorker.ResyncIndex(nil); err != nil {
|
||||
glog.Error("resyncIndex ", err)
|
||||
return
|
||||
}
|
||||
if _, err = chain.ResyncMempool(nil); err != nil {
|
||||
glog.Error("resyncMempool ", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
var publicServer *server.PublicServer
|
||||
if *publicBinding != "" {
|
||||
// start public server in limited functionality, extend it after sync is finished by calling ConnectFullPublicInterface
|
||||
publicServer, err = server.NewPublicServer(*publicBinding, *certFiles, index, chain, txCache, *explorerURL, metrics, internalState, *debugMode)
|
||||
if err != nil {
|
||||
glog.Error("socketio: ", err)
|
||||
|
@ -301,10 +291,27 @@ func main() {
|
|||
}
|
||||
|
||||
if *synchronize {
|
||||
// start the synchronization loops after the server interfaces are started
|
||||
internalState.SyncMode = true
|
||||
internalState.InitialSync = true
|
||||
if err := syncWorker.ResyncIndex(nil); err != nil {
|
||||
glog.Error("resyncIndex ", err)
|
||||
return
|
||||
}
|
||||
var mempoolCount int
|
||||
if mempoolCount, err = chain.ResyncMempool(nil); err != nil {
|
||||
glog.Error("resyncMempool ", err)
|
||||
return
|
||||
}
|
||||
internalState.FinishedMempoolSync(mempoolCount)
|
||||
go syncIndexLoop()
|
||||
go syncMempoolLoop()
|
||||
go storeInternalStateLoop()
|
||||
internalState.InitialSync = false
|
||||
}
|
||||
go storeInternalStateLoop()
|
||||
|
||||
if *publicBinding != "" {
|
||||
// start full public interface
|
||||
publicServer.ConnectFullPublicInterface()
|
||||
}
|
||||
|
||||
if *blockFrom >= 0 {
|
||||
|
|
|
@ -37,6 +37,10 @@ type InternalState struct {
|
|||
|
||||
LastStore time.Time `json:"lastStore"`
|
||||
|
||||
// true if application is with flag --sync
|
||||
SyncMode bool `json:"syncMode"`
|
||||
|
||||
InitialSync bool `json:"initialSync"`
|
||||
IsSynchronized bool `json:"isSynchronized"`
|
||||
BestHeight uint32 `json:"bestHeight"`
|
||||
LastSync time.Time `json:"lastSync"`
|
||||
|
@ -64,6 +68,14 @@ func (is *InternalState) FinishedSync(bestHeight uint32) {
|
|||
is.LastSync = time.Now()
|
||||
}
|
||||
|
||||
// UpdateBestHeight sets new best height, without changing IsSynchronized flag
|
||||
func (is *InternalState) UpdateBestHeight(bestHeight uint32) {
|
||||
is.mux.Lock()
|
||||
defer is.mux.Unlock()
|
||||
is.BestHeight = bestHeight
|
||||
is.LastSync = time.Now()
|
||||
}
|
||||
|
||||
// FinishedSyncNoChange marks end of synchronization in case no index update was necessary, it does not update lastSync time
|
||||
func (is *InternalState) FinishedSyncNoChange() {
|
||||
is.mux.Lock()
|
||||
|
|
|
@ -988,8 +988,10 @@ func (d *RocksDB) writeHeight(wb *gorocksdb.WriteBatch, height uint32, bi *Block
|
|||
return err
|
||||
}
|
||||
wb.PutCF(d.cfh[cfHeight], key, val)
|
||||
d.is.UpdateBestHeight(height)
|
||||
case opDelete:
|
||||
wb.DeleteCF(d.cfh[cfHeight], key)
|
||||
d.is.UpdateBestHeight(height - 1)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -1223,9 +1225,9 @@ func dirSize(path string) (int64, error) {
|
|||
var size int64
|
||||
err := filepath.Walk(path, func(_ string, info os.FileInfo, err error) error {
|
||||
if err == nil {
|
||||
if !info.IsDir() {
|
||||
size += info.Size()
|
||||
}
|
||||
if !info.IsDir() {
|
||||
size += info.Size()
|
||||
}
|
||||
}
|
||||
return err
|
||||
})
|
||||
|
@ -1352,6 +1354,12 @@ func (d *RocksDB) LoadInternalState(rpcCoin string) (*common.InternalState, erro
|
|||
}
|
||||
}
|
||||
is.DbColumns = nc
|
||||
// after load, reset the synchronization data
|
||||
is.IsSynchronized = false
|
||||
is.IsMempoolSynchronized = false
|
||||
var t time.Time
|
||||
is.LastMempoolSync = t
|
||||
is.SyncMode = false
|
||||
return is, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -42,6 +42,7 @@ type PublicServer struct {
|
|||
}
|
||||
|
||||
// NewPublicServer creates new public server http interface to blockbook and returns its handle
|
||||
// only basic functionality is mapped, to map all functions, call
|
||||
func NewPublicServer(binding string, certFiles string, db *db.RocksDB, chain bchain.BlockChain, txCache *db.TxCache, explorerURL string, metrics *common.Metrics, is *common.InternalState, debugMode bool) (*PublicServer, error) {
|
||||
|
||||
api, err := api.NewWorker(db, chain, txCache, is)
|
||||
|
@ -76,33 +77,15 @@ func NewPublicServer(binding string, certFiles string, db *db.RocksDB, chain bch
|
|||
is: is,
|
||||
debug: debugMode,
|
||||
}
|
||||
s.templates = parseTemplates()
|
||||
|
||||
// favicon
|
||||
// map only basic functions, the rest is enabled by method MapFullPublicInterface
|
||||
serveMux.Handle(path+"favicon.ico", http.FileServer(http.Dir("./static/")))
|
||||
// support for tests of socket.io interface
|
||||
serveMux.Handle(path+"test.html", http.FileServer(http.Dir("./static/")))
|
||||
// redirect to wallet requests for tx and address, possibly to external site
|
||||
serveMux.HandleFunc(path+"tx/", s.txRedirect)
|
||||
serveMux.HandleFunc(path+"address/", s.addressRedirect)
|
||||
// explorer
|
||||
serveMux.HandleFunc(path+"explorer/tx/", s.htmlTemplateHandler(s.explorerTx))
|
||||
serveMux.HandleFunc(path+"explorer/address/", s.htmlTemplateHandler(s.explorerAddress))
|
||||
serveMux.HandleFunc(path+"explorer/search/", s.htmlTemplateHandler(s.explorerSearch))
|
||||
serveMux.HandleFunc(path+"explorer/blocks", s.htmlTemplateHandler(s.explorerBlocks))
|
||||
serveMux.HandleFunc(path+"explorer/block/", s.htmlTemplateHandler(s.explorerBlock))
|
||||
serveMux.Handle(path+"static/", http.StripPrefix("/static/", http.FileServer(http.Dir("./static/"))))
|
||||
// API calls
|
||||
serveMux.HandleFunc(path+"api/block-index/", s.jsonHandler(s.apiBlockIndex))
|
||||
serveMux.HandleFunc(path+"api/tx/", s.jsonHandler(s.apiTx))
|
||||
serveMux.HandleFunc(path+"api/address/", s.jsonHandler(s.apiAddress))
|
||||
serveMux.HandleFunc(path+"api/block/", s.jsonHandler(s.apiBlock))
|
||||
serveMux.HandleFunc(path+"api/", s.jsonHandler(s.apiIndex))
|
||||
// handle socket.io
|
||||
serveMux.Handle(path+"socket.io/", socketio.GetHandler())
|
||||
// default handler
|
||||
serveMux.HandleFunc(path, s.htmlTemplateHandler(s.explorerIndex))
|
||||
|
||||
s.templates = parseTemplates()
|
||||
// default API handler
|
||||
serveMux.HandleFunc(path+"api/", s.jsonHandler(s.apiIndex))
|
||||
|
||||
return s, nil
|
||||
}
|
||||
|
@ -117,6 +100,30 @@ func (s *PublicServer) Run() error {
|
|||
return s.https.ListenAndServeTLS(fmt.Sprint(s.certFiles, ".crt"), fmt.Sprint(s.certFiles, ".key"))
|
||||
}
|
||||
|
||||
// ConnectFullPublicInterface enables complete public functionality
|
||||
func (s *PublicServer) ConnectFullPublicInterface() {
|
||||
serveMux := s.https.Handler.(*http.ServeMux)
|
||||
_, path := splitBinding(s.binding)
|
||||
// support for tests of socket.io interface
|
||||
serveMux.Handle(path+"test.html", http.FileServer(http.Dir("./static/")))
|
||||
// redirect to wallet requests for tx and address, possibly to external site
|
||||
serveMux.HandleFunc(path+"tx/", s.txRedirect)
|
||||
serveMux.HandleFunc(path+"address/", s.addressRedirect)
|
||||
// explorer
|
||||
serveMux.HandleFunc(path+"explorer/tx/", s.htmlTemplateHandler(s.explorerTx))
|
||||
serveMux.HandleFunc(path+"explorer/address/", s.htmlTemplateHandler(s.explorerAddress))
|
||||
serveMux.HandleFunc(path+"explorer/search/", s.htmlTemplateHandler(s.explorerSearch))
|
||||
serveMux.HandleFunc(path+"explorer/blocks", s.htmlTemplateHandler(s.explorerBlocks))
|
||||
serveMux.HandleFunc(path+"explorer/block/", s.htmlTemplateHandler(s.explorerBlock))
|
||||
// API calls
|
||||
serveMux.HandleFunc(path+"api/block-index/", s.jsonHandler(s.apiBlockIndex))
|
||||
serveMux.HandleFunc(path+"api/tx/", s.jsonHandler(s.apiTx))
|
||||
serveMux.HandleFunc(path+"api/address/", s.jsonHandler(s.apiAddress))
|
||||
serveMux.HandleFunc(path+"api/block/", s.jsonHandler(s.apiBlock))
|
||||
// socket.io interface
|
||||
serveMux.Handle(path+"socket.io/", s.socketio.GetHandler())
|
||||
}
|
||||
|
||||
// Close closes the server
|
||||
func (s *PublicServer) Close() error {
|
||||
glog.Infof("public server: closing")
|
||||
|
|
|
@ -1,5 +1,11 @@
|
|||
{{define "specific"}}{{$cs := .CoinShortcut}}{{$bb := .Info.Blockbook}}{{$be := .Info.Backend}}
|
||||
<h1>Application status</h1>
|
||||
{{- if $bb.InitialSync -}}
|
||||
<h3 class="bg-danger text-white" style="padding: 20px;">Application is now in initial synchronization and does not provide any data.</h3>
|
||||
{{- end -}}
|
||||
{{- if not $bb.SyncMode -}}
|
||||
<h3 class="bg-warning text-white" style="padding: 20px;">Synchronization with backend is disabled, the state of index is not up to date.</h3>
|
||||
{{- end -}}
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<h3>Blockbook</h3>
|
||||
|
@ -19,7 +25,7 @@
|
|||
</tr>
|
||||
<tr>
|
||||
<td>Synchronized</td>
|
||||
<td class="data{{if not $bb.InSync}} text-danger{{end}}">{{$bb.InSync}}</td>
|
||||
<td class="data {{if not $bb.InSync}}text-danger{{else}}text-success{{end}}">{{$bb.InSync}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Last Block</td>
|
||||
|
@ -31,7 +37,7 @@
|
|||
</tr>
|
||||
<tr>
|
||||
<td>Mempool in Sync</td>
|
||||
<td class="data{{if not $bb.InSyncMempool}} text-danger{{end}}">{{$bb.InSyncMempool}}</td>
|
||||
<td class="data {{if not $bb.InSyncMempool}}text-danger{{else}}text-success{{end}}">{{$bb.InSyncMempool}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Last Mempool Update</td>
|
||||
|
|
Loading…
Reference in New Issue