package io.vertx.ext.healthchecks.impl;
import io.vertx.core.AsyncResult;
import io.vertx.core.Future;
import io.vertx.core.Handler;
import io.vertx.core.Promise;
import io.vertx.core.Vertx;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.healthchecks.HealthChecks;
import io.vertx.ext.healthchecks.Status;
import java.util.Objects;
public class HealthChecksImpl implements HealthChecks {
private final Vertx vertx;
private CompositeProcedure root = new DefaultCompositeProcedure();
public HealthChecksImpl(Vertx vertx) {
this.vertx = Objects.requireNonNull(vertx);
}
@Override
public HealthChecks register(String name, Handler<Promise<Status>> procedure) {
return register(name, 1000L, procedure);
}
@Override
public HealthChecks register(String name, long timeout, Handler<Promise<Status>> procedure) {
Objects.requireNonNull(name);
if (timeout <= 0) {
throw new IllegalArgumentException("The timeout must be strictly positive");
}
if (name.isEmpty()) {
throw new IllegalArgumentException("The name must not be empty");
}
Objects.requireNonNull(procedure);
String[] segments = name.split("/");
CompositeProcedure parent = traverseAndCreate(segments);
String lastSegment = segments[segments.length - 1];
parent.add(lastSegment,
new DefaultProcedure(vertx, lastSegment, timeout, procedure));
return this;
}
private CompositeProcedure traverseAndCreate(String[] segments) {
int i;
CompositeProcedure parent = root;
for (i = 0; i < segments.length - 1; i++) {
Procedure c = parent.get(segments[i]);
if (c == null) {
DefaultCompositeProcedure composite = new DefaultCompositeProcedure();
parent.add(segments[i], composite);
parent = composite;
} else if (c instanceof CompositeProcedure) {
parent = (CompositeProcedure) c;
} else {
throw new IllegalArgumentException("Unable to find the procedure `" + segments[i] + "`, `"
+ segments[i] + "` is not a composite.");
}
}
return parent;
}
@Override
public HealthChecks unregister(String name) {
Objects.requireNonNull(name);
if (name.isEmpty()) {
throw new IllegalArgumentException("The name must not be empty");
}
String[] segments = name.split("/");
CompositeProcedure parent = findLastParent(segments);
if (parent != null) {
String lastSegment = segments[segments.length - 1];
parent.remove(lastSegment);
}
return this;
}
@Override
public HealthChecks invoke(Handler<JsonObject> resultHandler) {
compute(root, resultHandler);
return this;
}
@Override
public HealthChecks invoke(String name, Handler<AsyncResult<JsonObject>> resultHandler) {
if (name == null || name.isEmpty() || name.equals("/")) {
return invoke(json -> resultHandler.handle(Future.succeededFuture(json)));
} else {
String[] segments = name.split("/");
Procedure check = root;
for (String segment : segments) {
if (segment.trim().isEmpty()) {
continue;
}
if (check instanceof CompositeProcedure) {
check = ((CompositeProcedure) check).get(segment);
if (check == null) {
resultHandler.handle(Future.failedFuture("Not found"));
return this;
}
} else {
resultHandler.handle(Future.failedFuture("'" + segment + "' is not a composite"));
return this;
}
}
if (check == null) {
resultHandler.handle(null);
return this;
}
compute(check, json -> resultHandler.handle(Future.succeededFuture(json)));
}
return this;
}
private CompositeProcedure findLastParent(String[] segments) {
int i;
CompositeProcedure parent = root;
for (i = 0; i < segments.length - 1; i++) {
Procedure c = parent.get(segments[i]);
if (c instanceof CompositeProcedure) {
parent = (CompositeProcedure) c;
} else {
return null;
}
}
return parent;
}
private void compute(Procedure procedure, Handler<JsonObject> resultHandler) {
procedure.check(resultHandler);
}
}