@@ -21,7 +21,11 @@ import {
21
21
LoadBalancingConfig ,
22
22
getFirstUsableConfig ,
23
23
} from './load-balancer' ;
24
- import { ServiceConfig , validateServiceConfig } from './service-config' ;
24
+ import {
25
+ MethodConfig ,
26
+ ServiceConfig ,
27
+ validateServiceConfig ,
28
+ } from './service-config' ;
25
29
import { ConnectivityState } from './connectivity-state' ;
26
30
import { ConfigSelector , createResolver , Resolver } from './resolver' ;
27
31
import { ServiceError } from './call' ;
@@ -43,6 +47,59 @@ function trace(text: string): void {
43
47
logging . trace ( LogVerbosity . DEBUG , TRACER_NAME , text ) ;
44
48
}
45
49
50
+ type NameMatchLevel = 'EMPTY' | 'SERVICE' | 'SERVICE_AND_METHOD' ;
51
+
52
+ /**
53
+ * Name match levels in order from most to least specific. This is the order in
54
+ * which searches will be performed.
55
+ */
56
+ const NAME_MATCH_LEVEL_ORDER : NameMatchLevel [ ] = [
57
+ 'SERVICE_AND_METHOD' ,
58
+ 'SERVICE' ,
59
+ 'EMPTY' ,
60
+ ] ;
61
+
62
+ function hasMatchingName (
63
+ service : string ,
64
+ method : string ,
65
+ methodConfig : MethodConfig ,
66
+ matchLevel : NameMatchLevel
67
+ ) : boolean {
68
+ for ( const name of methodConfig . name ) {
69
+ switch ( matchLevel ) {
70
+ case 'EMPTY' :
71
+ if ( ! name . service && ! name . method ) {
72
+ return true ;
73
+ }
74
+ break ;
75
+ case 'SERVICE' :
76
+ if ( name . service === service && ! name . method ) {
77
+ return true ;
78
+ }
79
+ break ;
80
+ case 'SERVICE_AND_METHOD' :
81
+ if ( name . service === service && name . method === method ) {
82
+ return true ;
83
+ }
84
+ }
85
+ }
86
+ return false ;
87
+ }
88
+
89
+ function findMatchingConfig (
90
+ service : string ,
91
+ method : string ,
92
+ methodConfigs : MethodConfig [ ] ,
93
+ matchLevel : NameMatchLevel
94
+ ) : MethodConfig | null {
95
+ for ( const config of methodConfigs ) {
96
+ if ( hasMatchingName ( service , method , config , matchLevel ) ) {
97
+ return config ;
98
+ }
99
+ }
100
+ return null ;
101
+ }
102
+
46
103
function getDefaultConfigSelector (
47
104
serviceConfig : ServiceConfig | null
48
105
) : ConfigSelector {
@@ -54,19 +111,26 @@ function getDefaultConfigSelector(
54
111
const service = splitName [ 0 ] ?? '' ;
55
112
const method = splitName [ 1 ] ?? '' ;
56
113
if ( serviceConfig && serviceConfig . methodConfig ) {
57
- for ( const methodConfig of serviceConfig . methodConfig ) {
58
- for ( const name of methodConfig . name ) {
59
- if (
60
- name . service === service &&
61
- ( name . method === undefined || name . method === method )
62
- ) {
63
- return {
64
- methodConfig : methodConfig ,
65
- pickInformation : { } ,
66
- status : Status . OK ,
67
- dynamicFilterFactories : [ ] ,
68
- } ;
69
- }
114
+ /* Check for the following in order, and return the first method
115
+ * config that matches:
116
+ * 1. A name that exactly matches the service and method
117
+ * 2. A name with no method set that matches the service
118
+ * 3. An empty name
119
+ */
120
+ for ( const matchLevel of NAME_MATCH_LEVEL_ORDER ) {
121
+ const matchingConfig = findMatchingConfig (
122
+ service ,
123
+ method ,
124
+ serviceConfig . methodConfig ,
125
+ matchLevel
126
+ ) ;
127
+ if ( matchingConfig ) {
128
+ return {
129
+ methodConfig : matchingConfig ,
130
+ pickInformation : { } ,
131
+ status : Status . OK ,
132
+ dynamicFilterFactories : [ ] ,
133
+ } ;
70
134
}
71
135
}
72
136
}
0 commit comments