v1.27.0-a #10
@ -445,7 +445,7 @@ func GetFullNodeAPIV1LotusProvider(ctx *cli.Context, ainfoCfg []string, opts ...
|
||||
for _, head := range heads {
|
||||
v1api, closer, err := client.NewFullNodeRPCV1(ctx.Context, head.addr, head.header, rpcOpts...)
|
||||
if err != nil {
|
||||
log.Warnf("Not able to establish connection to node with addr: %s", head.addr)
|
||||
log.Warnf("Not able to establish connection to node with addr: %s, Reason: %s", head.addr, err.Error())
|
||||
continue
|
||||
}
|
||||
fullNodes = append(fullNodes, v1api)
|
||||
|
@ -9,6 +9,7 @@ import (
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/BurntSushi/toml"
|
||||
@ -176,7 +177,11 @@ func (deps *Deps) PopulateRemainingDeps(ctx context.Context, cctx *cli.Context,
|
||||
|
||||
if deps.Full == nil {
|
||||
var fullCloser func()
|
||||
deps.Full, fullCloser, err = cliutil.GetFullNodeAPIV1LotusProvider(cctx, deps.Cfg.Apis.ChainApiInfo)
|
||||
cfgApiInfo := deps.Cfg.Apis.ChainApiInfo
|
||||
if v := os.Getenv("FULLNODE_API_INFO"); v != "" {
|
||||
cfgApiInfo = []string{v}
|
||||
}
|
||||
deps.Full, fullCloser, err = cliutil.GetFullNodeAPIV1LotusProvider(cctx, cfgApiInfo)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -267,6 +272,7 @@ func GetConfig(cctx *cli.Context, db *harmonydb.DB) (*config.LotusProviderConfig
|
||||
for _, k := range meta.Keys() {
|
||||
have = append(have, strings.Join(k, " "))
|
||||
}
|
||||
log.Infow("Using layer", "layer", layer, "config", lp)
|
||||
}
|
||||
_ = have // FUTURE: verify that required fields are here.
|
||||
// If config includes 3rd-party config, consider JSONSchema as a way that
|
||||
|
@ -5,6 +5,7 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/BurntSushi/toml"
|
||||
@ -155,6 +156,15 @@ var webCmd = &cli.Command{
|
||||
Usage: "Address to listen on",
|
||||
Value: "127.0.0.1:4701",
|
||||
},
|
||||
&cli.StringSliceFlag{
|
||||
Name: "layers",
|
||||
Usage: "list of layers to be interpreted (atop defaults). Default: base. Web will be added",
|
||||
Value: cli.NewStringSlice("base"),
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "nosync",
|
||||
Usage: "don't check full-node sync status",
|
||||
},
|
||||
},
|
||||
Action: func(cctx *cli.Context) error {
|
||||
db, err := deps.MakeDB(cctx)
|
||||
@ -174,7 +184,9 @@ var webCmd = &cli.Command{
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err = cctx.Set("layers", "web"); err != nil {
|
||||
layers := append([]string{"web"}, cctx.StringSlice("layers")...)
|
||||
err = cctx.Set("layers", strings.Join(layers, ","))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return runCmd.Action(cctx)
|
||||
|
@ -29,7 +29,7 @@ type debug struct {
|
||||
|
||||
func Routes(r *mux.Router, deps *deps.Deps) {
|
||||
d := debug{deps}
|
||||
r.Methods("GET").Path("chain-state-sse").HandlerFunc(d.chainStateSSE)
|
||||
r.HandleFunc("/chain-state-sse", d.chainStateSSE)
|
||||
}
|
||||
|
||||
type rpcInfo struct {
|
||||
@ -79,29 +79,24 @@ func (d *debug) chainStateSSE(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
apiInfos := map[string][]byte{} // api address -> token
|
||||
// for dedup by address
|
||||
for _, info := range rpcInfos {
|
||||
ai := cliutil.ParseApiInfo(info.Apis.ChainApiInfo[0])
|
||||
apiInfos[ai.Addr] = ai.Token
|
||||
}
|
||||
dedup := map[string]bool{} // for dedup by address
|
||||
|
||||
infos := map[string]rpcInfo{} // api address -> rpc info
|
||||
var infosLk sync.Mutex
|
||||
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(len(rpcInfos))
|
||||
for addr, token := range apiInfos {
|
||||
addr := addr
|
||||
ai := cliutil.APIInfo{
|
||||
Addr: addr,
|
||||
Token: token,
|
||||
for _, info := range rpcInfos {
|
||||
ai := cliutil.ParseApiInfo(info.Apis.ChainApiInfo[0])
|
||||
if dedup[ai.Addr] {
|
||||
continue
|
||||
}
|
||||
go func(info string) {
|
||||
dedup[ai.Addr] = true
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
var clayers []string
|
||||
for layer, a := range confNameToAddr {
|
||||
if a == addr {
|
||||
if a == ai.Addr {
|
||||
clayers = append(clayers, layer)
|
||||
}
|
||||
}
|
||||
@ -113,8 +108,8 @@ func (d *debug) chainStateSSE(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
defer func() {
|
||||
infosLk.Lock()
|
||||
defer infosLk.Unlock()
|
||||
infos[ai.Addr] = myinfo
|
||||
infosLk.Unlock()
|
||||
}()
|
||||
da, err := ai.DialArgs("v1")
|
||||
if err != nil {
|
||||
@ -126,7 +121,7 @@ func (d *debug) chainStateSSE(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
v1api, closer, err := client.NewFullNodeRPCV1(ctx, da, ah)
|
||||
if err != nil {
|
||||
log.Warnf("Not able to establish connection to node with addr: %s", addr)
|
||||
log.Warnf("Not able to establish connection to node with addr: %s", ai.Addr)
|
||||
return
|
||||
}
|
||||
defer closer()
|
||||
@ -160,7 +155,7 @@ func (d *debug) chainStateSSE(w http.ResponseWriter, r *http.Request) {
|
||||
Version: ver.Version,
|
||||
SyncState: syncState,
|
||||
}
|
||||
}(addr)
|
||||
}()
|
||||
}
|
||||
wg.Wait()
|
||||
|
||||
|
@ -15,9 +15,7 @@ import (
|
||||
var templateFS embed.FS
|
||||
|
||||
func Routes(r *mux.Router, deps *deps.Deps) error {
|
||||
|
||||
t := new(template.Template)
|
||||
t, err := t.ParseFS(templateFS, "web/*")
|
||||
t, err := template.ParseFS(templateFS, "web/*")
|
||||
if err != nil {
|
||||
return xerrors.Errorf("parse templates: %w", err)
|
||||
}
|
||||
|
@ -4,9 +4,12 @@ package web
|
||||
import (
|
||||
"context"
|
||||
"embed"
|
||||
"io"
|
||||
"io/fs"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@ -22,30 +25,54 @@ import (
|
||||
//go:embed static
|
||||
var static embed.FS
|
||||
|
||||
var basePath = "/static/"
|
||||
|
||||
// An dev mode hack for no-restart changes to static and templates.
|
||||
// You still need to recomplie the binary for changes to go code.
|
||||
var webDev = os.Getenv("LOTUS_WEB_DEV") == "1"
|
||||
|
||||
func GetSrv(ctx context.Context, deps *deps.Deps) (*http.Server, error) {
|
||||
mux := mux.NewRouter()
|
||||
api.Routes(mux.PathPrefix("/api").Subrouter(), deps)
|
||||
err := hapi.Routes(mux.PathPrefix("/hapi").Subrouter(), deps)
|
||||
mx := mux.NewRouter()
|
||||
err := hapi.Routes(mx.PathPrefix("/hapi").Subrouter(), deps)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
mux.NotFoundHandler = http.FileServer(http.FS(static))
|
||||
api.Routes(mx.PathPrefix("/api").Subrouter(), deps)
|
||||
|
||||
basePath := basePath
|
||||
|
||||
var static fs.FS = static
|
||||
if webDev {
|
||||
mux.NotFoundHandler = http.FileServer(http.Dir("cmd/lotus-provider/web/static"))
|
||||
basePath = "cmd/lotus-provider/web/static"
|
||||
static = os.DirFS(basePath)
|
||||
}
|
||||
|
||||
return &http.Server{
|
||||
Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
mx.NotFoundHandler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
// If the request is for a directory, redirect to the index file.
|
||||
if strings.HasSuffix(r.URL.Path, "/") {
|
||||
r.URL.Path = r.URL.Path + "index.html"
|
||||
r.URL.Path += "index.html"
|
||||
}
|
||||
|
||||
file, err := static.Open(path.Join(basePath, r.URL.Path)[1:])
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
w.Write([]byte("404 Not Found"))
|
||||
return
|
||||
}
|
||||
mux.ServeHTTP(w, r)
|
||||
}),
|
||||
defer file.Close()
|
||||
|
||||
fileInfo, err := file.Stat()
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
w.Write([]byte("500 Internal Server Error"))
|
||||
return
|
||||
}
|
||||
|
||||
http.ServeContent(w, r, fileInfo.Name(), fileInfo.ModTime(), file.(io.ReadSeeker))
|
||||
})
|
||||
|
||||
return &http.Server{
|
||||
Handler: http.HandlerFunc(mx.ServeHTTP),
|
||||
BaseContext: func(listener net.Listener) context.Context {
|
||||
ctx, _ := tag.New(context.Background(), tag.Upsert(metrics.APIInterface, "lotus-provider"))
|
||||
return ctx
|
||||
|
Loading…
Reference in New Issue
Block a user