2222import com .google .spanner .v1 .CommitRequest ;
2323import com .google .spanner .v1 .DirectedReadOptions ;
2424import com .google .spanner .v1 .ExecuteSqlRequest ;
25+ import com .google .spanner .v1 .Group ;
2526import com .google .spanner .v1 .Mutation ;
2627import com .google .spanner .v1 .ReadRequest ;
2728import com .google .spanner .v1 .RoutingHint ;
29+ import com .google .spanner .v1 .Tablet ;
2830import com .google .spanner .v1 .TransactionOptions ;
2931import com .google .spanner .v1 .TransactionSelector ;
3032import java .util .ArrayList ;
33+ import java .util .HashSet ;
3134import java .util .List ;
3235import java .util .Objects ;
36+ import java .util .Set ;
3337import java .util .concurrent .ThreadLocalRandom ;
3438import java .util .concurrent .atomic .AtomicLong ;
3539import java .util .function .Predicate ;
40+ import javax .annotation .Nullable ;
3641
3742/**
3843 * Finds a server for a request using location-aware routing metadata.
@@ -47,9 +52,25 @@ public final class ChannelFinder {
4752 private final AtomicLong databaseId = new AtomicLong ();
4853 private final KeyRecipeCache recipeCache = new KeyRecipeCache ();
4954 private final KeyRangeCache rangeCache ;
55+ @ Nullable private final EndpointLifecycleManager lifecycleManager ;
56+ @ Nullable private final String finderKey ;
5057
5158 public ChannelFinder (ChannelEndpointCache endpointCache ) {
52- this .rangeCache = new KeyRangeCache (Objects .requireNonNull (endpointCache ));
59+ this (endpointCache , null , null );
60+ }
61+
62+ public ChannelFinder (
63+ ChannelEndpointCache endpointCache , @ Nullable EndpointLifecycleManager lifecycleManager ) {
64+ this (endpointCache , lifecycleManager , null );
65+ }
66+
67+ ChannelFinder (
68+ ChannelEndpointCache endpointCache ,
69+ @ Nullable EndpointLifecycleManager lifecycleManager ,
70+ @ Nullable String finderKey ) {
71+ this .rangeCache = new KeyRangeCache (Objects .requireNonNull (endpointCache ), lifecycleManager );
72+ this .lifecycleManager = lifecycleManager ;
73+ this .finderKey = finderKey ;
5374 }
5475
5576 void useDeterministicRandom () {
@@ -70,6 +91,24 @@ public void update(CacheUpdate update) {
7091 recipeCache .addRecipes (update .getKeyRecipes ());
7192 }
7293 rangeCache .addRanges (update );
94+
95+ // Notify the lifecycle manager about server addresses so it can create endpoints
96+ // in the background and start probing, and evict stale endpoints atomically.
97+ if (lifecycleManager != null && finderKey != null ) {
98+ Set <String > currentAddresses = new HashSet <>();
99+ for (Group group : update .getGroupList ()) {
100+ for (Tablet tablet : group .getTabletsList ()) {
101+ String addr = tablet .getServerAddress ();
102+ if (!addr .isEmpty ()) {
103+ currentAddresses .add (addr );
104+ }
105+ }
106+ }
107+ // Also include addresses from existing cached tablets not in this update.
108+ currentAddresses .addAll (rangeCache .getActiveAddresses ());
109+ // Atomically ensure endpoints exist and evict stale ones.
110+ lifecycleManager .updateActiveAddresses (finderKey , currentAddresses );
111+ }
73112 }
74113 }
75114
0 commit comments