18
18
19
19
import com .github .benmanes .caffeine .cache .Cache ;
20
20
import com .github .benmanes .caffeine .cache .Caffeine ;
21
+ import com .linkedin .d2 .balancer .KeyMapper ;
21
22
import com .linkedin .d2 .balancer .util .LoadBalancerUtil ;
22
23
import com .linkedin .data .ByteString ;
23
24
import com .linkedin .data .codec .symbol .EmptySymbolTable ;
27
28
import com .linkedin .data .codec .symbol .SymbolTableProvider ;
28
29
import com .linkedin .data .codec .symbol .SymbolTableSerializer ;
29
30
import com .linkedin .data .schema .DataSchema ;
31
+ import com .linkedin .r2 .message .RequestContext ;
30
32
import com .linkedin .r2 .message .rest .RestRequestBuilder ;
31
33
import com .linkedin .r2 .message .rest .RestResponse ;
32
34
import com .linkedin .r2 .transport .common .Client ;
48
50
import java .util .concurrent .ExecutionException ;
49
51
import java .util .concurrent .Future ;
50
52
import java .util .concurrent .TimeUnit ;
53
+ import javax .annotation .Nullable ;
51
54
import org .slf4j .Logger ;
52
55
import org .slf4j .LoggerFactory ;
53
56
@@ -93,6 +96,7 @@ public class RestLiSymbolTableProvider implements SymbolTableProvider, ResourceD
93
96
private final SymbolTableNameHandler _symbolTableNameHandler ;
94
97
private final Cache <String , SymbolTable > _serviceNameToSymbolTableCache ;
95
98
private final Cache <String , SymbolTable > _symbolTableNameToSymbolTableCache ;
99
+ private final Map <String , URI > _d2ServiceNameToTargetHostMap ;
96
100
private volatile SymbolTable _defaultResponseSymbolTable = null ;
97
101
private volatile String _defaultResponseSymbolTableName = null ;
98
102
@@ -174,6 +178,33 @@ public RestLiSymbolTableProvider(Client client,
174
178
String symbolTablePrefix ,
175
179
String serverNodeUri ,
176
180
List <String > overriddenSymbols )
181
+ {
182
+ this (client , uriPrefix , cacheSize , timeout , symbolTablePrefix , serverNodeUri , overriddenSymbols ,
183
+ Collections .emptyMap ());
184
+ }
185
+
186
+ /**
187
+ * Constructor
188
+ *
189
+ * @param client The {@link Client} to use to make requests to remote services to fetch their symbol tables.
190
+ * @param uriPrefix The URI prefix to use when invoking remote services by name (and not by hostname:port)
191
+ * @param cacheSize The size of the caches used to store symbol tables.
192
+ * @param timeout The client request timeout to fetch remote symbol table.
193
+ * @param symbolTablePrefix The prefix to use for symbol tables vended by this instance.
194
+ * @param serverNodeUri The URI on which the current service is running. This should also include the context
195
+ * and servlet path (if applicable).
196
+ * @param overriddenSymbols The list of overridden symbols to use for the symbol table.
197
+ * @param d2ServiceNameToTargetHostMap A map from d2 service name to target hosts for configuring target host routing
198
+ * when making request symbol table calls.
199
+ */
200
+ public RestLiSymbolTableProvider (Client client ,
201
+ String uriPrefix ,
202
+ int cacheSize ,
203
+ long timeout ,
204
+ String symbolTablePrefix ,
205
+ String serverNodeUri ,
206
+ List <String > overriddenSymbols ,
207
+ Map <String , URI > d2ServiceNameToTargetHostMap )
177
208
{
178
209
_client = client ;
179
210
_uriPrefix = uriPrefix ;
@@ -188,6 +219,7 @@ public RestLiSymbolTableProvider(Client client,
188
219
_defaultResponseSymbolTable = new InMemorySymbolTable (symbolTableName , overriddenSymbols );
189
220
_defaultResponseSymbolTableName = _symbolTableNameHandler .extractMetadata (symbolTableName ).getSymbolTableName ();
190
221
}
222
+ _d2ServiceNameToTargetHostMap = d2ServiceNameToTargetHostMap ;
191
223
}
192
224
193
225
/**
@@ -207,6 +239,30 @@ public RestLiSymbolTableProvider(Client client,
207
239
long timeout ,
208
240
String serverNodeUri ,
209
241
SymbolTable responseSymbolTable )
242
+ {
243
+ this (client , uriPrefix , cacheSize , timeout , serverNodeUri , responseSymbolTable , Collections .emptyMap ());
244
+ }
245
+
246
+ /**
247
+ * Constructor
248
+ *
249
+ * @param client The {@link Client} to use to make requests to remote services to fetch their symbol tables.
250
+ * @param uriPrefix The URI prefix to use when invoking remote services by name (and not by hostname:port)
251
+ * @param cacheSize The size of the caches used to store symbol tables.
252
+ * @param timeout The client request timeout to fetch remote symbol table.
253
+ * @param serverNodeUri The URI on which the current service is running. This should also include the context
254
+ * and servlet path (if applicable).
255
+ * @param responseSymbolTable The pre-generated response symbol table.
256
+ * @param d2ServiceNameToTargetHostMap A map from d2 service name to target hosts for configuring target host routing
257
+ * when making request symbol table calls.
258
+ */
259
+ public RestLiSymbolTableProvider (Client client ,
260
+ String uriPrefix ,
261
+ int cacheSize ,
262
+ long timeout ,
263
+ String serverNodeUri ,
264
+ SymbolTable responseSymbolTable ,
265
+ Map <String , URI > d2ServiceNameToTargetHostMap )
210
266
{
211
267
_client = client ;
212
268
_uriPrefix = uriPrefix ;
@@ -220,6 +276,7 @@ public RestLiSymbolTableProvider(Client client,
220
276
_defaultResponseSymbolTable = responseSymbolTable ;
221
277
_defaultResponseSymbolTableName = responseSymbolTable .getName ();
222
278
}
279
+ _d2ServiceNameToTargetHostMap = d2ServiceNameToTargetHostMap ;
223
280
}
224
281
225
282
@ Override
@@ -253,7 +310,7 @@ public SymbolTable getSymbolTable(String symbolTableName)
253
310
254
311
// Ok, we didn't find it in the cache, let's go query the service the table was served from.
255
312
URI symbolTableUri = new URI (serverNodeUri + "/" + RestLiSymbolTableRequestHandler .SYMBOL_TABLE_URI_PATH + "/" + tableName );
256
- symbolTable = fetchRemoteSymbolTable (symbolTableUri , Collections .emptyMap (), false );
313
+ symbolTable = fetchRemoteSymbolTable (new RequestContext (), symbolTableUri , Collections .emptyMap (), false );
257
314
258
315
if (symbolTable != null )
259
316
{
@@ -297,7 +354,12 @@ public SymbolTable getRequestSymbolTable(URI requestUri)
297
354
// Fetch remote symbol table, configuring the fetch to return an empty table on 404. This will ensure that
298
355
// for services that don't have symbol tables enabled yet, we will not use any symbol tables when encoding.
299
356
//
300
- symbolTable = fetchRemoteSymbolTable (symbolTableUri , Collections .emptyMap (), true );
357
+ RequestContext requestContext = new RequestContext ();
358
+ URI routingHint = _d2ServiceNameToTargetHostMap .get (serviceName );
359
+ if (routingHint != null ) {
360
+ KeyMapper .TargetHostHints .setRequestContextTargetHost (requestContext , routingHint );
361
+ }
362
+ symbolTable = fetchRemoteSymbolTable (requestContext , symbolTableUri , Collections .emptyMap (), true );
301
363
302
364
if (symbolTable != null )
303
365
{
@@ -350,13 +412,13 @@ public void onInitialized(Map<String, ResourceDefinition> resourceDefinitions)
350
412
_symbolTableNameHandler .extractMetadata (_defaultResponseSymbolTable .getName ()).getSymbolTableName ();
351
413
}
352
414
353
- SymbolTable fetchRemoteSymbolTable (URI symbolTableUri , Map <String , String > requestHeaders , boolean returnEmptyOn404 )
415
+ private SymbolTable fetchRemoteSymbolTable (RequestContext requestContext , URI symbolTableUri , Map <String , String > requestHeaders , boolean returnEmptyOn404 )
354
416
{
355
417
try
356
418
{
357
419
Map <String , String > headers = new HashMap <>(requestHeaders );
358
420
headers .put (RestConstants .HEADER_FETCH_SYMBOL_TABLE , Boolean .TRUE .toString ());
359
- Future <RestResponse > future = _client .restRequest (new RestRequestBuilder (symbolTableUri ).setHeaders (headers ).build ());
421
+ Future <RestResponse > future = _client .restRequest (new RestRequestBuilder (symbolTableUri ).setHeaders (headers ).build (), requestContext );
360
422
RestResponse restResponse = future .get (_timeout , TimeUnit .MILLISECONDS );
361
423
int status = restResponse .getStatus ();
362
424
0 commit comments