use of io.datarouter.web.handler.types.Param in project datarouter by hotpads.
the class S3BucketHandler method countObjects.
@Handler
public Mav countObjects(@Param(P_client) String client, @Param(P_bucket) String bucket, @Param(P_prefix) OptionalString prefix) {
ClientId clientId = clients.getClientId(client);
DatarouterS3Client s3Client = s3ClientManager.getClient(clientId);
var count = new AtomicLong();
var size = new AtomicLong();
var message = new AtomicReference<String>();
s3Client.scanObjects(bucket, prefix.orElse("")).each($ -> count.incrementAndGet()).each(obj -> size.addAndGet(obj.size())).sample(10_000, true).map(obj -> String.format("client=%s, bucket=%s, prefix=%s, count=%s, size=%s, through=%s", client, bucket, prefix.orElse(null), NumberFormatter.addCommas(count.get()), NumberFormatter.addCommas(size.get()), obj.key())).each(message::set).forEach(logger::warn);
return pageFactory.message(request, message.get());
}
use of io.datarouter.web.handler.types.Param in project datarouter by hotpads.
the class S3BucketHandler method index.
@Handler(defaultHandler = true)
public Mav index(@Param(P_client) String client, @Param(P_bucket) String bucket, @Param(P_prefix) OptionalString prefix, @Param(P_after) OptionalString after, @Param(P_offset) OptionalInteger offset, @Param(P_limit) OptionalInteger limit, @Param(P_currentDirectory) OptionalBoolean currentDirectory, @Param(P_delimiter) OptionalString delimiter) {
var form = new HtmlForm().withMethod("get");
form.addTextField().withDisplay("Client").withName(P_client).withPlaceholder("theClientName").withValue(client);
form.addTextField().withDisplay("Bucket").withName(P_bucket).withPlaceholder("the.bucket.name").withValue(bucket);
form.addTextField().withDisplay("Prefix").withName(P_prefix).withValue(prefix.orElse(""));
form.addTextField().withDisplay("After").withName(P_after).withValue(after.orElse(""));
form.addTextField().withDisplay("Offset").withName(P_offset).withValue(offset.orElse(0) + "");
form.addTextField().withDisplay("Limit").withName(P_limit).withValue(limit.orElse(100) + "");
form.addTextField().withDisplay("Delimiter").withName(P_delimiter).withValue(delimiter.orElse(""));
form.addCheckboxField().withDisplay("currentDirectory").withName(P_currentDirectory).withChecked(currentDirectory.orElse(false));
form.addButton().withDisplay("Submit").withValue("");
var htmlForm = Bootstrap4FormHtml.render(form).withClass("card card-body bg-light");
ClientId clientId = clients.getClientId(client);
DatarouterS3Client s3Client = s3ClientManager.getClient(clientId);
List<DirectoryDto> objects = s3Client.scanSubdirectories(bucket, prefix.orElse(null), after.orElse(null), delimiter.orElse(null), limit.orElse(100), currentDirectory.orElse(false)).list();
int sizePadding = sizePadding(objects);
ContainerTag<?> table = new J2HtmlTable<DirectoryDto>().withClasses("sortable table table-sm table-striped my-4 border").withHtmlColumn("Key", object -> {
String name = object.name;
if (object.isDirectory) {
return td(makePrefixLink(client, bucket, name, "/"));
}
return td(name);
}).withHtmlColumn("Directory", object -> {
boolean isDirectory = object.isDirectory;
if (isDirectory) {
String href = new URIBuilder().setPath(request.getContextPath() + paths.datarouter.clients.awsS3.countObjects.toSlashedString()).addParameter(P_client, client).addParameter(P_bucket, bucket).addParameter(P_prefix, object.name).toString();
return td(a("true, view count").withHref(href));
}
return td(String.valueOf(isDirectory));
}).withHtmlColumn("Size", object -> {
String commas = NumberFormatter.addCommas(object.size);
String padded = StringTool.pad(commas, ' ', sizePadding);
String escaped = padded.replaceAll(" ", " ");
return td(rawHtml(escaped));
}).withColumn("Last Modified", object -> object.lastModified).withColumn("Storage Class", object -> object.storageClass).build(objects);
ContainerTag<?> tableWrapper = table.withStyle("font-family:monospace; font-size:.9em;");
var content = div(htmlForm, h4(bucket), tableWrapper).withClass("container-fluid my-4");
return pageFactory.startBuilder(request).withTitle("S3 Bucket").withRequires(DatarouterWebRequireJsV2.SORTTABLE).withContent(content).buildMav();
}
use of io.datarouter.web.handler.types.Param in project datarouter by hotpads.
the class JobletHandler method list.
@Handler
private Mav list(@Param(PARAM_whereStatus) OptionalString pStatus, @Param(PARAM_type) OptionalString pType) {
Scanner<JobletRequest> requests = jobletRequestDao.scan();
if (pStatus.isPresent() && pType.isPresent()) {
JobletStatus status = JobletStatus.fromPersistentStringStatic(pStatus.get());
requests = requests.include(request -> status == request.getStatus()).include(request -> request.getKey().getType().equals(pType.get()));
} else if (pStatus.isPresent() && pType.isEmpty()) {
JobletStatus status = JobletStatus.fromPersistentStringStatic(pStatus.get());
requests = requests.include(request -> status == request.getStatus());
} else if (pStatus.isEmpty() && pType.isPresent()) {
requests = requests.include(request -> request.getKey().getType().equals(pType.get()));
}
Collection<JobletSummary> summaries = JobletSummary.summarizeByTypeExecutionOrderStatus(requests);
return pageFactory.startBuilder(request).withTitle(TITLE).withRequires(DatarouterWebRequireJsV2.SORTTABLE).withContent(makeContent(summaries)).buildMav();
}
use of io.datarouter.web.handler.types.Param in project datarouter by hotpads.
the class LoadTestGetHandler method get.
@Handler(defaultHandler = true)
private Mav get(@Param(P_num) OptionalString num, @Param(P_max) OptionalString max, @Param(P_numThreads) OptionalString numThreads, @Param(P_batchSize) OptionalString batchSize, @Param(P_logPeriod) OptionalString logPeriod, @Param(P_submitAction) OptionalString submitAction) {
var form = new HtmlForm().withMethod("post");
form.addTextField().withDisplay("Num").withName(P_num).withPlaceholder("100,000").withValue(num.orElse(null));
form.addTextField().withDisplay("Max").withName(P_max).withPlaceholder("10").withValue(max.orElse(null));
form.addTextField().withDisplay("Num Threads").withName(P_numThreads).withPlaceholder("10").withValue(numThreads.orElse(null));
form.addTextField().withDisplay("Batch Size").withName(P_batchSize).withPlaceholder("100").withValue(batchSize.orElse(null));
form.addTextField().withDisplay("Log Period").withName(P_logPeriod).withPlaceholder("1,0000").withValue(logPeriod.orElse(null));
form.addButton().withDisplay("Run Get").withValue("anything");
if (submitAction.isEmpty() || form.hasErrors()) {
return pageFactory.startBuilder(request).withTitle("Load Test - Get").withContent(Html.makeContent(form)).buildMav();
}
PhaseTimer timer = new PhaseTimer("get");
// params
int pNum = num.map(StringTool::nullIfEmpty).map(number -> number.replaceAll(",", "")).map(Integer::valueOf).orElse(DEFAULT_NUM);
int pMax = max.map(StringTool::nullIfEmpty).map(number -> number.replaceAll(",", "")).map(Integer::valueOf).orElse(pNum);
int pNumThreads = numThreads.map(StringTool::nullIfEmpty).map(number -> number.replaceAll(",", "")).map(Integer::valueOf).orElse(DEFAULT_NUM_THREADS);
int pBatchSize = batchSize.map(StringTool::nullIfEmpty).map(number -> number.replaceAll(",", "")).map(Integer::valueOf).orElse(DEFAULT_BATCH_SIZE);
int pLogPeriod = logPeriod.map(StringTool::nullIfEmpty).map(number -> number.replaceAll(",", "")).map(Integer::valueOf).orElse(DEFAULT_LOG_PERIOD);
// tracking
AtomicInteger rowCounter = new AtomicInteger(0);
AtomicLong lastBatchFinished = new AtomicLong(System.nanoTime());
// execute
int numBatches = LoadTestTool.numBatches(pNum, pBatchSize);
ExecutorService executor = Executors.newFixedThreadPool(pNumThreads);
Scanner.of(IntStream.range(0, numBatches).mapToObj(Integer::valueOf)).map(batchId -> LoadTestTool.makeRandomIdBatch(pNum, pMax, pBatchSize, batchId)).map(ids -> new GetBatchCallable(dao.getReaderNode(), ids, pLogPeriod, rowCounter, lastBatchFinished)).parallel(new ParallelScannerContext(executor, pNumThreads, true)).forEach(CallableTool::callUnchecked);
ExecutorServiceTool.shutdown(executor, Duration.ofSeconds(5));
timer.add("got " + rowCounter.get());
var message = div(h2("Load Test Get Results"), div(h3("Results"), dl(dt("Total Time"), dd(timer.getElapsedString()), dt("Rows per second"), dd(timer.getItemsPerSecond(rowCounter.get()) + ""))), div(h3("Params"), dl(dt("Num"), dd(pNum + ""), dt("Max"), dd(pMax + ""), dt("Num Threads"), dd(pNumThreads + ""), dt("Batch Size"), dd(pBatchSize + ""), dt("Log Period"), dd(pLogPeriod + "")))).withClass("container");
logger.warn("total={}, rps={}, num={}, max={}, numThreads={} batchSize={}, logPeriod={}", timer.getElapsedString(), timer.getItemsPerSecond(rowCounter.get()), pNum, pMax, pNumThreads, pBatchSize, pLogPeriod);
return pageFactory.message(request, message);
}
use of io.datarouter.web.handler.types.Param in project datarouter by hotpads.
the class BaseHandler method validateRequestParamValidators.
private Optional<RequestParamValidatorErrorResponseDto> validateRequestParamValidators(Method method, Object[] args) {
Parameter[] parameters = method.getParameters();
for (int index = 0; index < parameters.length; index++) {
Parameter parameter = parameters[index];
String parameterName = parameter.getName();
Optional<?> optionalParameterValue = HandlerTool.getParameterValue(args[index]);
if (optionalParameterValue.isEmpty()) {
continue;
}
Object parameterValue = optionalParameterValue.get();
Annotation[] parameterAnnotations = parameter.getAnnotations();
Optional<RequestParamValidatorErrorResponseDto> errorResponseDto = Scanner.of(parameterAnnotations).include(Param.class::isInstance).map(Param.class::cast).map(Param::validator).exclude(DefaultRequestParamValidator.class::equals).map(validate(parameterName, parameterValue)).exclude(responseDto -> responseDto.success).map(RequestParamValidatorErrorResponseDto::fromRequestParamValidatorResponseDto).findFirst();
if (errorResponseDto.isPresent()) {
return errorResponseDto;
}
}
return Optional.empty();
}
Aggregations