I'm have implemented node grpc client retry using interceptor but it is only retrying once and not upto maxRetries which is specified. Also, the error is not propagating to the caller. Can you please where i'm missing in fixing this?
function createRetryInterceptor(maxRetries = 3, backoffInterval) { return function (options, nextCall) { let retries = 0; return new grpc.InterceptingCall(nextCall(options), { start: function (metadata, listener, next) { function retryOrNext(status) { if (status.code === grpc.status.UNAVAILABLE && retries < maxRetries) { retries++; console.log(`Retry ${retries} after ${backoffInterval}ms`); console.error('Error message:', status.details); // Create a new call with the same options const call = nextCall(options); call.start(metadata, listener, retryOrNext); // Add a timeout for retry setTimeout(() => { call.cancel(); // Cancel the retry call if it takes too long }, backoffInterval); } else { // Propagate errors from interceptor as well if (status.code !== grpc.status.OK) { next(status); //return; // Exit the retry loop if not OK or UNAVAILABLE } // Proceed with successful call or other non-retriable errors next(status); } } // Wrap the listener to handle potential errors in onReceiveStatus const wrappedListener = { onReceiveStatus: function (status, next) { try { retryOrNext(status); } catch (error) { console.error('Error in onReceiveStatus:', error); next(status); } }, // Forward other listener methods if present ...listener, }; next(metadata, wrappedListener); } }); };}
static promiseBuilderFn(resolve, reject) { return (err, response) => { if (err != null) { console.log(`error in calling promise err: ${err}`); reject(err); } else { console.log(`success: ${response}`); resolve(response); } }; }
The grpc client i have created is like below
const client = new MyClient('localhost:5001', grpc.credentials.createInsecure(), {interceptors: [createRetryInterceptor(3, 5000)]});
and i'm calling the grpc service method as follows
return new Promise((resolve, reject) => { client.getData( request, metadata, promiseBuilderFn(resolve, reject) ); })
I tried implementing the interceptor as mentioned in https://github.com/grpc/proposal/blob/master/L5-node-client-interceptors.md#examples but it is giving error as TypeError: nextCall is not a function