Skip to content

Commit

Permalink
Error handling in KG
Browse files Browse the repository at this point in the history
  • Loading branch information
fvilla committed Dec 4, 2024
1 parent c9a4b4c commit 8d27f71
Show file tree
Hide file tree
Showing 5 changed files with 90 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
CLIReasonerView.Type.class, CLIReasonerView.BaseConcept.class,
CLIReasonerView.Compatible.class,
CLIReasonerView.Strategy.class, CLIReasonerView.Export.class,
CLIReasonerView.Matching.class})
CLIReasonerView.Matching.class, CLIReasonerView.Roles.class})
public class CLIReasonerView {


Expand Down Expand Up @@ -364,6 +364,42 @@ public void run() {

}

@Command(name = "roles", mixinStandardHelpOptions = true, version = Version.CURRENT, description = {
"List all the roles in a concept."}, subcommands = {})
public static class Roles implements Runnable {

@Spec
CommandSpec commandSpec;

@Option(names = {"-i", "--inherited"}, defaultValue = "false", description = {
"Include inherited traits"}, required = false)
boolean inherited = false;

@Parameters
java.util.List<String> observables;

@Override
public void run() {

PrintWriter out = commandSpec.commandLine().getOut();
PrintWriter err = commandSpec.commandLine().getErr();

var urn = Utils.Strings.join(observables, " ");
var reasoner = KlabCLI.INSTANCE.modeler().currentUser()
.getService(org.integratedmodelling.klab.api.services.Reasoner.class);
Concept concept = reasoner.resolveConcept(urn);
if (concept == null) {
err.println("Concept " + urn + " not found");
} else {
for (Concept c : inherited ? reasoner.roles(concept) : reasoner.directRoles(concept)) {
out.println(CommandLine.Help.Ansi.AUTO.string(" @|yellow " + c + "|@ " + c.getType()));
}
}
}

}


@Command(name = "export", mixinStandardHelpOptions = true, version = Version.CURRENT, description = {
"export a namespace to an OWL ontology."}, subcommands = {})
public static class Export implements Runnable {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import org.integratedmodelling.klab.api.data.Storage;
import org.integratedmodelling.klab.api.digitaltwin.StateStorage;
import org.integratedmodelling.klab.api.exceptions.KlabIllegalStateException;
import org.integratedmodelling.klab.api.exceptions.KlabResourceAccessException;
import org.integratedmodelling.klab.api.exceptions.KlabUnimplementedException;
import org.integratedmodelling.klab.api.knowledge.observation.Observation;
Expand Down Expand Up @@ -184,39 +185,46 @@ public <T extends Storage> T getExistingStorage(Observation observation, Class<T
if (ret != null && storageClass.isAssignableFrom(ret.getClass())) {
return (T) ret;
}
throw new KlabResourceAccessException("Observation " + observation + " does not have associated " +
"storage");
return null;
}

@Override
public <T extends Storage> T getOrCreateStorage(Observation observation, Class<T> storageClass) {

// TODO this just creates, never retrieves. Not sure if/how that works with mmapped files, may
// need to save on exit.

T ret = null;

if (DoubleStorage.class.isAssignableFrom(storageClass)) {
ret = (T) new DoubleStorage(Scale.create(observation.getGeometry()), this);
} else if (FloatStorage.class.isAssignableFrom(storageClass)) {
ret = (T) new FloatStorage(Scale.create(observation.getGeometry()), this);
} else if (IntStorage.class.isAssignableFrom(storageClass)) {
ret = (T) new IntStorage(Scale.create(observation.getGeometry()), this);
} else if (BooleanStorage.class.isAssignableFrom(storageClass)) {
ret = (T) new BooleanStorage(Scale.create(observation.getGeometry()), this);
} else if (KeyedStorage.class.isAssignableFrom(storageClass)) {
ret = (T) new KeyedStorage(Scale.create(observation.getGeometry()), this);
Class<?> sClass = storageClass;
if (storageClass == Storage.class) {
sClass = switch (observation.getObservable().getArtifactType()) {
case BOOLEAN -> BooleanStorage.class;
case NUMBER -> /* TODO use config to choose between double and float */ DoubleStorage.class;
case TEXT, CONCEPT -> KeyedStorage.class;
default ->
throw new KlabIllegalStateException("scalar mapping to type " + observation.getObservable().getArtifactType() + " not supported");
};
}

if (ret != null) {

// TODO load any existing state
T ret = getExistingStorage(observation, (Class<T>) sClass);

if (ret == null) {
if (DoubleStorage.class.isAssignableFrom(sClass)) {
ret = (T) new DoubleStorage(Scale.create(observation.getGeometry()), this);
} else if (FloatStorage.class.isAssignableFrom(sClass)) {
ret = (T) new FloatStorage(Scale.create(observation.getGeometry()), this);
} else if (IntStorage.class.isAssignableFrom(sClass)) {
ret = (T) new IntStorage(Scale.create(observation.getGeometry()), this);
} else if (BooleanStorage.class.isAssignableFrom(sClass)) {
ret = (T) new BooleanStorage(Scale.create(observation.getGeometry()), this);
} else if (KeyedStorage.class.isAssignableFrom(sClass)) {
ret = (T) new KeyedStorage(Scale.create(observation.getGeometry()), this);
}
}

if (ret != null) {
// TODO load any pre-existing state
storage.put(observation.getUrn(), ret);
return ret;
}

throw new KlabUnimplementedException("cannot create storage of class " + storageClass.getCanonicalName());
throw new KlabUnimplementedException("cannot create storage of class " + sClass.getCanonicalName());

}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,6 @@ private void compile(Actuator actuator) {
}
}


var descriptor = componentRegistry.getFunctionDescriptor(call);
if (descriptor.serviceInfo.getGeometry().isScalar()) {

Expand All @@ -206,13 +205,13 @@ private void compile(Actuator actuator) {
scalarMapper = null;
}

// we can be pretty sure that this will be a scale by now
// FIXME actually it's not. And we should cache scales.
var scale = Scale.create(observation.getGeometry());
Storage storage = digitalTwin.stateStorage().getExistingStorage(observation,
Storage storage = digitalTwin.stateStorage().getOrCreateStorage(observation,
Storage.class);
/**
/*
* Create a runnable with matched parameters and have it set the context observation
* TODO allow multiple methods taking different storage implementations, enabling the
* storage manager to be configured for the wanted precision
*/
List<Object> runArguments = new ArrayList<>();
if (descriptor.method != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,8 @@ public long submit(Observation observation, ContextScope scope) {
* root DT level and we get the context initialization activity as parent.
*/
var instantiation = digitalTwin.knowledgeGraph().operation(agent, parentActivity,
Activity.Type.INSTANTIATION, observation, this);
Activity.Type.INSTANTIATION,
"Instantiation of " + observation, observation, this);

try (instantiation) {

Expand Down Expand Up @@ -397,7 +398,8 @@ public Future<Observation> resolve(long id, ContextScope scope) {
This will commit or rollback at close()
*/
var resolution = digitalTwin.knowledgeGraph().operation(digitalTwin.knowledgeGraph().klab()
, parentActivity, Activity.Type.RESOLUTION, resolver);
, parentActivity, Activity.Type.RESOLUTION,
"Resolution of " + observation, resolver);

try (resolution) {
result = observation;
Expand All @@ -417,14 +419,17 @@ This will commit or rollback at close()
ret.completeExceptionally(new KlabResourceAccessException("Resolution of " + observation.getUrn() + " failed"));
}
} catch (Throwable t) {
Logging.INSTANCE.error(t);
ret.completeExceptionally(t);
resolution.fail(scope, observation, t);
scope.send(Message.MessageClass.ObservationLifecycle,
Message.MessageType.ResolutionAborted, observation);
}
} catch (Throwable t) {
Logging.INSTANCE.error(t);
scope.send(Message.MessageClass.ObservationLifecycle,
Message.MessageType.ResolutionAborted, observation);
resolution.fail(scope, observation, t);
ret.completeExceptionally(t);
}

Expand All @@ -435,7 +440,10 @@ this will commit all resources at close()
*/
var contextualization =
digitalTwin.knowledgeGraph().operation(digitalTwin.knowledgeGraph().klab(),
resolutionActivity, Activity.Type.EXECUTION, dataflow, this);
resolutionActivity, Activity.Type.EXECUTION,
"Execution of resolved dataflow to contextualize " + observation,
dataflow,
this);

try (contextualization) {
// TODO contextualization gets its own activities to use in operations
Expand All @@ -444,6 +452,7 @@ this will commit all resources at close()
ret.complete(result);
contextualization.success(scope, dataflow, result);
} catch (Throwable t) {
Logging.INSTANCE.error(t);
contextualization.fail(scope, dataflow, result, t);
ret.completeExceptionally(t);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,8 @@ public void close() throws IOException {
for (var asset : assets) {
if (asset instanceof ObservationImpl obs) {
observation = obs;
} else if (asset instanceof Throwable t) {
activity.setStackTrace(ExceptionUtils.getStackTrace(t));
}
}
}
Expand All @@ -249,6 +251,7 @@ public void close() throws IOException {

if (outcome == null) {
// Log an internal failure (no success or failure, should not happen)
Logging.INSTANCE.error("Internal error: activity did not properly finish: " + activity);
transaction.rollback();
} else if (outcome == Scope.Status.FINISHED) {
transaction.commit();
Expand Down Expand Up @@ -540,11 +543,13 @@ protected <T> List<T> adapt(EagerResult query, Class<T> cls, Scope scope) {
instance.setStart(node.get("start").asLong());
instance.setEnd(node.get("end").asLong());
instance.setName(node.get("name").asString());
instance.setServiceName(node.get("serviceName").isNull()? null : node.get("serviceName").asString());
instance.setServiceId(node.get("serviceId").isNull() ? null : node.get("serviceId").asString());
instance.setServiceName(node.get("serviceName").isNull() ? null :
node.get("serviceName").asString());
instance.setServiceId(node.get("serviceId").isNull() ? null :
node.get("serviceId").asString());
instance.setServiceType(node.get("serviceType").isNull() ? null :
KlabService.Type.valueOf(node.get("serviceType").asString()));
instance.setDataflow(node.get("dataflow").isNull() ? null : node.get("dataflow").asString());
instance.setDataflow(node.get("dataflow").isNull() ? null : node.get("dataflow").asString());
instance.setType(Activity.Type.valueOf(instance.getName()));
instance.setDescription(node.get("description").isNull() ? "No description" : node.get(
"description").asString());
Expand Down

0 comments on commit 8d27f71

Please sign in to comment.