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.

525 lines
16 KiB

build(deps): Bump google.golang.org/grpc from 1.42.0 to 1.43.0 (#7455) Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.42.0 to 1.43.0. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/grpc/grpc-go/releases">google.golang.org/grpc's releases</a>.</em></p> <blockquote> <h2>Release 1.43.0</h2> <h1>API Changes</h1> <ul> <li>grpc: stabilize <code>WithConnectParams</code> <code>DialOption</code> (<a href="https://github-redirect.dependabot.com/grpc/grpc-go/issues/4915">#4915</a>) <ul> <li>Special Thanks: <a href="https://github.com/hypnoglow"><code>@​hypnoglow</code></a></li> </ul> </li> </ul> <h1>Behavior Changes</h1> <ul> <li>status: support wrapped errors in <code>FromContextError</code> (<a href="https://github-redirect.dependabot.com/grpc/grpc-go/issues/4977">#4977</a>) <ul> <li>Special Thanks: <a href="https://github.com/bestbeforetoday"><code>@​bestbeforetoday</code></a></li> </ul> </li> <li>config: remove the environment variable to disable retry support (<a href="https://github-redirect.dependabot.com/grpc/grpc-go/issues/4922">#4922</a>)</li> </ul> <h1>New Features</h1> <ul> <li>balancer: new field <code>Authority</code> in <code>BuildOptions</code> for server name to use in the authentication handshake with a remote load balancer (<a href="https://github-redirect.dependabot.com/grpc/grpc-go/issues/4969">#4969</a>)</li> </ul> <h1>Bug Fixes</h1> <ul> <li>xds/resolver: fix possible <code>ClientConn</code> leak upon resolver initialization failure (<a href="https://github-redirect.dependabot.com/grpc/grpc-go/issues/4900">#4900</a>)</li> <li>client: fix <code>nil</code> panic in rare race conditions with the pick first LB policy (<a href="https://github-redirect.dependabot.com/grpc/grpc-go/issues/4971">#4971</a>)</li> <li>xds: improve RPC error messages when xDS connection errors occur (<a href="https://github-redirect.dependabot.com/grpc/grpc-go/issues/5032">#5032</a>, <a href="https://github-redirect.dependabot.com/grpc/grpc-go/issues/5054">#5054</a>)</li> <li>transport: do not create stream object in the face of illegal stream IDs (<a href="https://github-redirect.dependabot.com/grpc/grpc-go/issues/4873">#4873</a>) <ul> <li>Special Thanks: <a href="https://github.com/uds5501"><code>@​uds5501</code></a></li> </ul> </li> </ul> <h1>Documentation</h1> <ul> <li>client: clarify errors to indicate whether compressed or uncompressed messages exceeded size limits (<a href="https://github-redirect.dependabot.com/grpc/grpc-go/issues/4918">#4918</a>) <ul> <li>Special Thanks: <a href="https://github.com/uds5501"><code>@​uds5501</code></a></li> </ul> </li> </ul> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/grpc/grpc-go/commit/14c11384b76b67f7b1b32a5d18f865762634c0ae"><code>14c1138</code></a> Change version to 1.43.0 (<a href="https://github-redirect.dependabot.com/grpc/grpc-go/issues/5039">#5039</a>)</li> <li><a href="https://github.com/grpc/grpc-go/commit/ae29ac3e1e62a7b47fb672dec21de2dd83e4f027"><code>ae29ac3</code></a> xds/client: send NewStream errors to the watchers (<a href="https://github-redirect.dependabot.com/grpc/grpc-go/issues/5032">#5032</a>)</li> <li><a href="https://github.com/grpc/grpc-go/commit/296afc2e579c14228edadb3debcb040204a0870f"><code>296afc2</code></a> transport: better error message when per-RPC creds fail (<a href="https://github-redirect.dependabot.com/grpc/grpc-go/issues/5033">#5033</a>)</li> <li><a href="https://github.com/grpc/grpc-go/commit/e15d978c827661f8e7cfe807cb9fd8fd8f15a262"><code>e15d978</code></a> xds/client: send connection errors to all watchers (<a href="https://github-redirect.dependabot.com/grpc/grpc-go/issues/5054">#5054</a>)</li> <li><a href="https://github.com/grpc/grpc-go/commit/46e883a9ab006a3000afe0a510aea62b75495b8f"><code>46e883a</code></a> Backport &quot;xds/c2p: replace C2P resolver env var with experimental scheme suff...</li> <li><a href="https://github.com/grpc/grpc-go/commit/3786ae1778f5bfcc49da81cbd925b7175ec81839"><code>3786ae1</code></a> xds/resolver: Add support for cluster specifier plugins (<a href="https://github-redirect.dependabot.com/grpc/grpc-go/issues/4987">#4987</a>)</li> <li><a href="https://github.com/grpc/grpc-go/commit/512e89474bfbd567806e026e0afdec468b1ee1ea"><code>512e894</code></a> rls: support extra_keys and constant_keys (<a href="https://github-redirect.dependabot.com/grpc/grpc-go/issues/4995">#4995</a>)</li> <li><a href="https://github.com/grpc/grpc-go/commit/f3bbd12084380987ae0c9fcccdd7c4d405294a68"><code>f3bbd12</code></a> xds/bootstrap_config: add a string function to server config (<a href="https://github-redirect.dependabot.com/grpc/grpc-go/issues/5031">#5031</a>)</li> <li><a href="https://github.com/grpc/grpc-go/commit/46935b96506deef74e73192e70cc44e3795b1452"><code>46935b9</code></a> fix possible nil before casting (<a href="https://github-redirect.dependabot.com/grpc/grpc-go/issues/5017">#5017</a>)</li> <li><a href="https://github.com/grpc/grpc-go/commit/c2bccd0b1594416da57a74d15f09f8eb0a3d727b"><code>c2bccd0</code></a> xds/kokoro: install go 1.17, and retry go build (<a href="https://github-redirect.dependabot.com/grpc/grpc-go/issues/5015">#5015</a>)</li> <li>Additional commits viewable in <a href="https://github.com/grpc/grpc-go/compare/v1.42.0...v1.43.0">compare view</a></li> </ul> </details> <br /> [![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=google.golang.org/grpc&package-manager=go_modules&previous-version=1.42.0&new-version=1.43.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) </details>
2 years ago
build(deps): Bump google.golang.org/grpc from 1.42.0 to 1.43.0 (#7455) Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.42.0 to 1.43.0. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/grpc/grpc-go/releases">google.golang.org/grpc's releases</a>.</em></p> <blockquote> <h2>Release 1.43.0</h2> <h1>API Changes</h1> <ul> <li>grpc: stabilize <code>WithConnectParams</code> <code>DialOption</code> (<a href="https://github-redirect.dependabot.com/grpc/grpc-go/issues/4915">#4915</a>) <ul> <li>Special Thanks: <a href="https://github.com/hypnoglow"><code>@​hypnoglow</code></a></li> </ul> </li> </ul> <h1>Behavior Changes</h1> <ul> <li>status: support wrapped errors in <code>FromContextError</code> (<a href="https://github-redirect.dependabot.com/grpc/grpc-go/issues/4977">#4977</a>) <ul> <li>Special Thanks: <a href="https://github.com/bestbeforetoday"><code>@​bestbeforetoday</code></a></li> </ul> </li> <li>config: remove the environment variable to disable retry support (<a href="https://github-redirect.dependabot.com/grpc/grpc-go/issues/4922">#4922</a>)</li> </ul> <h1>New Features</h1> <ul> <li>balancer: new field <code>Authority</code> in <code>BuildOptions</code> for server name to use in the authentication handshake with a remote load balancer (<a href="https://github-redirect.dependabot.com/grpc/grpc-go/issues/4969">#4969</a>)</li> </ul> <h1>Bug Fixes</h1> <ul> <li>xds/resolver: fix possible <code>ClientConn</code> leak upon resolver initialization failure (<a href="https://github-redirect.dependabot.com/grpc/grpc-go/issues/4900">#4900</a>)</li> <li>client: fix <code>nil</code> panic in rare race conditions with the pick first LB policy (<a href="https://github-redirect.dependabot.com/grpc/grpc-go/issues/4971">#4971</a>)</li> <li>xds: improve RPC error messages when xDS connection errors occur (<a href="https://github-redirect.dependabot.com/grpc/grpc-go/issues/5032">#5032</a>, <a href="https://github-redirect.dependabot.com/grpc/grpc-go/issues/5054">#5054</a>)</li> <li>transport: do not create stream object in the face of illegal stream IDs (<a href="https://github-redirect.dependabot.com/grpc/grpc-go/issues/4873">#4873</a>) <ul> <li>Special Thanks: <a href="https://github.com/uds5501"><code>@​uds5501</code></a></li> </ul> </li> </ul> <h1>Documentation</h1> <ul> <li>client: clarify errors to indicate whether compressed or uncompressed messages exceeded size limits (<a href="https://github-redirect.dependabot.com/grpc/grpc-go/issues/4918">#4918</a>) <ul> <li>Special Thanks: <a href="https://github.com/uds5501"><code>@​uds5501</code></a></li> </ul> </li> </ul> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/grpc/grpc-go/commit/14c11384b76b67f7b1b32a5d18f865762634c0ae"><code>14c1138</code></a> Change version to 1.43.0 (<a href="https://github-redirect.dependabot.com/grpc/grpc-go/issues/5039">#5039</a>)</li> <li><a href="https://github.com/grpc/grpc-go/commit/ae29ac3e1e62a7b47fb672dec21de2dd83e4f027"><code>ae29ac3</code></a> xds/client: send NewStream errors to the watchers (<a href="https://github-redirect.dependabot.com/grpc/grpc-go/issues/5032">#5032</a>)</li> <li><a href="https://github.com/grpc/grpc-go/commit/296afc2e579c14228edadb3debcb040204a0870f"><code>296afc2</code></a> transport: better error message when per-RPC creds fail (<a href="https://github-redirect.dependabot.com/grpc/grpc-go/issues/5033">#5033</a>)</li> <li><a href="https://github.com/grpc/grpc-go/commit/e15d978c827661f8e7cfe807cb9fd8fd8f15a262"><code>e15d978</code></a> xds/client: send connection errors to all watchers (<a href="https://github-redirect.dependabot.com/grpc/grpc-go/issues/5054">#5054</a>)</li> <li><a href="https://github.com/grpc/grpc-go/commit/46e883a9ab006a3000afe0a510aea62b75495b8f"><code>46e883a</code></a> Backport &quot;xds/c2p: replace C2P resolver env var with experimental scheme suff...</li> <li><a href="https://github.com/grpc/grpc-go/commit/3786ae1778f5bfcc49da81cbd925b7175ec81839"><code>3786ae1</code></a> xds/resolver: Add support for cluster specifier plugins (<a href="https://github-redirect.dependabot.com/grpc/grpc-go/issues/4987">#4987</a>)</li> <li><a href="https://github.com/grpc/grpc-go/commit/512e89474bfbd567806e026e0afdec468b1ee1ea"><code>512e894</code></a> rls: support extra_keys and constant_keys (<a href="https://github-redirect.dependabot.com/grpc/grpc-go/issues/4995">#4995</a>)</li> <li><a href="https://github.com/grpc/grpc-go/commit/f3bbd12084380987ae0c9fcccdd7c4d405294a68"><code>f3bbd12</code></a> xds/bootstrap_config: add a string function to server config (<a href="https://github-redirect.dependabot.com/grpc/grpc-go/issues/5031">#5031</a>)</li> <li><a href="https://github.com/grpc/grpc-go/commit/46935b96506deef74e73192e70cc44e3795b1452"><code>46935b9</code></a> fix possible nil before casting (<a href="https://github-redirect.dependabot.com/grpc/grpc-go/issues/5017">#5017</a>)</li> <li><a href="https://github.com/grpc/grpc-go/commit/c2bccd0b1594416da57a74d15f09f8eb0a3d727b"><code>c2bccd0</code></a> xds/kokoro: install go 1.17, and retry go build (<a href="https://github-redirect.dependabot.com/grpc/grpc-go/issues/5015">#5015</a>)</li> <li>Additional commits viewable in <a href="https://github.com/grpc/grpc-go/compare/v1.42.0...v1.43.0">compare view</a></li> </ul> </details> <br /> [![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=google.golang.org/grpc&package-manager=go_modules&previous-version=1.42.0&new-version=1.43.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) </details>
2 years ago
8 years ago
8 years ago
7 years ago
8 years ago
8 years ago
8 years ago
  1. package abciclient
  2. import (
  3. "context"
  4. "errors"
  5. "fmt"
  6. "net"
  7. "sync"
  8. "time"
  9. "google.golang.org/grpc"
  10. "google.golang.org/grpc/credentials/insecure"
  11. "github.com/tendermint/tendermint/abci/types"
  12. "github.com/tendermint/tendermint/libs/log"
  13. tmnet "github.com/tendermint/tendermint/libs/net"
  14. "github.com/tendermint/tendermint/libs/service"
  15. )
  16. // A gRPC client.
  17. type grpcClient struct {
  18. service.BaseService
  19. logger log.Logger
  20. mustConnect bool
  21. client types.ABCIApplicationClient
  22. conn *grpc.ClientConn
  23. chReqRes chan *ReqRes // dispatches "async" responses to callbacks *in order*, needed by mempool
  24. mtx sync.Mutex
  25. addr string
  26. err error
  27. resCb func(*types.Request, *types.Response) // listens to all callbacks
  28. }
  29. var _ Client = (*grpcClient)(nil)
  30. // NewGRPCClient creates a gRPC client, which will connect to addr upon the
  31. // start. Note Client#Start returns an error if connection is unsuccessful and
  32. // mustConnect is true.
  33. //
  34. // GRPC calls are synchronous, but some callbacks expect to be called
  35. // asynchronously (eg. the mempool expects to be able to lock to remove bad txs
  36. // from cache). To accommodate, we finish each call in its own go-routine,
  37. // which is expensive, but easy - if you want something better, use the socket
  38. // protocol! maybe one day, if people really want it, we use grpc streams, but
  39. // hopefully not :D
  40. func NewGRPCClient(logger log.Logger, addr string, mustConnect bool) Client {
  41. cli := &grpcClient{
  42. logger: logger,
  43. addr: addr,
  44. mustConnect: mustConnect,
  45. // Buffering the channel is needed to make calls appear asynchronous,
  46. // which is required when the caller makes multiple async calls before
  47. // processing callbacks (e.g. due to holding locks). 64 means that a
  48. // caller can make up to 64 async calls before a callback must be
  49. // processed (otherwise it deadlocks). It also means that we can make 64
  50. // gRPC calls while processing a slow callback at the channel head.
  51. chReqRes: make(chan *ReqRes, 64),
  52. }
  53. cli.BaseService = *service.NewBaseService(logger, "grpcClient", cli)
  54. return cli
  55. }
  56. func dialerFunc(ctx context.Context, addr string) (net.Conn, error) {
  57. return tmnet.Connect(addr)
  58. }
  59. func (cli *grpcClient) OnStart(ctx context.Context) error {
  60. // This processes asynchronous request/response messages and dispatches
  61. // them to callbacks.
  62. go func() {
  63. // Use a separate function to use defer for mutex unlocks (this handles panics)
  64. callCb := func(reqres *ReqRes) {
  65. cli.mtx.Lock()
  66. defer cli.mtx.Unlock()
  67. reqres.SetDone()
  68. reqres.Done()
  69. // Notify client listener if set
  70. if cli.resCb != nil {
  71. cli.resCb(reqres.Request, reqres.Response)
  72. }
  73. // Notify reqRes listener if set
  74. if cb := reqres.GetCallback(); cb != nil {
  75. cb(reqres.Response)
  76. }
  77. }
  78. for {
  79. select {
  80. case reqres := <-cli.chReqRes:
  81. if reqres != nil {
  82. callCb(reqres)
  83. } else {
  84. cli.logger.Error("Received nil reqres")
  85. }
  86. case <-ctx.Done():
  87. return
  88. }
  89. }
  90. }()
  91. RETRY_LOOP:
  92. for {
  93. conn, err := grpc.Dial(cli.addr,
  94. grpc.WithTransportCredentials(insecure.NewCredentials()),
  95. grpc.WithContextDialer(dialerFunc),
  96. )
  97. if err != nil {
  98. if cli.mustConnect {
  99. return err
  100. }
  101. cli.logger.Error(fmt.Sprintf("abci.grpcClient failed to connect to %v. Retrying...\n", cli.addr), "err", err)
  102. time.Sleep(time.Second * dialRetryIntervalSeconds)
  103. continue RETRY_LOOP
  104. }
  105. cli.logger.Info("Dialed server. Waiting for echo.", "addr", cli.addr)
  106. client := types.NewABCIApplicationClient(conn)
  107. cli.conn = conn
  108. ENSURE_CONNECTED:
  109. for {
  110. _, err := client.Echo(ctx, &types.RequestEcho{Message: "hello"}, grpc.WaitForReady(true))
  111. if err == nil {
  112. break ENSURE_CONNECTED
  113. }
  114. if errors.Is(err, context.Canceled) || errors.Is(err, context.DeadlineExceeded) {
  115. return err
  116. }
  117. cli.logger.Error("Echo failed", "err", err)
  118. time.Sleep(time.Second * echoRetryIntervalSeconds)
  119. }
  120. cli.client = client
  121. return nil
  122. }
  123. }
  124. func (cli *grpcClient) OnStop() {
  125. if cli.conn != nil {
  126. cli.conn.Close()
  127. }
  128. close(cli.chReqRes)
  129. }
  130. func (cli *grpcClient) StopForError(err error) {
  131. if !cli.IsRunning() {
  132. return
  133. }
  134. cli.mtx.Lock()
  135. if cli.err == nil {
  136. cli.err = err
  137. }
  138. cli.mtx.Unlock()
  139. cli.logger.Error("Stopping abci.grpcClient for error", "err", err)
  140. if err := cli.Stop(); err != nil {
  141. cli.logger.Error("error stopping abci.grpcClient", "err", err)
  142. }
  143. }
  144. func (cli *grpcClient) Error() error {
  145. cli.mtx.Lock()
  146. defer cli.mtx.Unlock()
  147. return cli.err
  148. }
  149. // Set listener for all responses
  150. // NOTE: callback may get internally generated flush responses.
  151. func (cli *grpcClient) SetResponseCallback(resCb Callback) {
  152. cli.mtx.Lock()
  153. cli.resCb = resCb
  154. cli.mtx.Unlock()
  155. }
  156. //----------------------------------------
  157. // NOTE: call is synchronous, use ctx to break early if needed
  158. func (cli *grpcClient) EchoAsync(ctx context.Context, msg string) (*ReqRes, error) {
  159. req := types.ToRequestEcho(msg)
  160. res, err := cli.client.Echo(ctx, req.GetEcho(), grpc.WaitForReady(true))
  161. if err != nil {
  162. return nil, err
  163. }
  164. return cli.finishAsyncCall(ctx, req, &types.Response{Value: &types.Response_Echo{Echo: res}})
  165. }
  166. // NOTE: call is synchronous, use ctx to break early if needed
  167. func (cli *grpcClient) FlushAsync(ctx context.Context) (*ReqRes, error) {
  168. req := types.ToRequestFlush()
  169. res, err := cli.client.Flush(ctx, req.GetFlush(), grpc.WaitForReady(true))
  170. if err != nil {
  171. return nil, err
  172. }
  173. return cli.finishAsyncCall(ctx, req, &types.Response{Value: &types.Response_Flush{Flush: res}})
  174. }
  175. // NOTE: call is synchronous, use ctx to break early if needed
  176. func (cli *grpcClient) InfoAsync(ctx context.Context, params types.RequestInfo) (*ReqRes, error) {
  177. req := types.ToRequestInfo(params)
  178. res, err := cli.client.Info(ctx, req.GetInfo(), grpc.WaitForReady(true))
  179. if err != nil {
  180. return nil, err
  181. }
  182. return cli.finishAsyncCall(ctx, req, &types.Response{Value: &types.Response_Info{Info: res}})
  183. }
  184. // NOTE: call is synchronous, use ctx to break early if needed
  185. func (cli *grpcClient) DeliverTxAsync(ctx context.Context, params types.RequestDeliverTx) (*ReqRes, error) {
  186. req := types.ToRequestDeliverTx(params)
  187. res, err := cli.client.DeliverTx(ctx, req.GetDeliverTx(), grpc.WaitForReady(true))
  188. if err != nil {
  189. return nil, err
  190. }
  191. return cli.finishAsyncCall(ctx, req, &types.Response{Value: &types.Response_DeliverTx{DeliverTx: res}})
  192. }
  193. // NOTE: call is synchronous, use ctx to break early if needed
  194. func (cli *grpcClient) CheckTxAsync(ctx context.Context, params types.RequestCheckTx) (*ReqRes, error) {
  195. req := types.ToRequestCheckTx(params)
  196. res, err := cli.client.CheckTx(ctx, req.GetCheckTx(), grpc.WaitForReady(true))
  197. if err != nil {
  198. return nil, err
  199. }
  200. return cli.finishAsyncCall(ctx, req, &types.Response{Value: &types.Response_CheckTx{CheckTx: res}})
  201. }
  202. // NOTE: call is synchronous, use ctx to break early if needed
  203. func (cli *grpcClient) QueryAsync(ctx context.Context, params types.RequestQuery) (*ReqRes, error) {
  204. req := types.ToRequestQuery(params)
  205. res, err := cli.client.Query(ctx, req.GetQuery(), grpc.WaitForReady(true))
  206. if err != nil {
  207. return nil, err
  208. }
  209. return cli.finishAsyncCall(ctx, req, &types.Response{Value: &types.Response_Query{Query: res}})
  210. }
  211. // NOTE: call is synchronous, use ctx to break early if needed
  212. func (cli *grpcClient) CommitAsync(ctx context.Context) (*ReqRes, error) {
  213. req := types.ToRequestCommit()
  214. res, err := cli.client.Commit(ctx, req.GetCommit(), grpc.WaitForReady(true))
  215. if err != nil {
  216. return nil, err
  217. }
  218. return cli.finishAsyncCall(ctx, req, &types.Response{Value: &types.Response_Commit{Commit: res}})
  219. }
  220. // NOTE: call is synchronous, use ctx to break early if needed
  221. func (cli *grpcClient) InitChainAsync(ctx context.Context, params types.RequestInitChain) (*ReqRes, error) {
  222. req := types.ToRequestInitChain(params)
  223. res, err := cli.client.InitChain(ctx, req.GetInitChain(), grpc.WaitForReady(true))
  224. if err != nil {
  225. return nil, err
  226. }
  227. return cli.finishAsyncCall(ctx, req, &types.Response{Value: &types.Response_InitChain{InitChain: res}})
  228. }
  229. // NOTE: call is synchronous, use ctx to break early if needed
  230. func (cli *grpcClient) BeginBlockAsync(ctx context.Context, params types.RequestBeginBlock) (*ReqRes, error) {
  231. req := types.ToRequestBeginBlock(params)
  232. res, err := cli.client.BeginBlock(ctx, req.GetBeginBlock(), grpc.WaitForReady(true))
  233. if err != nil {
  234. return nil, err
  235. }
  236. return cli.finishAsyncCall(ctx, req, &types.Response{Value: &types.Response_BeginBlock{BeginBlock: res}})
  237. }
  238. // NOTE: call is synchronous, use ctx to break early if needed
  239. func (cli *grpcClient) EndBlockAsync(ctx context.Context, params types.RequestEndBlock) (*ReqRes, error) {
  240. req := types.ToRequestEndBlock(params)
  241. res, err := cli.client.EndBlock(ctx, req.GetEndBlock(), grpc.WaitForReady(true))
  242. if err != nil {
  243. return nil, err
  244. }
  245. return cli.finishAsyncCall(ctx, req, &types.Response{Value: &types.Response_EndBlock{EndBlock: res}})
  246. }
  247. // NOTE: call is synchronous, use ctx to break early if needed
  248. func (cli *grpcClient) ListSnapshotsAsync(ctx context.Context, params types.RequestListSnapshots) (*ReqRes, error) {
  249. req := types.ToRequestListSnapshots(params)
  250. res, err := cli.client.ListSnapshots(ctx, req.GetListSnapshots(), grpc.WaitForReady(true))
  251. if err != nil {
  252. return nil, err
  253. }
  254. return cli.finishAsyncCall(ctx, req, &types.Response{Value: &types.Response_ListSnapshots{ListSnapshots: res}})
  255. }
  256. // NOTE: call is synchronous, use ctx to break early if needed
  257. func (cli *grpcClient) OfferSnapshotAsync(ctx context.Context, params types.RequestOfferSnapshot) (*ReqRes, error) {
  258. req := types.ToRequestOfferSnapshot(params)
  259. res, err := cli.client.OfferSnapshot(ctx, req.GetOfferSnapshot(), grpc.WaitForReady(true))
  260. if err != nil {
  261. return nil, err
  262. }
  263. return cli.finishAsyncCall(ctx, req, &types.Response{Value: &types.Response_OfferSnapshot{OfferSnapshot: res}})
  264. }
  265. // NOTE: call is synchronous, use ctx to break early if needed
  266. func (cli *grpcClient) LoadSnapshotChunkAsync(
  267. ctx context.Context,
  268. params types.RequestLoadSnapshotChunk,
  269. ) (*ReqRes, error) {
  270. req := types.ToRequestLoadSnapshotChunk(params)
  271. res, err := cli.client.LoadSnapshotChunk(ctx, req.GetLoadSnapshotChunk(), grpc.WaitForReady(true))
  272. if err != nil {
  273. return nil, err
  274. }
  275. return cli.finishAsyncCall(ctx, req, &types.Response{Value: &types.Response_LoadSnapshotChunk{LoadSnapshotChunk: res}})
  276. }
  277. // NOTE: call is synchronous, use ctx to break early if needed
  278. func (cli *grpcClient) ApplySnapshotChunkAsync(
  279. ctx context.Context,
  280. params types.RequestApplySnapshotChunk,
  281. ) (*ReqRes, error) {
  282. req := types.ToRequestApplySnapshotChunk(params)
  283. res, err := cli.client.ApplySnapshotChunk(ctx, req.GetApplySnapshotChunk(), grpc.WaitForReady(true))
  284. if err != nil {
  285. return nil, err
  286. }
  287. return cli.finishAsyncCall(
  288. ctx,
  289. req,
  290. &types.Response{Value: &types.Response_ApplySnapshotChunk{ApplySnapshotChunk: res}},
  291. )
  292. }
  293. // finishAsyncCall creates a ReqRes for an async call, and immediately populates it
  294. // with the response. We don't complete it until it's been ordered via the channel.
  295. func (cli *grpcClient) finishAsyncCall(ctx context.Context, req *types.Request, res *types.Response) (*ReqRes, error) {
  296. reqres := NewReqRes(req)
  297. reqres.Response = res
  298. select {
  299. case cli.chReqRes <- reqres: // use channel for async responses, since they must be ordered
  300. return reqres, nil
  301. case <-ctx.Done():
  302. return nil, ctx.Err()
  303. }
  304. }
  305. // finishSyncCall waits for an async call to complete. It is necessary to call all
  306. // sync calls asynchronously as well, to maintain call and response ordering via
  307. // the channel, and this method will wait until the async call completes.
  308. func (cli *grpcClient) finishSyncCall(reqres *ReqRes) *types.Response {
  309. // It's possible that the callback is called twice, since the callback can
  310. // be called immediately on SetCallback() in addition to after it has been
  311. // set. This is because completing the ReqRes happens in a separate critical
  312. // section from the one where the callback is called: there is a race where
  313. // SetCallback() is called between completing the ReqRes and dispatching the
  314. // callback.
  315. //
  316. // We also buffer the channel with 1 response, since SetCallback() will be
  317. // called synchronously if the reqres is already completed, in which case
  318. // it will block on sending to the channel since it hasn't gotten around to
  319. // receiving from it yet.
  320. //
  321. // ReqRes should really handle callback dispatch internally, to guarantee
  322. // that it's only called once and avoid the above race conditions.
  323. var once sync.Once
  324. ch := make(chan *types.Response, 1)
  325. reqres.SetCallback(func(res *types.Response) {
  326. once.Do(func() {
  327. ch <- res
  328. })
  329. })
  330. return <-ch
  331. }
  332. //----------------------------------------
  333. func (cli *grpcClient) FlushSync(ctx context.Context) error {
  334. return nil
  335. }
  336. func (cli *grpcClient) EchoSync(ctx context.Context, msg string) (*types.ResponseEcho, error) {
  337. reqres, err := cli.EchoAsync(ctx, msg)
  338. if err != nil {
  339. return nil, err
  340. }
  341. return cli.finishSyncCall(reqres).GetEcho(), cli.Error()
  342. }
  343. func (cli *grpcClient) InfoSync(
  344. ctx context.Context,
  345. req types.RequestInfo,
  346. ) (*types.ResponseInfo, error) {
  347. reqres, err := cli.InfoAsync(ctx, req)
  348. if err != nil {
  349. return nil, err
  350. }
  351. return cli.finishSyncCall(reqres).GetInfo(), cli.Error()
  352. }
  353. func (cli *grpcClient) DeliverTxSync(
  354. ctx context.Context,
  355. params types.RequestDeliverTx,
  356. ) (*types.ResponseDeliverTx, error) {
  357. reqres, err := cli.DeliverTxAsync(ctx, params)
  358. if err != nil {
  359. return nil, err
  360. }
  361. return cli.finishSyncCall(reqres).GetDeliverTx(), cli.Error()
  362. }
  363. func (cli *grpcClient) CheckTxSync(
  364. ctx context.Context,
  365. params types.RequestCheckTx,
  366. ) (*types.ResponseCheckTx, error) {
  367. reqres, err := cli.CheckTxAsync(ctx, params)
  368. if err != nil {
  369. return nil, err
  370. }
  371. return cli.finishSyncCall(reqres).GetCheckTx(), cli.Error()
  372. }
  373. func (cli *grpcClient) QuerySync(
  374. ctx context.Context,
  375. req types.RequestQuery,
  376. ) (*types.ResponseQuery, error) {
  377. reqres, err := cli.QueryAsync(ctx, req)
  378. if err != nil {
  379. return nil, err
  380. }
  381. return cli.finishSyncCall(reqres).GetQuery(), cli.Error()
  382. }
  383. func (cli *grpcClient) CommitSync(ctx context.Context) (*types.ResponseCommit, error) {
  384. reqres, err := cli.CommitAsync(ctx)
  385. if err != nil {
  386. return nil, err
  387. }
  388. return cli.finishSyncCall(reqres).GetCommit(), cli.Error()
  389. }
  390. func (cli *grpcClient) InitChainSync(
  391. ctx context.Context,
  392. params types.RequestInitChain,
  393. ) (*types.ResponseInitChain, error) {
  394. reqres, err := cli.InitChainAsync(ctx, params)
  395. if err != nil {
  396. return nil, err
  397. }
  398. return cli.finishSyncCall(reqres).GetInitChain(), cli.Error()
  399. }
  400. func (cli *grpcClient) BeginBlockSync(
  401. ctx context.Context,
  402. params types.RequestBeginBlock,
  403. ) (*types.ResponseBeginBlock, error) {
  404. reqres, err := cli.BeginBlockAsync(ctx, params)
  405. if err != nil {
  406. return nil, err
  407. }
  408. return cli.finishSyncCall(reqres).GetBeginBlock(), cli.Error()
  409. }
  410. func (cli *grpcClient) EndBlockSync(
  411. ctx context.Context,
  412. params types.RequestEndBlock,
  413. ) (*types.ResponseEndBlock, error) {
  414. reqres, err := cli.EndBlockAsync(ctx, params)
  415. if err != nil {
  416. return nil, err
  417. }
  418. return cli.finishSyncCall(reqres).GetEndBlock(), cli.Error()
  419. }
  420. func (cli *grpcClient) ListSnapshotsSync(
  421. ctx context.Context,
  422. params types.RequestListSnapshots,
  423. ) (*types.ResponseListSnapshots, error) {
  424. reqres, err := cli.ListSnapshotsAsync(ctx, params)
  425. if err != nil {
  426. return nil, err
  427. }
  428. return cli.finishSyncCall(reqres).GetListSnapshots(), cli.Error()
  429. }
  430. func (cli *grpcClient) OfferSnapshotSync(
  431. ctx context.Context,
  432. params types.RequestOfferSnapshot,
  433. ) (*types.ResponseOfferSnapshot, error) {
  434. reqres, err := cli.OfferSnapshotAsync(ctx, params)
  435. if err != nil {
  436. return nil, err
  437. }
  438. return cli.finishSyncCall(reqres).GetOfferSnapshot(), cli.Error()
  439. }
  440. func (cli *grpcClient) LoadSnapshotChunkSync(
  441. ctx context.Context,
  442. params types.RequestLoadSnapshotChunk) (*types.ResponseLoadSnapshotChunk, error) {
  443. reqres, err := cli.LoadSnapshotChunkAsync(ctx, params)
  444. if err != nil {
  445. return nil, err
  446. }
  447. return cli.finishSyncCall(reqres).GetLoadSnapshotChunk(), cli.Error()
  448. }
  449. func (cli *grpcClient) ApplySnapshotChunkSync(
  450. ctx context.Context,
  451. params types.RequestApplySnapshotChunk) (*types.ResponseApplySnapshotChunk, error) {
  452. reqres, err := cli.ApplySnapshotChunkAsync(ctx, params)
  453. if err != nil {
  454. return nil, err
  455. }
  456. return cli.finishSyncCall(reqres).GetApplySnapshotChunk(), cli.Error()
  457. }