use of org.infinispan.reactive.publisher.impl.commands.batch.PublisherResponse in project infinispan by infinispan.
the class InnerPublisherSubscription method accept.
/**
* This method is invoked every time a new request is sent to the underlying publisher. We need to submit a request
* if there is not a pending one. Whenever requestedAmount is a number greater than 0, that means we must submit or
* there is a pending one.
* @param count request count
*/
@Override
public void accept(long count) {
if (shouldSubmit(count)) {
if (checkCancelled()) {
return;
}
// Find which address and segments we still need to retrieve - when the supplier returns null that means
// we don't need to do anything else (normal termination state)
Map.Entry<Address, IntSet> target = currentTarget;
if (target == null) {
alreadyCreated = false;
target = builder.supplier.get();
if (target == null) {
if (log.isTraceEnabled()) {
log.tracef("Completing processor %s", flowableProcessor);
}
flowableProcessor.onComplete();
return;
} else {
currentTarget = target;
}
}
ClusterPublisherManagerImpl<K, ?>.SubscriberHandler<I, R> parent = builder.parent;
CompletionStage<PublisherResponse> stage;
Address address = target.getKey();
IntSet segments = target.getValue();
try {
if (alreadyCreated) {
stage = parent.sendNextCommand(address, builder.topologyId);
} else {
alreadyCreated = true;
stage = parent.sendInitialCommand(address, segments, builder.batchSize, builder.excludedKeys.remove(address), builder.topologyId);
}
} catch (Throwable t) {
handleThrowableInResponse(t, address, segments);
return;
}
stage.whenComplete((values, t) -> {
if (t != null) {
handleThrowableInResponse(CompletableFutures.extractException(t), address, segments);
return;
}
try {
if (log.isTraceEnabled()) {
// Note the size of the array may not be the amount of entries as it isn't resized (can contain nulls)
log.tracef("Received %s for id %s from %s", values, parent.requestId, address);
}
IntSet completedSegments = values.getCompletedSegments();
if (completedSegments != null) {
if (log.isTraceEnabled()) {
log.tracef("Completed segments %s for id %s from %s", completedSegments, parent.requestId, address);
}
completedSegments.forEach((IntConsumer) parent::completeSegment);
completedSegments.forEach((IntConsumer) segments::remove);
}
IntSet lostSegments = values.getLostSegments();
if (lostSegments != null) {
if (log.isTraceEnabled()) {
log.tracef("Lost segments %s for id %s from %s", completedSegments, parent.requestId, address);
}
lostSegments.forEach((IntConsumer) segments::remove);
}
boolean complete = values.isComplete();
if (complete) {
// Current address has returned all values it can - setting to null will force the next invocation
// of this method try the next target if available
currentTarget = null;
} else {
values.keysForNonCompletedSegments(parent);
}
R[] valueArray = (R[]) values.getResults();
if (values instanceof KeyPublisherResponse) {
KeyPublisherResponse kpr = (KeyPublisherResponse) values;
int extraSize = kpr.getExtraSize();
if (extraSize > 0) {
int arrayLength = valueArray.length;
Object[] newArray = new Object[arrayLength + extraSize];
System.arraycopy(valueArray, 0, newArray, 0, arrayLength);
System.arraycopy(kpr.getExtraObjects(), 0, newArray, arrayLength, extraSize);
valueArray = (R[]) newArray;
}
}
int pos = 0;
for (PublisherHandler.SegmentResult segmentResult : values.getSegmentResults()) {
if (checkCancelled()) {
return;
}
int segment = segmentResult.getSegment();
for (int i = 0; i < segmentResult.getEntryCount(); ++i) {
R value = valueArray[pos++];
doOnValue(value, segment);
}
if (completedSegments != null && completedSegments.remove(segment)) {
doOnSegmentComplete(segment);
}
}
// Any completed segments left were empty, just complete them together
if (completedSegments != null) {
completedSegments.forEach((IntConsumer) this::doOnSegmentComplete);
}
accept(-pos);
} catch (Throwable innerT) {
handleThrowableInResponse(innerT, address, segments);
}
});
}
}
Aggregations