You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

510 lines
16 KiB

9 years ago
9 years ago
9 years ago
8 years ago
7 years ago
9 years ago
8 years ago
9 years ago
9 years ago
  1. package abciclient
  2. import (
  3. "context"
  4. "fmt"
  5. "net"
  6. "sync"
  7. "time"
  8. "google.golang.org/grpc"
  9. "google.golang.org/grpc/credentials/insecure"
  10. "github.com/tendermint/tendermint/abci/types"
  11. tmsync "github.com/tendermint/tendermint/internal/libs/sync"
  12. tmnet "github.com/tendermint/tendermint/libs/net"
  13. "github.com/tendermint/tendermint/libs/service"
  14. )
  15. // A gRPC client.
  16. type grpcClient struct {
  17. service.BaseService
  18. mustConnect bool
  19. client types.ABCIApplicationClient
  20. conn *grpc.ClientConn
  21. chReqRes chan *ReqRes // dispatches "async" responses to callbacks *in order*, needed by mempool
  22. mtx tmsync.Mutex
  23. addr string
  24. err error
  25. resCb func(*types.Request, *types.Response) // listens to all callbacks
  26. }
  27. var _ Client = (*grpcClient)(nil)
  28. // NewGRPCClient creates a gRPC client, which will connect to addr upon the
  29. // start. Note Client#Start returns an error if connection is unsuccessful and
  30. // mustConnect is true.
  31. //
  32. // GRPC calls are synchronous, but some callbacks expect to be called
  33. // asynchronously (eg. the mempool expects to be able to lock to remove bad txs
  34. // from cache). To accommodate, we finish each call in its own go-routine,
  35. // which is expensive, but easy - if you want something better, use the socket
  36. // protocol! maybe one day, if people really want it, we use grpc streams, but
  37. // hopefully not :D
  38. func NewGRPCClient(addr string, mustConnect bool) Client {
  39. cli := &grpcClient{
  40. addr: addr,
  41. mustConnect: mustConnect,
  42. // Buffering the channel is needed to make calls appear asynchronous,
  43. // which is required when the caller makes multiple async calls before
  44. // processing callbacks (e.g. due to holding locks). 64 means that a
  45. // caller can make up to 64 async calls before a callback must be
  46. // processed (otherwise it deadlocks). It also means that we can make 64
  47. // gRPC calls while processing a slow callback at the channel head.
  48. chReqRes: make(chan *ReqRes, 64),
  49. }
  50. cli.BaseService = *service.NewBaseService(nil, "grpcClient", cli)
  51. return cli
  52. }
  53. func dialerFunc(ctx context.Context, addr string) (net.Conn, error) {
  54. return tmnet.Connect(addr)
  55. }
  56. func (cli *grpcClient) OnStart() error {
  57. // This processes asynchronous request/response messages and dispatches
  58. // them to callbacks.
  59. go func() {
  60. // Use a separate function to use defer for mutex unlocks (this handles panics)
  61. callCb := func(reqres *ReqRes) {
  62. cli.mtx.Lock()
  63. defer cli.mtx.Unlock()
  64. reqres.SetDone()
  65. reqres.Done()
  66. // Notify client listener if set
  67. if cli.resCb != nil {
  68. cli.resCb(reqres.Request, reqres.Response)
  69. }
  70. // Notify reqRes listener if set
  71. if cb := reqres.GetCallback(); cb != nil {
  72. cb(reqres.Response)
  73. }
  74. }
  75. for reqres := range cli.chReqRes {
  76. if reqres != nil {
  77. callCb(reqres)
  78. } else {
  79. cli.Logger.Error("Received nil reqres")
  80. }
  81. }
  82. }()
  83. RETRY_LOOP:
  84. for {
  85. conn, err := grpc.Dial(cli.addr,
  86. grpc.WithTransportCredentials(insecure.NewCredentials()),
  87. grpc.WithContextDialer(dialerFunc),
  88. )
  89. if err != nil {
  90. if cli.mustConnect {
  91. return err
  92. }
  93. cli.Logger.Error(fmt.Sprintf("abci.grpcClient failed to connect to %v. Retrying...\n", cli.addr), "err", err)
  94. time.Sleep(time.Second * dialRetryIntervalSeconds)
  95. continue RETRY_LOOP
  96. }
  97. cli.Logger.Info("Dialed server. Waiting for echo.", "addr", cli.addr)
  98. client := types.NewABCIApplicationClient(conn)
  99. cli.conn = conn
  100. ENSURE_CONNECTED:
  101. for {
  102. _, err := client.Echo(context.Background(), &types.RequestEcho{Message: "hello"}, grpc.WaitForReady(true))
  103. if err == nil {
  104. break ENSURE_CONNECTED
  105. }
  106. cli.Logger.Error("Echo failed", "err", err)
  107. time.Sleep(time.Second * echoRetryIntervalSeconds)
  108. }
  109. cli.client = client
  110. return nil
  111. }
  112. }
  113. func (cli *grpcClient) OnStop() {
  114. if cli.conn != nil {
  115. cli.conn.Close()
  116. }
  117. close(cli.chReqRes)
  118. }
  119. func (cli *grpcClient) StopForError(err error) {
  120. if !cli.IsRunning() {
  121. return
  122. }
  123. cli.mtx.Lock()
  124. if cli.err == nil {
  125. cli.err = err
  126. }
  127. cli.mtx.Unlock()
  128. cli.Logger.Error(fmt.Sprintf("Stopping abci.grpcClient for error: %v", err.Error()))
  129. if err := cli.Stop(); err != nil {
  130. cli.Logger.Error("Error stopping abci.grpcClient", "err", err)
  131. }
  132. }
  133. func (cli *grpcClient) Error() error {
  134. cli.mtx.Lock()
  135. defer cli.mtx.Unlock()
  136. return cli.err
  137. }
  138. // Set listener for all responses
  139. // NOTE: callback may get internally generated flush responses.
  140. func (cli *grpcClient) SetResponseCallback(resCb Callback) {
  141. cli.mtx.Lock()
  142. cli.resCb = resCb
  143. cli.mtx.Unlock()
  144. }
  145. //----------------------------------------
  146. // NOTE: call is synchronous, use ctx to break early if needed
  147. func (cli *grpcClient) EchoAsync(ctx context.Context, msg string) (*ReqRes, error) {
  148. req := types.ToRequestEcho(msg)
  149. res, err := cli.client.Echo(ctx, req.GetEcho(), grpc.WaitForReady(true))
  150. if err != nil {
  151. return nil, err
  152. }
  153. return cli.finishAsyncCall(ctx, req, &types.Response{Value: &types.Response_Echo{Echo: res}})
  154. }
  155. // NOTE: call is synchronous, use ctx to break early if needed
  156. func (cli *grpcClient) FlushAsync(ctx context.Context) (*ReqRes, error) {
  157. req := types.ToRequestFlush()
  158. res, err := cli.client.Flush(ctx, req.GetFlush(), grpc.WaitForReady(true))
  159. if err != nil {
  160. return nil, err
  161. }
  162. return cli.finishAsyncCall(ctx, req, &types.Response{Value: &types.Response_Flush{Flush: res}})
  163. }
  164. // NOTE: call is synchronous, use ctx to break early if needed
  165. func (cli *grpcClient) InfoAsync(ctx context.Context, params types.RequestInfo) (*ReqRes, error) {
  166. req := types.ToRequestInfo(params)
  167. res, err := cli.client.Info(ctx, req.GetInfo(), grpc.WaitForReady(true))
  168. if err != nil {
  169. return nil, err
  170. }
  171. return cli.finishAsyncCall(ctx, req, &types.Response{Value: &types.Response_Info{Info: res}})
  172. }
  173. // NOTE: call is synchronous, use ctx to break early if needed
  174. func (cli *grpcClient) DeliverTxAsync(ctx context.Context, params types.RequestDeliverTx) (*ReqRes, error) {
  175. req := types.ToRequestDeliverTx(params)
  176. res, err := cli.client.DeliverTx(ctx, req.GetDeliverTx(), grpc.WaitForReady(true))
  177. if err != nil {
  178. return nil, err
  179. }
  180. return cli.finishAsyncCall(ctx, req, &types.Response{Value: &types.Response_DeliverTx{DeliverTx: res}})
  181. }
  182. // NOTE: call is synchronous, use ctx to break early if needed
  183. func (cli *grpcClient) CheckTxAsync(ctx context.Context, params types.RequestCheckTx) (*ReqRes, error) {
  184. req := types.ToRequestCheckTx(params)
  185. res, err := cli.client.CheckTx(ctx, req.GetCheckTx(), grpc.WaitForReady(true))
  186. if err != nil {
  187. return nil, err
  188. }
  189. return cli.finishAsyncCall(ctx, req, &types.Response{Value: &types.Response_CheckTx{CheckTx: res}})
  190. }
  191. // NOTE: call is synchronous, use ctx to break early if needed
  192. func (cli *grpcClient) QueryAsync(ctx context.Context, params types.RequestQuery) (*ReqRes, error) {
  193. req := types.ToRequestQuery(params)
  194. res, err := cli.client.Query(ctx, req.GetQuery(), grpc.WaitForReady(true))
  195. if err != nil {
  196. return nil, err
  197. }
  198. return cli.finishAsyncCall(ctx, req, &types.Response{Value: &types.Response_Query{Query: res}})
  199. }
  200. // NOTE: call is synchronous, use ctx to break early if needed
  201. func (cli *grpcClient) CommitAsync(ctx context.Context) (*ReqRes, error) {
  202. req := types.ToRequestCommit()
  203. res, err := cli.client.Commit(ctx, req.GetCommit(), grpc.WaitForReady(true))
  204. if err != nil {
  205. return nil, err
  206. }
  207. return cli.finishAsyncCall(ctx, req, &types.Response{Value: &types.Response_Commit{Commit: res}})
  208. }
  209. // NOTE: call is synchronous, use ctx to break early if needed
  210. func (cli *grpcClient) InitChainAsync(ctx context.Context, params types.RequestInitChain) (*ReqRes, error) {
  211. req := types.ToRequestInitChain(params)
  212. res, err := cli.client.InitChain(ctx, req.GetInitChain(), grpc.WaitForReady(true))
  213. if err != nil {
  214. return nil, err
  215. }
  216. return cli.finishAsyncCall(ctx, req, &types.Response{Value: &types.Response_InitChain{InitChain: res}})
  217. }
  218. // NOTE: call is synchronous, use ctx to break early if needed
  219. func (cli *grpcClient) BeginBlockAsync(ctx context.Context, params types.RequestBeginBlock) (*ReqRes, error) {
  220. req := types.ToRequestBeginBlock(params)
  221. res, err := cli.client.BeginBlock(ctx, req.GetBeginBlock(), grpc.WaitForReady(true))
  222. if err != nil {
  223. return nil, err
  224. }
  225. return cli.finishAsyncCall(ctx, req, &types.Response{Value: &types.Response_BeginBlock{BeginBlock: res}})
  226. }
  227. // NOTE: call is synchronous, use ctx to break early if needed
  228. func (cli *grpcClient) EndBlockAsync(ctx context.Context, params types.RequestEndBlock) (*ReqRes, error) {
  229. req := types.ToRequestEndBlock(params)
  230. res, err := cli.client.EndBlock(ctx, req.GetEndBlock(), grpc.WaitForReady(true))
  231. if err != nil {
  232. return nil, err
  233. }
  234. return cli.finishAsyncCall(ctx, req, &types.Response{Value: &types.Response_EndBlock{EndBlock: res}})
  235. }
  236. // NOTE: call is synchronous, use ctx to break early if needed
  237. func (cli *grpcClient) ListSnapshotsAsync(ctx context.Context, params types.RequestListSnapshots) (*ReqRes, error) {
  238. req := types.ToRequestListSnapshots(params)
  239. res, err := cli.client.ListSnapshots(ctx, req.GetListSnapshots(), grpc.WaitForReady(true))
  240. if err != nil {
  241. return nil, err
  242. }
  243. return cli.finishAsyncCall(ctx, req, &types.Response{Value: &types.Response_ListSnapshots{ListSnapshots: res}})
  244. }
  245. // NOTE: call is synchronous, use ctx to break early if needed
  246. func (cli *grpcClient) OfferSnapshotAsync(ctx context.Context, params types.RequestOfferSnapshot) (*ReqRes, error) {
  247. req := types.ToRequestOfferSnapshot(params)
  248. res, err := cli.client.OfferSnapshot(ctx, req.GetOfferSnapshot(), grpc.WaitForReady(true))
  249. if err != nil {
  250. return nil, err
  251. }
  252. return cli.finishAsyncCall(ctx, req, &types.Response{Value: &types.Response_OfferSnapshot{OfferSnapshot: res}})
  253. }
  254. // NOTE: call is synchronous, use ctx to break early if needed
  255. func (cli *grpcClient) LoadSnapshotChunkAsync(
  256. ctx context.Context,
  257. params types.RequestLoadSnapshotChunk,
  258. ) (*ReqRes, error) {
  259. req := types.ToRequestLoadSnapshotChunk(params)
  260. res, err := cli.client.LoadSnapshotChunk(ctx, req.GetLoadSnapshotChunk(), grpc.WaitForReady(true))
  261. if err != nil {
  262. return nil, err
  263. }
  264. return cli.finishAsyncCall(ctx, req, &types.Response{Value: &types.Response_LoadSnapshotChunk{LoadSnapshotChunk: res}})
  265. }
  266. // NOTE: call is synchronous, use ctx to break early if needed
  267. func (cli *grpcClient) ApplySnapshotChunkAsync(
  268. ctx context.Context,
  269. params types.RequestApplySnapshotChunk,
  270. ) (*ReqRes, error) {
  271. req := types.ToRequestApplySnapshotChunk(params)
  272. res, err := cli.client.ApplySnapshotChunk(ctx, req.GetApplySnapshotChunk(), grpc.WaitForReady(true))
  273. if err != nil {
  274. return nil, err
  275. }
  276. return cli.finishAsyncCall(
  277. ctx,
  278. req,
  279. &types.Response{Value: &types.Response_ApplySnapshotChunk{ApplySnapshotChunk: res}},
  280. )
  281. }
  282. // finishAsyncCall creates a ReqRes for an async call, and immediately populates it
  283. // with the response. We don't complete it until it's been ordered via the channel.
  284. func (cli *grpcClient) finishAsyncCall(ctx context.Context, req *types.Request, res *types.Response) (*ReqRes, error) {
  285. reqres := NewReqRes(req)
  286. reqres.Response = res
  287. select {
  288. case cli.chReqRes <- reqres: // use channel for async responses, since they must be ordered
  289. return reqres, nil
  290. case <-ctx.Done():
  291. return nil, ctx.Err()
  292. }
  293. }
  294. // finishSyncCall waits for an async call to complete. It is necessary to call all
  295. // sync calls asynchronously as well, to maintain call and response ordering via
  296. // the channel, and this method will wait until the async call completes.
  297. func (cli *grpcClient) finishSyncCall(reqres *ReqRes) *types.Response {
  298. // It's possible that the callback is called twice, since the callback can
  299. // be called immediately on SetCallback() in addition to after it has been
  300. // set. This is because completing the ReqRes happens in a separate critical
  301. // section from the one where the callback is called: there is a race where
  302. // SetCallback() is called between completing the ReqRes and dispatching the
  303. // callback.
  304. //
  305. // We also buffer the channel with 1 response, since SetCallback() will be
  306. // called synchronously if the reqres is already completed, in which case
  307. // it will block on sending to the channel since it hasn't gotten around to
  308. // receiving from it yet.
  309. //
  310. // ReqRes should really handle callback dispatch internally, to guarantee
  311. // that it's only called once and avoid the above race conditions.
  312. var once sync.Once
  313. ch := make(chan *types.Response, 1)
  314. reqres.SetCallback(func(res *types.Response) {
  315. once.Do(func() {
  316. ch <- res
  317. })
  318. })
  319. return <-ch
  320. }
  321. //----------------------------------------
  322. func (cli *grpcClient) FlushSync(ctx context.Context) error {
  323. return nil
  324. }
  325. func (cli *grpcClient) EchoSync(ctx context.Context, msg string) (*types.ResponseEcho, error) {
  326. reqres, err := cli.EchoAsync(ctx, msg)
  327. if err != nil {
  328. return nil, err
  329. }
  330. return cli.finishSyncCall(reqres).GetEcho(), cli.Error()
  331. }
  332. func (cli *grpcClient) InfoSync(
  333. ctx context.Context,
  334. req types.RequestInfo,
  335. ) (*types.ResponseInfo, error) {
  336. reqres, err := cli.InfoAsync(ctx, req)
  337. if err != nil {
  338. return nil, err
  339. }
  340. return cli.finishSyncCall(reqres).GetInfo(), cli.Error()
  341. }
  342. func (cli *grpcClient) DeliverTxSync(
  343. ctx context.Context,
  344. params types.RequestDeliverTx,
  345. ) (*types.ResponseDeliverTx, error) {
  346. reqres, err := cli.DeliverTxAsync(ctx, params)
  347. if err != nil {
  348. return nil, err
  349. }
  350. return cli.finishSyncCall(reqres).GetDeliverTx(), cli.Error()
  351. }
  352. func (cli *grpcClient) CheckTxSync(
  353. ctx context.Context,
  354. params types.RequestCheckTx,
  355. ) (*types.ResponseCheckTx, error) {
  356. reqres, err := cli.CheckTxAsync(ctx, params)
  357. if err != nil {
  358. return nil, err
  359. }
  360. return cli.finishSyncCall(reqres).GetCheckTx(), cli.Error()
  361. }
  362. func (cli *grpcClient) QuerySync(
  363. ctx context.Context,
  364. req types.RequestQuery,
  365. ) (*types.ResponseQuery, error) {
  366. reqres, err := cli.QueryAsync(ctx, req)
  367. if err != nil {
  368. return nil, err
  369. }
  370. return cli.finishSyncCall(reqres).GetQuery(), cli.Error()
  371. }
  372. func (cli *grpcClient) CommitSync(ctx context.Context) (*types.ResponseCommit, error) {
  373. reqres, err := cli.CommitAsync(ctx)
  374. if err != nil {
  375. return nil, err
  376. }
  377. return cli.finishSyncCall(reqres).GetCommit(), cli.Error()
  378. }
  379. func (cli *grpcClient) InitChainSync(
  380. ctx context.Context,
  381. params types.RequestInitChain,
  382. ) (*types.ResponseInitChain, error) {
  383. reqres, err := cli.InitChainAsync(ctx, params)
  384. if err != nil {
  385. return nil, err
  386. }
  387. return cli.finishSyncCall(reqres).GetInitChain(), cli.Error()
  388. }
  389. func (cli *grpcClient) BeginBlockSync(
  390. ctx context.Context,
  391. params types.RequestBeginBlock,
  392. ) (*types.ResponseBeginBlock, error) {
  393. reqres, err := cli.BeginBlockAsync(ctx, params)
  394. if err != nil {
  395. return nil, err
  396. }
  397. return cli.finishSyncCall(reqres).GetBeginBlock(), cli.Error()
  398. }
  399. func (cli *grpcClient) EndBlockSync(
  400. ctx context.Context,
  401. params types.RequestEndBlock,
  402. ) (*types.ResponseEndBlock, error) {
  403. reqres, err := cli.EndBlockAsync(ctx, params)
  404. if err != nil {
  405. return nil, err
  406. }
  407. return cli.finishSyncCall(reqres).GetEndBlock(), cli.Error()
  408. }
  409. func (cli *grpcClient) ListSnapshotsSync(
  410. ctx context.Context,
  411. params types.RequestListSnapshots,
  412. ) (*types.ResponseListSnapshots, error) {
  413. reqres, err := cli.ListSnapshotsAsync(ctx, params)
  414. if err != nil {
  415. return nil, err
  416. }
  417. return cli.finishSyncCall(reqres).GetListSnapshots(), cli.Error()
  418. }
  419. func (cli *grpcClient) OfferSnapshotSync(
  420. ctx context.Context,
  421. params types.RequestOfferSnapshot,
  422. ) (*types.ResponseOfferSnapshot, error) {
  423. reqres, err := cli.OfferSnapshotAsync(ctx, params)
  424. if err != nil {
  425. return nil, err
  426. }
  427. return cli.finishSyncCall(reqres).GetOfferSnapshot(), cli.Error()
  428. }
  429. func (cli *grpcClient) LoadSnapshotChunkSync(
  430. ctx context.Context,
  431. params types.RequestLoadSnapshotChunk) (*types.ResponseLoadSnapshotChunk, error) {
  432. reqres, err := cli.LoadSnapshotChunkAsync(ctx, params)
  433. if err != nil {
  434. return nil, err
  435. }
  436. return cli.finishSyncCall(reqres).GetLoadSnapshotChunk(), cli.Error()
  437. }
  438. func (cli *grpcClient) ApplySnapshotChunkSync(
  439. ctx context.Context,
  440. params types.RequestApplySnapshotChunk) (*types.ResponseApplySnapshotChunk, error) {
  441. reqres, err := cli.ApplySnapshotChunkAsync(ctx, params)
  442. if err != nil {
  443. return nil, err
  444. }
  445. return cli.finishSyncCall(reqres).GetApplySnapshotChunk(), cli.Error()
  446. }