[rpc-client] add retrying

This commit is contained in:
41666 2019-04-14 12:51:56 -05:00
parent c3b510f0bb
commit 10d5979ce1
No known key found for this signature in database
GPG key ID: BC51D07640DC10AF

View file

@ -1,6 +1,7 @@
// @flow
import superagent from 'superagent'
import RPCError from './error'
import retry from 'async-retry'
export type RPCResponse = {
response?: mixed,
@ -37,7 +38,9 @@ export default class RPCClient {
args: number
}> = []
constructor ({ forceDev, baseUrl = '/api/_rpc' }: { forceDev?: boolean, baseUrl?: string } = {}) {
retry: boolean
constructor ({ forceDev, baseUrl = '/api/_rpc', retry = false }: { forceDev?: boolean, baseUrl?: string, retry?: boolean } = {}) {
this.baseUrl = (process.env.APP_URL || '') + baseUrl
if (forceDev != null) {
@ -46,6 +49,8 @@ export default class RPCClient {
this.dev = process.env.NODE_ENV === 'development'
}
this.retry = retry
this.rpc = new Proxy({}, {
get: this.__rpcCall,
has: this.__checkCall,
@ -59,7 +64,7 @@ export default class RPCClient {
}
withCookies = (h: string) => {
this.headerMixins['Set-Cookie'] = h
this.cookieHeader = h
return this.rpc
}
@ -92,10 +97,35 @@ export default class RPCClient {
}
}
async call (fn: string, ...args: any[]): mixed {
call (fn: string, ...args: any[]): mixed {
// console.debug('rpc call:', { fn, args })
if (this.retry) {
return this.callWithRetry(fn, ...args)
} else {
return this.callAsNormal(fn, ...args)
}
}
async callWithRetry (fn: string, ...args: any[]): mixed {
return retry<mixed>(async (bail) => {
try {
return await this.callAsNormal(fn, ...args)
} catch (e) {
if (e instanceof RPCError) {
bail(e)
}
}
})
}
async callAsNormal (fn: string, ...args: any[]): mixed {
const req: RPCRequest = { fn, args }
const rq = superagent.post(this.baseUrl).set({ ...this.headerMixins })
if (this.cookieHeader != null && this.cookieHeader !== '') {
rq.cookies = this.cookieHeader
}
const rsp = await rq.send(req).ok(() => true)
const body: RPCResponse = rsp.body
@ -121,6 +151,7 @@ export default class RPCClient {
}
// PROXY HANDLERS
// __rpcCall = (_: {}, fn: string) => this.call.bind(this, fn)
__rpcCall = (_: {}, fn: string) => this.call.bind(this, fn)
__checkCall = (_: {}, fn: string) => this.dev ? this.__listCalls(_).includes(fn) : true
__listCalls = (_: {}): string[] => this.__rpcAvailable.map(x => x.name)