github.com/machinefi/w3bstream@v1.6.5-rc9.0.20240426031326-b8c7c4876e72/pkg/modules/vm/wasmapi/server.go (about) 1 package wasmapi 2 3 import ( 4 "bytes" 5 "context" 6 "encoding/json" 7 "fmt" 8 "net/http" 9 "net/http/httptest" 10 "time" 11 12 "github.com/gin-gonic/gin" 13 "github.com/hibiken/asynq" 14 "github.com/pkg/errors" 15 16 confid "github.com/machinefi/w3bstream/pkg/depends/conf/id" 17 confmq "github.com/machinefi/w3bstream/pkg/depends/conf/mq" 18 "github.com/machinefi/w3bstream/pkg/depends/conf/redis" 19 "github.com/machinefi/w3bstream/pkg/depends/kit/logr" 20 "github.com/machinefi/w3bstream/pkg/depends/kit/sqlx" 21 optypes "github.com/machinefi/w3bstream/pkg/modules/operator/pool/types" 22 "github.com/machinefi/w3bstream/pkg/modules/vm/wasmapi/async" 23 "github.com/machinefi/w3bstream/pkg/modules/vm/wasmapi/handler" 24 apitypes "github.com/machinefi/w3bstream/pkg/modules/vm/wasmapi/types" 25 "github.com/machinefi/w3bstream/pkg/types" 26 "github.com/machinefi/w3bstream/pkg/types/wasm/kvdb" 27 ) 28 29 type Server struct { 30 router *gin.Engine 31 cli *asynq.Client 32 srv *asynq.Server 33 } 34 35 func (s *Server) Call(ctx context.Context, data []byte) *apitypes.HttpResponse { 36 _, l := logr.Start(ctx, "vm.Server.Call") 37 defer l.End() 38 39 apiReq := apitypes.HttpRequest{} 40 if err := json.Unmarshal(data, &apiReq); err != nil { 41 l.Error(errors.Wrap(err, "http request illegal format")) 42 return &apitypes.HttpResponse{ 43 StatusCode: http.StatusBadRequest, 44 } 45 } 46 req, err := http.NewRequestWithContext(ctx, apiReq.Method, apiReq.Url, bytes.NewReader(apiReq.Body)) 47 if err != nil { 48 l.Error(errors.Wrap(err, "build http request failed")) 49 return &apitypes.HttpResponse{ 50 StatusCode: http.StatusBadRequest, 51 } 52 } 53 req.Header = apiReq.Header 54 55 respRecorder := httptest.NewRecorder() 56 s.router.ServeHTTP(respRecorder, req) 57 58 resp, err := async.ConvHttpResponse(apiReq.Header, respRecorder.Result()) 59 if err != nil { 60 l.Error(errors.Wrap(err, "conv http response failed")) 61 return &apitypes.HttpResponse{ 62 StatusCode: http.StatusInternalServerError, 63 } 64 } 65 return resp 66 } 67 68 func (s *Server) Shutdown() { 69 s.srv.Shutdown() 70 } 71 72 func newRouter(mgrDB sqlx.DBExecutor, chainConf *types.ChainConfig, opPool optypes.Pool, sfid confid.SFIDGenerator, 73 asyncCli *asynq.Client, risc0Conf *types.Risc0Config) *gin.Engine { 74 router := gin.New() 75 router.Use(gin.Recovery()) 76 router.Use(handler.ParamValidate()) 77 78 handlers := handler.New(mgrDB, chainConf, opPool, sfid, asyncCli, risc0Conf) 79 80 router.GET("/system/hello", handlers.Hello) 81 router.GET("/system/hello/async", handlers.HelloAsync) 82 router.GET("/system/read_tx", handlers.ReadTx) 83 router.GET("/system/read_tx/async", handlers.ReadTxAsync) 84 router.POST("/system/send_tx", handlers.SendTx) 85 router.POST("/system/send_tx/async", handlers.SendTxAsync) 86 router.POST("/system/send_tx/async/state", handlers.SendTxAsyncStateCheck) 87 router.POST("/system/gen_zk_proof", handlers.GenRisc0Proof) 88 router.POST("/system/gen_zk_proof/async", handlers.GenRisc0ProofAsync) 89 90 return router 91 } 92 93 func NewServer(redisConf *redis.Redis, mgrDB sqlx.DBExecutor, kv *kvdb.RedisDB, chainConf *types.ChainConfig, 94 tasks *confmq.Config, opPool optypes.Pool, sfid confid.SFIDGenerator, risc0Conf *types.Risc0Config) (*Server, error) { 95 96 redisCli := asynq.RedisClientOpt{ 97 Network: redisConf.Protocol, 98 Addr: fmt.Sprintf("%s:%d", redisConf.Host, redisConf.Port), 99 Password: redisConf.Password.String(), 100 ReadTimeout: time.Duration(redisConf.ReadTimeout), 101 WriteTimeout: time.Duration(redisConf.WriteTimeout), 102 DialTimeout: time.Duration(redisConf.ConnectTimeout), 103 DB: redisConf.DB, 104 } 105 asyncCli := asynq.NewClient(redisCli) 106 asyncSrv := asynq.NewServer(redisCli, asynq.Config{}) 107 108 router := newRouter(mgrDB, chainConf, opPool, sfid, asyncCli, risc0Conf) 109 110 mux := asynq.NewServeMux() 111 mux.Handle(async.TaskNameApiCall, async.NewApiCallProcessor(router, asyncCli)) 112 mux.Handle(async.TaskNameApiResult, async.NewApiResultProcessor(mgrDB, kv, tasks, redisConf)) 113 114 if err := asyncSrv.Start(mux); err != nil { 115 return nil, err 116 } 117 118 return &Server{ 119 router: router, 120 cli: asyncCli, 121 srv: asyncSrv, 122 }, nil 123 }