use of io.cdap.cdap.app.store.ApplicationFilter in project cdap by caskdata.
the class AppMetadataStore method scanApplications.
/**
* Scans applications. Allows to optionally set namespace / filters and implement pagination. For pagination
* set {@link ScanApplicationsRequest#getScanFrom()} to the last application id of the previous page.
*
* @param request parameters defining filters and sorting
* @param func a {@link Function} to consume application metadata entries generated by the scan. The boolean
* value returned is {@code true}, the scan will continue; otherwise the scan will stop and return.
* Note that the parameter is a {@link Map.Entry} to allow lazy deserialization of
* {@link ApplicationMeta} and it should not be replaced with {@link BiFunction}.
* @see ScanApplicationsRequest#builder(ScanApplicationsRequest) to create a next page / batch request
* @throws IOException if failed to scan the storage
*/
public void scanApplications(ScanApplicationsRequest request, Function<Map.Entry<ApplicationId, ApplicationMeta>, Boolean> func) throws IOException {
Range.Bound startBound = Range.Bound.INCLUSIVE;
Collection<Field<?>> startFields = request.getNamespaceId() == null ? Collections.emptyList() : Collections.singletonList(Fields.stringField(StoreDefinition.AppMetadataStore.NAMESPACE_FIELD, request.getNamespaceId().getNamespace()));
Range.Bound endBound = Range.Bound.INCLUSIVE;
Collection<Field<?>> endFields = startFields;
if (request.getScanFrom() != null) {
if (request.getNamespaceId() != null && !request.getNamespaceId().equals(request.getScanFrom().getNamespaceId())) {
throw new IllegalArgumentException("Requested to start scan from application " + request.getScanFrom() + " that is outside of scan namespace " + request.getNamespaceId());
}
startBound = Range.Bound.EXCLUSIVE;
startFields = getApplicationPrimaryKeys(request.getScanFrom());
}
if (request.getScanTo() != null) {
if (request.getNamespaceId() != null && !request.getNamespaceId().equals(request.getScanTo().getNamespaceId())) {
throw new IllegalArgumentException("Requested to finish scan at application " + request.getScanTo() + " that is outside of scan namespace " + request.getNamespaceId());
}
endBound = Range.Bound.EXCLUSIVE;
endFields = getApplicationPrimaryKeys(request.getScanTo());
}
Range range;
if (request.getSortOrder() == SortOrder.ASC) {
range = Range.create(startFields, startBound, endFields, endBound);
} else {
range = Range.create(endFields, endBound, startFields, startBound);
}
// As of now this is where we push filter to. it does not go to the StructuredTable,
// but we don't deserialize ApplicationMeta unless needed
Predicate<AppScanEntry> scanEntryPredicate = e -> true;
for (ApplicationFilter filter : request.getFilters()) {
if (filter instanceof ApplicationFilter.ApplicationIdFilter) {
scanEntryPredicate = scanEntryPredicate.and(e -> ((ApplicationFilter.ApplicationIdFilter) filter).test(e.getKey()));
} else if (filter instanceof ApplicationFilter.ArtifactIdFilter) {
scanEntryPredicate = scanEntryPredicate.and(e -> ((ApplicationFilter.ArtifactIdFilter) filter).test(e.getValue().getSpec().getArtifactId()));
} else {
throw new UnsupportedOperationException("Application filter " + filter + " is not supported");
}
}
StructuredTable table = getApplicationSpecificationTable();
int limit = request.getLimit();
try (CloseableIterator<StructuredRow> iterator = table.scan(range, Integer.MAX_VALUE, request.getSortOrder())) {
boolean keepScanning = true;
while (iterator.hasNext() && keepScanning && limit > 0) {
StructuredRow row = iterator.next();
AppScanEntry scanEntry = new AppScanEntry(row);
if (scanEntryPredicate.test(scanEntry)) {
keepScanning = func.apply(scanEntry);
limit--;
}
}
}
}
Aggregations