use of cz.o2.proxima.direct.core.CommitCallback in project proxima-platform by O2-Czech-Republic.
the class TransactionIT method swapValueBetween.
private boolean swapValueBetween(String key, String attrA, String attrB, boolean canFailWrite) throws InterruptedException {
long retrySleep = 1;
do {
String transactionId = UUID.randomUUID().toString();
BlockingQueue<Response> responses = new ArrayBlockingQueue<>(1);
Optional<KeyValue<byte[]>> valA = view.get(key, attrA, device);
Optional<KeyValue<byte[]>> valB = view.get(key, attrB, device);
final List<KeyAttribute> fetched = Arrays.asList(valA.isPresent() ? KeyAttributes.ofStreamElement(valA.get()) : KeyAttributes.ofMissingAttribute(user, key, device, device.extractSuffix(attrA)), valB.isPresent() ? KeyAttributes.ofStreamElement(valB.get()) : KeyAttributes.ofMissingAttribute(user, key, device, device.extractSuffix(attrB)));
client.begin(transactionId, (id, resp) -> ExceptionUtils.unchecked(() -> responses.put(resp)), fetched);
Response response = responses.take();
if (response.getFlags() != Flags.OPEN) {
;
TimeUnit.MILLISECONDS.sleep(Math.min(8, retrySleep *= 2));
continue;
}
long sequentialId = response.getSeqId();
final List<StreamElement> updates;
if (valA.isPresent()) {
int currentVal = ByteBuffer.wrap(valA.get().getParsedRequired()).getInt();
updates = updateAttributeAndRemove(sequentialId, key, attrB, attrA, currentVal);
} else {
int currentVal = ByteBuffer.wrap(valB.get().getParsedRequired()).getInt();
updates = updateAttributeAndRemove(sequentialId, key, attrA, attrB, currentVal);
}
client.commit(transactionId, updates.stream().map(KeyAttributes::ofStreamElement).collect(Collectors.toList()));
response = responses.take();
if (response.getFlags() != Flags.COMMITTED) {
TimeUnit.MILLISECONDS.sleep(Math.min(8, retrySleep *= 2));
continue;
}
CountDownLatch latch = new CountDownLatch(1);
AtomicBoolean succeeded = new AtomicBoolean();
CommitCallback callback = (succ, exc) -> {
if (!succ) {
client.rollback(transactionId);
}
succeeded.set(succ);
latch.countDown();
};
if (canFailWrite && random.nextBoolean()) {
callback.commit(false, new RuntimeException("Failed!"));
} else {
CommitCallback multiCallback = CommitCallback.afterNumCommits(updates.size(), callback);
updates.forEach(u -> view.write(u, multiCallback));
}
latch.await();
return succeeded.get();
} while (true);
}
use of cz.o2.proxima.direct.core.CommitCallback in project proxima-platform by O2-Czech-Republic.
the class TransactionIT_Large method swapValueBetween.
private boolean swapValueBetween(String key, String attrA, String attrB, boolean canFailWrite) throws InterruptedException {
long retrySleep = 1;
do {
String transactionId = UUID.randomUUID().toString();
BlockingQueue<Response> responses = new ArrayBlockingQueue<>(1);
Optional<KeyValue<byte[]>> valA = view.get(key, attrA, device);
Optional<KeyValue<byte[]>> valB = view.get(key, attrB, device);
final List<KeyAttribute> fetched = Arrays.asList(valA.isPresent() ? KeyAttributes.ofStreamElement(valA.get()) : KeyAttributes.ofMissingAttribute(user, key, device, device.extractSuffix(attrA)), valB.isPresent() ? KeyAttributes.ofStreamElement(valB.get()) : KeyAttributes.ofMissingAttribute(user, key, device, device.extractSuffix(attrB)));
client.begin(transactionId, (id, resp) -> ExceptionUtils.unchecked(() -> responses.put(resp)), fetched);
Response response = responses.take();
if (response.getFlags() != Flags.OPEN) {
;
TimeUnit.MILLISECONDS.sleep(Math.min(8, retrySleep *= 2));
continue;
}
long sequentialId = response.getSeqId();
final List<StreamElement> updates;
if (valA.isPresent()) {
int currentVal = ByteBuffer.wrap(valA.get().getParsedRequired()).getInt();
updates = updateAttributeAndRemove(sequentialId, key, attrB, attrA, currentVal);
} else {
int currentVal = ByteBuffer.wrap(valB.get().getParsedRequired()).getInt();
updates = updateAttributeAndRemove(sequentialId, key, attrA, attrB, currentVal);
}
client.commit(transactionId, updates.stream().map(KeyAttributes::ofStreamElement).collect(Collectors.toList()));
response = responses.take();
if (response.getFlags() != Flags.COMMITTED) {
TimeUnit.MILLISECONDS.sleep(Math.min(8, retrySleep *= 2));
continue;
}
CountDownLatch latch = new CountDownLatch(1);
AtomicBoolean succeeded = new AtomicBoolean();
CommitCallback callback = (succ, exc) -> {
if (!succ) {
client.rollback(transactionId);
}
succeeded.set(succ);
latch.countDown();
};
if (canFailWrite && random.nextBoolean()) {
callback.commit(false, new RuntimeException("Failed!"));
} else {
CommitCallback multiCallback = CommitCallback.afterNumCommits(updates.size(), callback);
updates.forEach(u -> view.write(u, multiCallback));
}
latch.await();
return succeeded.get();
} while (true);
}
use of cz.o2.proxima.direct.core.CommitCallback in project proxima-platform by O2-Czech-Republic.
the class TransactionalOnlineAttributeWriter method write.
@Override
public synchronized void write(StreamElement data, CommitCallback statusCallback) {
// this means start transaction with the single KeyAttribute as input and then
// commit that transaction right away
executor.execute(() -> {
try (Transaction t = begin()) {
@Nullable String suffix = data.getAttributeDescriptor().isWildcard() ? data.getAttribute().substring(data.getAttributeDescriptor().toAttributePrefix().length()) : null;
KeyAttribute outputKeyAttribute = KeyAttributes.ofAttributeDescriptor(data.getEntityDescriptor(), data.getKey(), data.getAttributeDescriptor(), Long.MAX_VALUE, suffix);
t.update(Collections.singletonList(outputKeyAttribute));
t.commitWrite(Collections.singletonList(data), statusCallback);
} catch (TransactionRejectedException e) {
statusCallback.commit(false, e);
}
});
}
use of cz.o2.proxima.direct.core.CommitCallback in project proxima-platform by O2-Czech-Republic.
the class TransactionResourceManager method writeResponseAndUpdateState.
@Override
public void writeResponseAndUpdateState(String transactionId, State updateState, String responseId, Response response, CommitCallback callback) {
CachedTransaction cachedTransaction = openTransactionMap.get(transactionId);
if (cachedTransaction != null) {
DirectAttributeFamilyDescriptor responseFamily = cachedTransaction.getResponseFamily();
DirectAttributeFamilyDescriptor stateFamily = cachedTransaction.getStateFamily();
final OnlineAttributeWriter writer = cachedTransaction.getCommitWriter();
final CachedView stateView = cachedTransaction.getStateView();
long now = System.currentTimeMillis();
StreamElement stateUpsert = getStateDesc().upsert(transactionId, now, updateState);
Commit commit = Commit.of(Arrays.asList(new Commit.TransactionUpdate(stateFamily.getDesc().getName(), stateUpsert), new Commit.TransactionUpdate(responseFamily.getDesc().getName(), getResponseDesc().upsert(transactionId, responseId, now, response))));
synchronized (stateView) {
ensureTransactionOpen(transactionId, updateState);
stateView.cache(stateUpsert);
}
synchronized (writer) {
writer.write(getCommitDesc().upsert(transactionId, System.currentTimeMillis(), commit), callback);
}
} else {
log.warn("Transaction {} is not open, don't have a writer to return response {}", transactionId, response);
callback.commit(true, null);
}
}
use of cz.o2.proxima.direct.core.CommitCallback in project proxima-platform by O2-Czech-Republic.
the class CommitCallback method afterNumCommits.
/**
* Create new {@link CommitCallback} that will commit the delegate after
*
* <ul>
* <li>{@code numCommits} successful commits as successful, or
* <li>after first error as failed
* </ul>
*
* @param numCommits
* @param delegate
* @return
*/
static CommitCallback afterNumCommits(int numCommits, CommitCallback delegate) {
Preconditions.checkState(numCommits > 0, "numCommits must be positive, got %s", numCommits);
AtomicInteger missingCommits = new AtomicInteger(numCommits);
return (succ, exc) -> {
if (succ) {
if (missingCommits.decrementAndGet() == 0) {
delegate.commit(true, null);
}
} else if (missingCommits.get() > 0) {
missingCommits.set(-1);
delegate.commit(false, exc);
}
};
}
Aggregations