mirror of https://github.com/dtm-labs/dtm.git
7 changed files with 231 additions and 137 deletions
@ -0,0 +1,137 @@ |
|||||
|
package dtmsvr |
||||
|
|
||||
|
import ( |
||||
|
"encoding/json" |
||||
|
"errors" |
||||
|
"fmt" |
||||
|
"time" |
||||
|
|
||||
|
"github.com/dtm-labs/dtm/dtmcli" |
||||
|
"github.com/dtm-labs/dtm/dtmcli/dtmimp" |
||||
|
"github.com/dtm-labs/dtm/dtmcli/logger" |
||||
|
"github.com/gin-gonic/gin" |
||||
|
) |
||||
|
|
||||
|
const jrpcCodeFailure = -32901 |
||||
|
const jrpcCodeOngoing = -32902 |
||||
|
|
||||
|
type jrpcReq struct { |
||||
|
Method string `json:"method"` |
||||
|
Jsonrpc string `json:"jsonrpc"` |
||||
|
Params interface{} `json:"params"` |
||||
|
ID string `json:"id"` |
||||
|
} |
||||
|
|
||||
|
func addJrpcRouter(engine *gin.Engine) { |
||||
|
type jrpcFunc = func(interface{}) interface{} |
||||
|
handlers := map[string]jrpcFunc{ |
||||
|
"dtmserver.NewGid": jrpcNewGid, |
||||
|
"dtmserver.Prepare": jrpcPrepare, |
||||
|
"dtmserver.Submit": jrpcSubmit, |
||||
|
"dtmserver.Abort": jrpcAbort, |
||||
|
"dtmserver.RegisterBranch": jrpcRegisterBranch, |
||||
|
} |
||||
|
engine.POST("/", func(c *gin.Context) { |
||||
|
began := time.Now() |
||||
|
var err error |
||||
|
var req jrpcReq |
||||
|
var jerr map[string]interface{} |
||||
|
r := func() interface{} { |
||||
|
defer dtmimp.P2E(&err) |
||||
|
err2 := c.BindJSON(&req) |
||||
|
if err2 != nil { |
||||
|
jerr = map[string]interface{}{ |
||||
|
"code": -32700, |
||||
|
"message": fmt.Sprintf("Parse json error: %s", err2.Error()), |
||||
|
} |
||||
|
} else if req.ID == "" || req.Jsonrpc != "2.0" { |
||||
|
jerr = map[string]interface{}{ |
||||
|
"code": -32600, |
||||
|
"message": fmt.Sprintf("Bad json request: %s", dtmimp.MustMarshalString(req)), |
||||
|
} |
||||
|
} else if handlers[req.Method] == nil { |
||||
|
jerr = map[string]interface{}{ |
||||
|
"code": -32601, |
||||
|
"message": fmt.Sprintf("Method not found: %s", req.Method), |
||||
|
} |
||||
|
} else if handlers[req.Method] != nil { |
||||
|
return handlers[req.Method](req.Params) |
||||
|
} |
||||
|
return nil |
||||
|
}() |
||||
|
|
||||
|
// error maybe returned in r, assign it to err
|
||||
|
if ne, ok := r.(error); ok && err == nil { |
||||
|
err = ne |
||||
|
} |
||||
|
|
||||
|
if err != nil { |
||||
|
if errors.Is(err, dtmcli.ErrFailure) { |
||||
|
jerr = map[string]interface{}{ |
||||
|
"code": jrpcCodeFailure, |
||||
|
"message": err.Error(), |
||||
|
} |
||||
|
} else if errors.Is(err, dtmcli.ErrOngoing) { |
||||
|
jerr = map[string]interface{}{ |
||||
|
"code": jrpcCodeOngoing, |
||||
|
"message": err.Error(), |
||||
|
} |
||||
|
} else if jerr == nil { |
||||
|
jerr = map[string]interface{}{ |
||||
|
"code": -32603, |
||||
|
"message": err.Error(), |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
result := map[string]interface{}{ |
||||
|
"jsonrpc": "2.0", |
||||
|
"id": req.ID, |
||||
|
"error": jerr, |
||||
|
"result": r, |
||||
|
} |
||||
|
b, _ := json.Marshal(result) |
||||
|
cont := string(b) |
||||
|
if jerr == nil || jerr["code"] == jrpcCodeOngoing { |
||||
|
logger.Infof("%2dms %d %s %s %s", time.Since(began).Milliseconds(), 200, c.Request.Method, c.Request.RequestURI, cont) |
||||
|
} else { |
||||
|
logger.Errorf("%2dms %d %s %s %s", time.Since(began).Milliseconds(), 200, c.Request.Method, c.Request.RequestURI, cont) |
||||
|
} |
||||
|
c.JSON(200, result) |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
// TransFromJrpcParams construct TransGlobal from jrpc params
|
||||
|
func TransFromJrpcParams(params interface{}) *TransGlobal { |
||||
|
t := TransGlobal{} |
||||
|
dtmimp.MustRemarshal(params, &t) |
||||
|
return &t |
||||
|
} |
||||
|
|
||||
|
func jrpcNewGid(interface{}) interface{} { |
||||
|
return map[string]interface{}{"gid": GenGid()} |
||||
|
} |
||||
|
|
||||
|
func jrpcPrepare(params interface{}) interface{} { |
||||
|
return svcPrepare(TransFromJrpcParams(params)) |
||||
|
} |
||||
|
|
||||
|
func jrpcSubmit(params interface{}) interface{} { |
||||
|
return svcSubmit(TransFromJrpcParams(params)) |
||||
|
} |
||||
|
|
||||
|
func jrpcAbort(params interface{}) interface{} { |
||||
|
return svcAbort(TransFromJrpcParams(params)) |
||||
|
} |
||||
|
|
||||
|
func jrpcRegisterBranch(params interface{}) interface{} { |
||||
|
data := map[string]string{} |
||||
|
dtmimp.MustRemarshal(params, &data) |
||||
|
branch := TransBranch{ |
||||
|
Gid: data["gid"], |
||||
|
BranchID: data["branch_id"], |
||||
|
Status: dtmcli.StatusPrepared, |
||||
|
BinData: []byte(data["data"]), |
||||
|
} |
||||
|
return svcRegisterBranch(data["trans_type"], &branch, data) |
||||
|
} |
||||
@ -1,110 +0,0 @@ |
|||||
package dtmsvr |
|
||||
|
|
||||
import ( |
|
||||
"encoding/json" |
|
||||
"fmt" |
|
||||
"net/http" |
|
||||
|
|
||||
"github.com/dtm-labs/dtm/dtmcli" |
|
||||
"github.com/dtm-labs/dtm/dtmcli/logger" |
|
||||
"github.com/gin-gonic/gin" |
|
||||
) |
|
||||
|
|
||||
type jsonRPCReq struct { |
|
||||
Method string `json:"method"` |
|
||||
Jsonrpc string `json:"jsonrpc"` |
|
||||
Params interface{} `json:"params"` |
|
||||
ID string `json:"id"` |
|
||||
} |
|
||||
|
|
||||
func addJSONRPCRouter(engine *gin.Engine) { |
|
||||
engine.POST("/", dispatcher) |
|
||||
} |
|
||||
|
|
||||
func dispatcher(c *gin.Context) { |
|
||||
req := new(jsonRPCReq) |
|
||||
err := c.BindJSON(req) |
|
||||
logger.Infof("request:%s\n", req) |
|
||||
if err != nil { |
|
||||
c.JSON(http.StatusOK, gin.H{"id": req.ID, "result": nil, "error": map[string]interface{}{"code": -32700, "message": "Parse error"}}) |
|
||||
return |
|
||||
} |
|
||||
if req.Method == "dtmserver.NewGid" { |
|
||||
res := jsonRPCNewGid() |
|
||||
c.JSON(http.StatusOK, gin.H{"id": req.ID, "result": res, "error": err}) |
|
||||
return |
|
||||
} |
|
||||
|
|
||||
if req.Method == "dtmserver.Prepare" { |
|
||||
res := jsonRPCPrepare(req.Params) |
|
||||
c.JSON(http.StatusOK, gin.H{"id": req.ID, "result": res, "error": nil}) |
|
||||
return |
|
||||
} |
|
||||
|
|
||||
if req.Method == "dtmserver.Submit" { |
|
||||
res := jsonRPCSubmit(req.Params) |
|
||||
c.JSON(http.StatusOK, gin.H{"id": req.ID, "result": res, "error": nil}) |
|
||||
return |
|
||||
} |
|
||||
|
|
||||
if req.Method == "dtmserver.Abort" { |
|
||||
res := jsonRPCAbort(req.Params) |
|
||||
c.JSON(http.StatusOK, gin.H{"id": req.ID, "result": res, "error": nil}) |
|
||||
return |
|
||||
} |
|
||||
|
|
||||
if req.Method == "dtmserver.RegisterBranch" { |
|
||||
res := jsonRPCRegisterBranch(req.Params) |
|
||||
c.JSON(http.StatusOK, gin.H{"id": req.ID, "result": res, "error": nil}) |
|
||||
return |
|
||||
} |
|
||||
c.JSON(http.StatusOK, gin.H{"id": req.ID, "result": nil, "error": map[string]interface{}{"code": -32601, "message": "Method not found"}}) |
|
||||
} |
|
||||
|
|
||||
func jsonRPCNewGid() interface{} { |
|
||||
return map[string]interface{}{"gid": GenGid(), "dtm_result": dtmcli.ResultSuccess} |
|
||||
} |
|
||||
|
|
||||
func jsonRPCPrepare(params interface{}) interface{} { |
|
||||
res := svcPrepare(TransFromJSONRPCContext(params)) |
|
||||
if res == nil { |
|
||||
return map[string]string{"dtm_result": "SUCCESS"} |
|
||||
} |
|
||||
return map[string]string{"dtm_result": "FAILURE", "message": fmt.Sprintf("%v", res)} |
|
||||
} |
|
||||
|
|
||||
func jsonRPCSubmit(params interface{}) interface{} { |
|
||||
res := svcSubmit(TransFromJSONRPCContext(params)) |
|
||||
if res == nil { |
|
||||
return map[string]string{"dtm_result": "SUCCESS"} |
|
||||
} |
|
||||
return map[string]string{"dtm_result": "FAILURE", "message": fmt.Sprintf("%v", res)} |
|
||||
} |
|
||||
|
|
||||
func jsonRPCAbort(params interface{}) interface{} { |
|
||||
res := svcAbort(TransFromJSONRPCContext(params)) |
|
||||
if res == nil { |
|
||||
return map[string]string{"dtm_result": "SUCCESS"} |
|
||||
} |
|
||||
return map[string]string{"dtm_result": "FAILURE", "message": fmt.Sprintf("%v", res)} |
|
||||
} |
|
||||
|
|
||||
func jsonRPCRegisterBranch(params interface{}) interface{} { |
|
||||
data := map[string]string{} |
|
||||
paramsJSON, _ := json.Marshal(params) |
|
||||
err := json.Unmarshal(paramsJSON, &data) |
|
||||
if err != nil { |
|
||||
return map[string]string{"dtm_result": "FAILURE", "message": err.Error()} |
|
||||
} |
|
||||
branch := TransBranch{ |
|
||||
Gid: data["gid"], |
|
||||
BranchID: data["branch_id"], |
|
||||
Status: dtmcli.StatusPrepared, |
|
||||
BinData: []byte(data["data"]), |
|
||||
} |
|
||||
res := svcRegisterBranch(data["trans_type"], &branch, data) |
|
||||
if res == nil { |
|
||||
return map[string]string{"dtm_result": "SUCCESS"} |
|
||||
} |
|
||||
return map[string]string{"dtm_result": "FAILURE", "message": res.Error()} |
|
||||
} |
|
||||
Loading…
Reference in new issue