Skip to content

Commit

Permalink
feat: implement retries on grpc and rest query calls
Browse files Browse the repository at this point in the history
  • Loading branch information
ThomasRalee committed May 16, 2023
1 parent ef8518c commit d8c4486
Show file tree
Hide file tree
Showing 37 changed files with 946 additions and 467 deletions.
2 changes: 1 addition & 1 deletion jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ const directoryPaths = Object.keys(compilerOptions.paths).reduce(
// https://jestjs.io/docs/en/configuration.html

module.exports = {
testTimeout: 15000,
testTimeout: 30000,
// All imported modules in your tests should be mocked automatically
// automock: false,

Expand Down
64 changes: 29 additions & 35 deletions packages/sdk-ts/src/client/BaseGrpcConsumer.ts
Original file line number Diff line number Diff line change
@@ -1,51 +1,45 @@
import { grpc } from '@injectivelabs/grpc-web'
import { GrpcUnaryRequestException } from '@injectivelabs/exceptions'
import { isBrowser } from '../utils/helpers'
import { getGrpcTransport } from '../utils/grpc'
import { InjectiveAccountRpc } from '@injectivelabs/indexer-proto-ts'

if (!isBrowser()) {
grpc.setDefaultTransport(getGrpcTransport() as grpc.TransportFactory)
}
/**
* @hidden
*/
export default class BaseGrpcConsumer {
protected module: string = ''

protected endpoint: string
export default class BaseGrpcConsumer extends InjectiveAccountRpc.GrpcWebImpl {
protected module: string = ''

constructor(endpoint: string) {
this.endpoint = endpoint
super(endpoint, { transport: getGrpcTransport() })
}

public getGrpcWebImpl(endpoint: string) {
return new BaseGrpcConsumer(endpoint)
}

protected request<
TRequest extends grpc.ProtobufMessage,
TResponse extends grpc.ProtobufMessage,
S extends grpc.UnaryMethodDefinition<TRequest, TResponse>,
>(request: TRequest, service: S): Promise<TResponse> {
return new Promise((resolve, reject) => {
grpc.unary(service, {
request,
host: this.endpoint,
onEnd: (res) => {
const { statusMessage, status, message } = res
protected retry<TResponse>(
grpcCall: Function,
retries: number = 3,
delay: number = 1000,
): Promise<TResponse> {
const retryGrpcCall = async (attempt = 1): Promise<any> => {
try {
return await grpcCall()
} catch (e: any) {
if (attempt >= retries) {
throw e
}

if (status === grpc.Code.OK && message) {
return resolve(message as TResponse)
}
return new Promise((resolve) =>
setTimeout(
() => resolve(retryGrpcCall(attempt + 1)),
delay * attempt,
),
)
}
}

return reject(
new GrpcUnaryRequestException(
new Error(statusMessage || 'The request failed.'),
{
code: status,
context: `${this.endpoint}?service=${service.methodName}`,
contextModule: this.module,
},
),
)
},
})
})
return retryGrpcCall()
}
}
22 changes: 0 additions & 22 deletions packages/sdk-ts/src/client/BaseGrpcDmmWebConsumer.ts

This file was deleted.

25 changes: 24 additions & 1 deletion packages/sdk-ts/src/client/BaseRestConsumer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,28 @@ import { HttpRestClient } from '@injectivelabs/utils'
* @hidden
*/
export default class BaseRestConsumer extends HttpRestClient {
//
protected retry<TResponse>(
httpCall: Function,
retries: number = 3,
delay: number = 1000,
): Promise<TResponse> {
const retryHttpCall = async (attempt = 1): Promise<any> => {
try {
return (await httpCall()) as TResponse
} catch (e: any) {
if (attempt >= retries) {
throw e
}

return new Promise((resolve) =>
setTimeout(
() => resolve(retryHttpCall(attempt + 1)),
delay * attempt,
),
)
}
}

return retryHttpCall()
}
}
27 changes: 19 additions & 8 deletions packages/sdk-ts/src/client/chain/grpc/ChainGrpcAuctionApi.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,25 @@
import { InjectiveAuctionV1Beta1Query } from '@injectivelabs/core-proto-ts'
import {
GrpcUnaryRequestException,
UnspecifiedErrorCode,
} from '@injectivelabs/exceptions'
import { getGrpcWebImpl } from '../../BaseGrpcWebConsumer'
import { ChainGrpcAuctionTransformer } from '../transformers'
import { InjectiveAuctionV1Beta1Query } from '@injectivelabs/core-proto-ts'
import BaseGrpcConsumer from '../../BaseGrpcConsumer'
import { ChainModule } from '../types'
import { ChainGrpcAuctionTransformer } from '../transformers'

/**
* @category Chain Grpc API
*/
export class ChainGrpcAuctionApi {
export class ChainGrpcAuctionApi extends BaseGrpcConsumer {
protected module: string = ChainModule.Auction

protected client: InjectiveAuctionV1Beta1Query.QueryClientImpl

constructor(endpoint: string) {
super(endpoint)

this.client = new InjectiveAuctionV1Beta1Query.QueryClientImpl(
getGrpcWebImpl(endpoint),
this.getGrpcWebImpl(endpoint),
)
}

Expand All @@ -26,7 +28,10 @@ export class ChainGrpcAuctionApi {
InjectiveAuctionV1Beta1Query.QueryAuctionParamsRequest.create()

try {
const response = await this.client.AuctionParams(request)
const response =
await this.retry<InjectiveAuctionV1Beta1Query.QueryAuctionParamsResponse>(
() => this.client.AuctionParams(request),
)

return ChainGrpcAuctionTransformer.moduleParamsResponseToModuleParams(
response,
Expand All @@ -53,7 +58,10 @@ export class ChainGrpcAuctionApi {
InjectiveAuctionV1Beta1Query.QueryModuleStateRequest.create()

try {
const response = await this.client.AuctionModuleState(request)
const response =
await this.retry<InjectiveAuctionV1Beta1Query.QueryModuleStateResponse>(
() => this.client.AuctionModuleState(request),
)

return ChainGrpcAuctionTransformer.auctionModuleStateResponseToAuctionModuleState(
response,
Expand All @@ -80,7 +88,10 @@ export class ChainGrpcAuctionApi {
InjectiveAuctionV1Beta1Query.QueryCurrentAuctionBasketRequest.create()

try {
const response = await this.client.CurrentAuctionBasket(request)
const response =
await this.retry<InjectiveAuctionV1Beta1Query.QueryCurrentAuctionBasketResponse>(
() => this.client.CurrentAuctionBasket(request),
)

return ChainGrpcAuctionTransformer.currentBasketResponseToCurrentBasket(
response,
Expand Down
33 changes: 22 additions & 11 deletions packages/sdk-ts/src/client/chain/grpc/ChainGrpcAuthApi.ts
Original file line number Diff line number Diff line change
@@ -1,33 +1,38 @@
import { CosmosAuthV1Beta1Query } from '@injectivelabs/core-proto-ts'
import { PaginationOption } from '../../../types/pagination'
import { paginationRequestFromPagination } from '../../../utils/pagination'
import { ChainGrpcAuthTransformer } from '../transformers/ChainGrpcAuthTransformer'
import { ChainModule } from '../types'
import {
GrpcUnaryRequestException,
UnspecifiedErrorCode,
} from '@injectivelabs/exceptions'
import { getGrpcWebImpl } from '../../BaseGrpcWebConsumer'
import { CosmosAuthV1Beta1Query } from '@injectivelabs/core-proto-ts'
import BaseGrpcConsumer from '../../BaseGrpcConsumer'
import { ChainModule } from '../types'
import { PaginationOption } from '../../../types/pagination'
import { paginationRequestFromPagination } from '../../../utils/pagination'
import { ChainGrpcAuthTransformer } from '../transformers/ChainGrpcAuthTransformer'

/**
* @category Chain Grpc API
*/
export class ChainGrpcAuthApi {
export class ChainGrpcAuthApi extends BaseGrpcConsumer {
protected module: string = ChainModule.Auth

protected client: CosmosAuthV1Beta1Query.QueryClientImpl

constructor(endpoint: string) {
super(endpoint)

this.client = new CosmosAuthV1Beta1Query.QueryClientImpl(
getGrpcWebImpl(endpoint),
this.getGrpcWebImpl(endpoint),
)
}

async fetchModuleParams() {
const request = CosmosAuthV1Beta1Query.QueryParamsRequest.create()

try {
const response = await this.client.Params(request)
const response =
await this.retry<CosmosAuthV1Beta1Query.QueryParamsResponse>(() =>
this.client.Params(request),
)

return ChainGrpcAuthTransformer.moduleParamsResponseToModuleParams(
response,
Expand Down Expand Up @@ -55,7 +60,10 @@ export class ChainGrpcAuthApi {
request.address = address

try {
const response = await this.client.Account(request)
const response =
await this.retry<CosmosAuthV1Beta1Query.QueryAccountResponse>(() =>
this.client.Account(request),
)

return ChainGrpcAuthTransformer.accountResponseToAccount(response)
} catch (e: unknown) {
Expand Down Expand Up @@ -84,7 +92,10 @@ export class ChainGrpcAuthApi {
}

try {
const response = await this.client.Accounts(request)
const response =
await this.retry<CosmosAuthV1Beta1Query.QueryAccountsResponse>(() =>
this.client.Accounts(request),
)

return ChainGrpcAuthTransformer.accountsResponseToAccounts(response)
} catch (e: unknown) {
Expand Down
36 changes: 25 additions & 11 deletions packages/sdk-ts/src/client/chain/grpc/ChainGrpcBankApi.ts
Original file line number Diff line number Diff line change
@@ -1,33 +1,38 @@
import { getGrpcWebImpl } from '../../BaseGrpcWebConsumer'
import { PaginationOption } from '../../../types/pagination'
import { paginationRequestFromPagination } from '../../../utils/pagination'
import { ChainGrpcBankTransformer } from '../transformers'
import {
GrpcUnaryRequestException,
UnspecifiedErrorCode,
} from '@injectivelabs/exceptions'
import { ChainModule } from '../types'
import { CosmosBankV1Beta1Query } from '@injectivelabs/core-proto-ts'
import BaseGrpcConsumer from '../../BaseGrpcConsumer'
import { ChainModule } from '../types'
import { ChainGrpcBankTransformer } from '../transformers'
import { PaginationOption } from '../../../types/pagination'
import { paginationRequestFromPagination } from '../../../utils/pagination'

/**
* @category Chain Grpc API
*/
export class ChainGrpcBankApi {
export class ChainGrpcBankApi extends BaseGrpcConsumer {
protected module: string = ChainModule.Bank

protected client: CosmosBankV1Beta1Query.QueryClientImpl

constructor(endpoint: string) {
super(endpoint)

this.client = new CosmosBankV1Beta1Query.QueryClientImpl(
getGrpcWebImpl(endpoint),
this.getGrpcWebImpl(endpoint),
)
}

async fetchModuleParams() {
const request = CosmosBankV1Beta1Query.QueryParamsRequest.create()

try {
const response = await this.client.Params(request)
const response =
await this.retry<CosmosBankV1Beta1Query.QueryParamsResponse>(() =>
this.client.Params(request),
)

return ChainGrpcBankTransformer.moduleParamsResponseToModuleParams(
response,
Expand Down Expand Up @@ -62,7 +67,10 @@ export class ChainGrpcBankApi {
request.denom = denom

try {
const response = await this.client.Balance(request)
const response =
await this.retry<CosmosBankV1Beta1Query.QueryBalanceResponse>(() =>
this.client.Balance(request),
)

return ChainGrpcBankTransformer.balanceResponseToBalance(response)
} catch (e: unknown) {
Expand All @@ -88,7 +96,10 @@ export class ChainGrpcBankApi {
request.address = address

try {
const response = await this.client.AllBalances(request)
const response =
await this.retry<CosmosBankV1Beta1Query.QueryAllBalancesResponse>(() =>
this.client.AllBalances(request),
)

return ChainGrpcBankTransformer.balancesResponseToBalances(response)
} catch (e: unknown) {
Expand Down Expand Up @@ -117,7 +128,10 @@ export class ChainGrpcBankApi {
}

try {
const response = await this.client.TotalSupply(request)
const response =
await this.retry<CosmosBankV1Beta1Query.QueryTotalSupplyResponse>(() =>
this.client.TotalSupply(request),
)

return ChainGrpcBankTransformer.totalSupplyResponseToTotalSupply(response)
} catch (e: unknown) {
Expand Down
Loading

0 comments on commit d8c4486

Please sign in to comment.