use of org.infinispan.test.op.TestWriteOperation in project infinispan by infinispan.
the class CacheEntryCloudEventsTest method assertEntryEventSent.
private void assertEntryEventSent(Object key, Object value, TestWriteOperation op) {
byte[] expectedKeyBytes = getKeyBytes(key);
byte[] expectedValueBytes = getValueBytes(value);
String type = translateType(op);
Optional<ProducerRecord<byte[], byte[]>> record = mockSender.getProducer().history().stream().filter(r -> Arrays.equals(r.key(), expectedKeyBytes)).findFirst();
assertTrue(record.isPresent());
byte[] eventBytes = record.get().value();
Json json = Json.read(new String(eventBytes));
assertEquals("1.0", json.at(SPECVERSION).asString());
assertEquals(type, json.at(TYPE).asString());
String source = json.at(SOURCE).asString();
assertTrue(source.startsWith("/infinispan"));
assertTrue(source.endsWith("/" + CACHE_NAME));
Instant.parse(json.at(TIME).asString());
boolean keyIsBase64 = json.at(INFINISPAN_SUBJECT_ISBASE64, false).asBoolean();
assertEquals(expectedContentType(keyIsBase64).toString(), json.at(INFINISPAN_SUBJECT_CONTENTTYPE, APPLICATION_JSON_TYPE).asString());
String subject = json.at(SUBJECT).asString();
byte[] keyBytes = keyIsBase64 ? Base64.getDecoder().decode(subject) : subject.getBytes(StandardCharsets.UTF_8);
assertEquals(expectedKeyBytes, keyBytes);
String data = json.at(DATA).asString();
boolean valueIsBase64 = json.at(INFINISPAN_DATA_ISBASE64, false).asBoolean();
assertEquals(expectedContentType(valueIsBase64).toString(), json.at(DATACONTENTTYPE, APPLICATION_JSON_TYPE).asString());
byte[] valueBytes = valueIsBase64 ? Base64.getDecoder().decode(data) : data.getBytes(StandardCharsets.UTF_8);
assertEquals(expectedValueBytes, valueBytes);
}
use of org.infinispan.test.op.TestWriteOperation in project infinispan by infinispan.
the class StateTransferOverwritingValueTest method doTest.
private void doTest(final TestWriteOperation op) throws Exception {
// Test scenario:
// cache0 is the only member in the cluster, cache1 joins
// Key k is in the cache, and is transferred to cache1
// A user operation/tx also modifies key k
// The user tx must update k even if it doesn't find key k in the data container.
final AdvancedCache<Object, Object> cache0 = advancedCache(0);
final String key = "key";
// Prepare for replace/remove: put a previous value in cache0
final Object previousValue = op.getPreviousValue();
if (previousValue != null) {
cache0.put(key, previousValue);
assertEquals(previousValue, cache0.get(key));
log.tracef("Previous value inserted: %s = %s", key, previousValue);
}
int preJoinTopologyId = cache0.getDistributionManager().getCacheTopology().getTopologyId();
// Block any state response commands on cache0
CheckPoint checkPoint = new CheckPoint();
ControlledRpcManager blockingRpcManager0 = replaceRpcManager(cache0);
blockingRpcManager0.excludeCommands(WriteCommand.class, BackupWriteCommand.class, RevokeBiasCommand.class, InvalidateVersionsCommand.class, AbstractTransactionBoundaryCommand.class, TxCompletionNotificationCommand.class);
int rebalanceTopologyId = preJoinTopologyId + 1;
// Block the rebalance confirmation on cache0
blockRebalanceConfirmation(manager(0), checkPoint, rebalanceTopologyId);
// Start the joiner
log.tracef("Starting the cache on the joiner");
ConfigurationBuilder c = getConfigurationBuilder();
c.clustering().stateTransfer().awaitInitialTransfer(false).timeout(30, SECONDS);
addClusterEnabledCacheManager(c);
final AdvancedCache<Object, Object> cache1 = advancedCache(1);
// Wait for joiner to finish requesting segments, so that write commands are not blocked
StateTransferLock stateTransferLock1 = TestingUtil.extractComponent(cache1, StateTransferLock.class);
stateTransferLock1.transactionDataFuture(rebalanceTopologyId).toCompletableFuture().get(10, SECONDS);
assertEquals(2, cache1.getRpcManager().getMembers().size());
// Every PutKeyValueCommand will be blocked before committing the entry on cache1
CyclicBarrier beforeCommitCache1Barrier = new CyclicBarrier(2);
// Scattered cache mode uses only PKVC or RemoveCommands for backup
BlockingInterceptor<?> blockingInterceptor1 = new BlockingInterceptor<>(beforeCommitCache1Barrier, true, false, cacheMode.isScattered() ? t -> t instanceof PutKeyValueCommand || t instanceof RemoveCommand : t -> t.getClass().equals(op.getCommandClass()));
AsyncInterceptorChain interceptorChain1 = TestingUtil.extractInterceptorChain(cache1);
Class<? extends EntryWrappingInterceptor> ewi = interceptorChain1.findInterceptorExtending(EntryWrappingInterceptor.class).getClass();
assertTrue(interceptorChain1.addInterceptorAfter(blockingInterceptor1, ewi));
// Wait for cache0 to collect the state to send to cache1 (including our previous value).
ControlledRpcManager.BlockedRequest<?> blockedStateResponse = blockingRpcManager0.expectCommand(StateResponseCommand.class);
// Put/Replace/Remove from cache0 with cache0 as primary owner, cache1 will become a backup owner for the retry
// The put command will be blocked on cache1 just before committing the entry.
Future<Object> future = fork(() -> op.perform(cache0, key));
// Wait for the entry to be wrapped on cache1
beforeCommitCache1Barrier.await(10, TimeUnit.SECONDS);
// Stop blocking, otherwise we'll block the state transfer put commands as well
blockingInterceptor1.suspend(true);
// Allow the state to be applied on cache1 (writing the old value for our entry)
blockedStateResponse.send().receiveAll();
if (cacheMode.isScattered()) {
blockingRpcManager0.expectCommand(StateResponseCommand.class).send().receiveAll();
}
// Wait for cache1 to finish applying the state, but don't allow the rebalance confirmation to be processed.
// (It would change the topology and it would trigger a retry for the command.)
checkPoint.awaitStrict("pre_rebalance_confirmation_" + rebalanceTopologyId + "_from_" + address(1), 10, SECONDS);
// Now allow the command to commit on cache1
beforeCommitCache1Barrier.await(10, TimeUnit.SECONDS);
// Wait for the command to finish and check that it didn't fail
Object result = future.get(10, TimeUnit.SECONDS);
assertEquals(op.getReturnValue(), result);
log.tracef("%s operation is done", op);
// Allow the rebalance confirmation to proceed and wait for the topology to change everywhere
checkPoint.trigger("resume_rebalance_confirmation_" + rebalanceTopologyId + "_from_" + address(0));
checkPoint.trigger("resume_rebalance_confirmation_" + rebalanceTopologyId + "_from_" + address(1));
TestingUtil.waitForNoRebalance(cache0, cache1);
// Check the value on all the nodes
assertEquals(op.getValue(), cache0.get(key));
assertEquals(op.getValue(), cache1.get(key));
blockingRpcManager0.stopBlocking();
}
Aggregations