@@ -20,20 +20,20 @@ import type {
2020 ServerReflectionResponse ,
2121} from './reflection_providers/v1alpha/reflection_pb' ;
2222
23- const supportedReflectionProtocols = [
24- {
25- protocol : 'v1alpha' ,
23+ const supportedReflectionProtocols = {
24+ v1alpha : {
25+ priority : 0 ,
2626 serviceName : 'grpc.reflection.v1alpha.ServerReflection' ,
2727 client : import ( './reflection_providers/v1alpha/reflection_pb' ) ,
2828 service : import ( './reflection_providers/v1alpha/reflection_grpc_pb' ) ,
2929 } ,
30- {
31- protocol : 'v1' ,
30+ v1 : {
31+ priority : 1 ,
3232 serviceName : 'grpc.reflection.v1.ServerReflection' ,
3333 client : import ( './reflection_providers/v1/reflection_pb' ) ,
3434 service : import ( './reflection_providers/v1/reflection_grpc_pb' ) ,
3535 } ,
36- ] ;
36+ } ;
3737
3838export class Client {
3939 metadata : Metadata ;
@@ -95,60 +95,100 @@ export class Client {
9595 } ) ;
9696 }
9797
98- private async initializeReflectionClient ( ) {
99- if ( this . grpcClient || this . compatibleProtocol ) {
100- return ;
101- }
98+ private async evaluateServerReflectionProtocol ( ) {
99+ const evaluationPromises = [ ] ;
102100
103101 // Check protocol compatibility and initialize gRPC client based on that
104- for ( const protocolConfig of supportedReflectionProtocols ) {
105- const {
106- protocol,
107- service : servicePromise ,
108- client : clientPromise ,
109- } = protocolConfig ;
110-
111- const [ protocolService , protocolClient ] = await Promise . all ( [
112- servicePromise ,
113- clientPromise ,
114- ] ) ;
115-
116- const grpcClientForProtocol = new protocolService . ServerReflectionClient (
117- this . url ,
118- this . credentials ,
119- this . clientOptions
102+ for ( const protocol of Object . keys ( supportedReflectionProtocols ) ) {
103+ type PromiseReturnType = {
104+ successful : boolean ;
105+ priority : number ;
106+ effect ?: ( ) => void ;
107+ error ?: ServiceError ;
108+ } ;
109+
110+ evaluationPromises . push (
111+ // eslint-disable-next-line no-async-promise-executor
112+ new Promise < PromiseReturnType > ( async resolve => {
113+ const protocolConfig =
114+ supportedReflectionProtocols [
115+ protocol as keyof typeof supportedReflectionProtocols
116+ ] ;
117+ const {
118+ service : servicePromise ,
119+ client : clientPromise ,
120+ } = protocolConfig ;
121+
122+ const [ protocolService , protocolClient ] = await Promise . all ( [
123+ servicePromise ,
124+ clientPromise ,
125+ ] ) ;
126+
127+ const grpcClientForProtocol = new protocolService . ServerReflectionClient (
128+ this . url ,
129+ this . credentials ,
130+ this . clientOptions
131+ ) ;
132+
133+ const request = new protocolClient . ServerReflectionRequest ( ) ;
134+
135+ request . setListServices ( '*' ) ;
136+
137+ try {
138+ const [ reflectionResponse ] = await this . sendReflectionRequest (
139+ request ,
140+ grpcClientForProtocol
141+ ) ;
142+
143+ return resolve ( {
144+ successful : true ,
145+ priority : protocolConfig . priority ,
146+ effect : ( ) => {
147+ this . grpcClient = grpcClientForProtocol ;
148+ this . compatibleProtocol = protocol ;
149+ this . CompatibleServerReflectionRequest =
150+ protocolClient . ServerReflectionRequest ;
151+ this . reflectionResponseCache = reflectionResponse ;
152+ } ,
153+ } ) ;
154+ } catch ( error ) {
155+ return resolve ( {
156+ successful : false ,
157+ priority : protocolConfig . priority ,
158+ error : error as ServiceError ,
159+ } ) ;
160+ }
161+ } )
120162 ) ;
163+ }
121164
122- const request = new protocolClient . ServerReflectionRequest ( ) ;
165+ const evaluationResults = await Promise . all ( evaluationPromises ) ;
123166
124- request . setListServices ( '*' ) ;
167+ const [ successfulReflectionByPriority ] = evaluationResults
168+ . filter ( res => res . successful )
169+ . sort ( ( res1 , res2 ) => res2 . priority - res1 . priority ) ;
125170
126- try {
127- const [ reflectionResponse ] = await this . sendReflectionRequest (
128- request ,
129- grpcClientForProtocol
130- ) ;
171+ if ( ! successfulReflectionByPriority ) {
172+ const noCompatibleProtocolRrror = new Error (
173+ 'No compatible reflection protocol found.'
174+ ) ;
131175
132- this . grpcClient = grpcClientForProtocol ;
133- this . compatibleProtocol = protocol ;
134- this . CompatibleServerReflectionRequest =
135- protocolClient . ServerReflectionRequest ;
136- this . reflectionResponseCache = reflectionResponse ;
137-
138- break ; // Exit loop on first successful protocol
139- } catch ( error ) {
140- if ( ( error as ServiceError ) . code !== GrpcStatus . UNIMPLEMENTED ) {
141- // Something is wrong with the gRPC server itself
142- throw error ;
143- }
176+ const resultWithServiceError = evaluationResults . find ( res => {
177+ // Something is actually wrong with the gRPC service
178+ return res . error && res . error . code !== GrpcStatus . UNIMPLEMENTED ;
179+ } ) ;
144180
145- continue ; // Try next protocol
146- }
181+ throw resultWithServiceError ?. error || noCompatibleProtocolRrror ;
147182 }
148183
149- if ( ! this . grpcClient ) {
150- throw new Error ( 'No compatible reflection protocol found.' ) ;
151- }
184+ // Set grpc client and other properties based on highest priority successful protocol
185+ successfulReflectionByPriority . effect ! ( ) ;
186+ }
187+
188+ private async initializeReflectionClient ( ) {
189+ if ( this . grpcClient || this . compatibleProtocol ) return ;
190+
191+ await this . evaluateServerReflectionProtocol ( ) ;
152192 }
153193
154194 async listServices ( ) : Promise < string [ ] > {
0 commit comments