use of io.pravega.controller.store.stream.AbstractStreamMetadataStore.DATA_NOT_FOUND_PREDICATE in project pravega by pravega.
the class PersistentStreamBase method generateMarksForTransactions.
/**
* This method takes the list of transactions in the committing transactions record, and tries to report marks
* for writers for these transactions, if the information about writer is present in the record. The information
* about writer and commit time is optionally provided by the client. A client not interested in watermarking may not
* report writer id and time during commit request. Similarly older clients will not report writer id and time either.
* WriterId, commit time and commit offsets are recorded in ActiveTxnRecord for each transaction.
* For transactions where above fields are present, a mark is recorded for them.
* This method will ignore any INVALID_TIME or INVALID_POSITION related failures in noting marks for writers.
* This is because those will typically arise from idempotent commit case where this and a transaction with higher
* position and time may already have been committed and the overall mark for the writer may already have progressed.
*
* @return A completableFuture, which when completed will have marks reported for all transactions in the committing
* transaction record for which a writer with time and position information is available.
*/
CompletableFuture<Void> generateMarksForTransactions(OperationContext context, Map<String, TxnWriterMark> writerMarks) {
Preconditions.checkNotNull(context, "Operation context cannot be null");
Preconditions.checkArgument(writerMarks != null);
// For each writerId we will take the transaction with the time and position pair (which is to take
// max of all transactions for the said writer).
// Note: if multiple transactions from same writer have same time, we will take any one arbitrarily and
// use its position for watermarks. Other positions and times would be ignored.
val noteTimeFutures = writerMarks.entrySet().stream().map(x -> Futures.exceptionallyExpecting(noteWriterMark(x.getKey(), x.getValue().getTimestamp(), x.getValue().getPosition(), context), DATA_NOT_FOUND_PREDICATE, null)).collect(Collectors.toList());
return Futures.allOf(noteTimeFutures);
}
use of io.pravega.controller.store.stream.AbstractStreamMetadataStore.DATA_NOT_FOUND_PREDICATE in project pravega by pravega.
the class PersistentStreamBase method noteWriterMark.
@Override
public CompletableFuture<WriterTimestampResponse> noteWriterMark(String writer, long timestamp, Map<Long, Long> position, OperationContext context) {
Preconditions.checkNotNull(context, "operation context cannot be null");
// Remember: a writer position is not a stream cut.
// For sanity check we will check that the request advances the time and position.
// if time is not advanced --> respond with invalid time.
// if position is not advanced --> respond with invalid position
ImmutableMap<Long, Long> newPosition = ImmutableMap.copyOf(position);
return Futures.exceptionallyExpecting(getWriterMarkRecord(writer, context), DATA_NOT_FOUND_PREDICATE, null).thenCompose(record -> {
if (record == null) {
// we will translate it to writeConflict and let the caller deal with it.
return createWriterMarkRecord(writer, timestamp, newPosition, context).exceptionally(e -> {
if (Exceptions.unwrap(e) instanceof StoreException.DataExistsException) {
throw StoreException.create(StoreException.Type.WRITE_CONFLICT, "writer mark exists");
}
throw new CompletionException(e);
}).thenApply(v -> WriterTimestampResponse.SUCCESS);
} else {
// sanity check and update
if (record.getObject().getTimestamp() > timestamp) {
// existing time is already ahead of new time
return CompletableFuture.completedFuture(WriterTimestampResponse.INVALID_TIME);
}
if (!compareWriterPositions(record.getObject().getPosition(), newPosition)) {
// existing position is already ahead of new position
return CompletableFuture.completedFuture(WriterTimestampResponse.INVALID_POSITION);
}
// its a valid mark, update it
return updateWriterMarkRecord(writer, timestamp, newPosition, true, record.getVersion(), context).thenApply(v -> WriterTimestampResponse.SUCCESS);
}
});
}
Aggregations