private void onFindPrimaryShardSuccess( PrimaryShardInfo primaryShardInfo, TransactionProxy parent, String shardName, TransactionContextWrapper transactionContextWrapper) { if (LOG.isDebugEnabled()) { LOG.debug( "Tx {}: Found primary {} for shard {}", parent.getIdentifier(), primaryShardInfo.getPrimaryShardActor(), shardName); } updateShardInfo(shardName, primaryShardInfo); try { TransactionContext localContext = maybeCreateLocalTransactionContext(parent, shardName); if (localContext != null) { transactionContextWrapper.executePriorTransactionOperations(localContext); } else { RemoteTransactionContextSupport remote = new RemoteTransactionContextSupport(transactionContextWrapper, parent, shardName); remote.setPrimaryShard( primaryShardInfo.getPrimaryShardActor(), primaryShardInfo.getPrimaryShardVersion()); } } finally { onTransactionContextCreated(parent.getIdentifier()); } }
@Test public void testFindPrimaryShardAsyncRemotePrimaryFound() throws Exception { TestActorRef<MessageCollectorActor> shardManager = TestActorRef.create(getSystem(), Props.create(MessageCollectorActor.class)); DatastoreContext dataStoreContext = DatastoreContext.newBuilder() .dataStoreType("config") .shardLeaderElectionTimeout(100, TimeUnit.MILLISECONDS) .build(); final String expPrimaryPath = "akka://test-system/find-primary-shard"; final short expPrimaryVersion = DataStoreVersions.CURRENT_VERSION; ActorContext actorContext = new ActorContext( getSystem(), shardManager, mock(ClusterWrapper.class), mock(Configuration.class), dataStoreContext, new PrimaryShardInfoFutureCache()) { @Override protected Future<Object> doAsk(ActorRef actorRef, Object message, Timeout timeout) { return Futures.successful( (Object) new RemotePrimaryShardFound(expPrimaryPath, expPrimaryVersion)); } }; Future<PrimaryShardInfo> foobar = actorContext.findPrimaryShardAsync("foobar"); PrimaryShardInfo actual = Await.result(foobar, Duration.apply(5000, TimeUnit.MILLISECONDS)); assertNotNull(actual); assertEquals("LocalShardDataTree present", false, actual.getLocalShardDataTree().isPresent()); assertTrue( "Unexpected PrimaryShardActor path " + actual.getPrimaryShardActor().path(), expPrimaryPath.endsWith(actual.getPrimaryShardActor().pathString())); assertEquals("getPrimaryShardVersion", expPrimaryVersion, actual.getPrimaryShardVersion()); Future<PrimaryShardInfo> cached = actorContext.getPrimaryShardInfoCache().getIfPresent("foobar"); PrimaryShardInfo cachedInfo = Await.result(cached, FiniteDuration.apply(1, TimeUnit.MILLISECONDS)); assertEquals(cachedInfo, actual); actorContext.getPrimaryShardInfoCache().remove("foobar"); cached = actorContext.getPrimaryShardInfoCache().getIfPresent("foobar"); assertNull(cached); }
private void updateShardInfo(final String shardName, final PrimaryShardInfo primaryShardInfo) { final Optional<DataTree> maybeDataTree = primaryShardInfo.getLocalShardDataTree(); if (maybeDataTree.isPresent()) { if (!knownLocal.containsKey(shardName)) { LOG.debug("Shard {} resolved to local data tree - adding local factory", shardName); F factory = factoryForShard( shardName, primaryShardInfo.getPrimaryShardActor(), maybeDataTree.get()); knownLocal.putIfAbsent(shardName, factory); } } else if (knownLocal.containsKey(shardName)) { LOG.debug("Shard {} invalidating local data tree", shardName); knownLocal.remove(shardName); } }