Skip to content

Commit

Permalink
Separate "operational" services from "essential"
Browse files Browse the repository at this point in the history
  • Loading branch information
fvilla committed Sep 17, 2024
1 parent d102e22 commit 1647e13
Show file tree
Hide file tree
Showing 18 changed files with 220 additions and 144 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
import java.time.ZonedDateTime;
import java.util.List;

import org.integratedmodelling.klab.api.Klab;
import org.integratedmodelling.klab.api.configuration.Configuration;
import org.integratedmodelling.klab.api.exceptions.KlabIllegalArgumentException;
import org.integratedmodelling.klab.api.geometry.Geometry.Dimension;
import org.integratedmodelling.klab.api.geometry.impl.GeometryImpl.DimensionImpl;
Expand Down Expand Up @@ -46,6 +48,7 @@ public class TimeBuilder {
if (time == null) {
time = new DimensionImpl();
time.setType(Dimension.Type.TIME);
time.getParameters().put(GeometryImpl.PARAMETER_TIME_REPRESENTATION, Time.Type.LOGICAL);
time.setDimensionality(1);
}
}
Expand All @@ -72,11 +75,34 @@ public TimeBuilder covering(long startMs, long endMs) {
return this;
}

public TimeBuilder step(Quantity quantity) {
regular();
time.getParameters().put(GeometryImpl.PARAMETER_TIME_REPRESENTATION, Time.Type.GRID);
time.getParameters().put(GeometryImpl.PARAMETER_TIME_GRIDRESOLUTION, quantity);
return this;
}

public TimeBuilder between(TimeInstant start, TimeInstant end) {
start(start);
end(end);
time.getParameters().put(GeometryImpl.PARAMETER_TIME_REPRESENTATION, Time.Type.PHYSICAL);
return this;
}

public TimeBuilder between(long start, long end) {
start(start);
end(end);
time.getParameters().put(GeometryImpl.PARAMETER_TIME_REPRESENTATION, Time.Type.PHYSICAL);
return this;
}

public TimeBuilder year(int year) {
var start = TimeInstant.create(year);
this.start(start.getMilliseconds());
this.end(start.plus(1, Time.Resolution.of(1,
start(start.getMilliseconds());
end(start.plus(1, Time.Resolution.of(1,
Time.Resolution.Type.YEAR)).getMilliseconds());
resolution(Time.Resolution.of(1, Time.Resolution.Type.YEAR));
time.getParameters().put(GeometryImpl.PARAMETER_TIME_REPRESENTATION, Time.Type.PHYSICAL);
return this;
}

Expand Down Expand Up @@ -124,6 +150,10 @@ public SpaceBuilder space() {
}

public GeometryBuilder build() {
if (time.getParameters().get(GeometryImpl.PARAMETER_TIME_START) == null || time.getParameters().get(GeometryImpl.PARAMETER_TIME_START) == null) {
generic();
time.getParameters().put(GeometryImpl.PARAMETER_TIME_REPRESENTATION, Time.Type.LOGICAL);
}
return GeometryBuilder.this;
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.integratedmodelling.klab.api.scope;

import org.integratedmodelling.klab.api.geometry.Geometry;
import org.integratedmodelling.klab.api.knowledge.Concept;
import org.integratedmodelling.klab.api.knowledge.Observable;
import org.integratedmodelling.klab.api.knowledge.observation.DirectObservation;
Expand Down Expand Up @@ -545,6 +546,20 @@ public static String getScopeId(ContextScope scope) {
}


static Geometry getResolutionGeometry(ContextScope scope) {

var resolutionGeometry = scope.getConstraint(ResolutionConstraint.Type.Geometry, Geometry.class);
if (resolutionGeometry == null || resolutionGeometry.isEmpty()) {
if (scope.getContextObservation() != null) {
resolutionGeometry = scope.getContextObservation().getGeometry();
}
if ((resolutionGeometry == null || resolutionGeometry.isEmpty()) && scope.getObserver() != null) {
resolutionGeometry = scope.getObserver().getObserverGeometry();
}
}
return resolutionGeometry;
}

/**
* Parse a scope token into the corresponding data structure
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -586,7 +586,6 @@ public void setSchema(Class<?> cls, Schema schema) {
*
* @param query
* @return the list of IDs resulting, or empty
* @throws KlabException
*/
public List<Long> queryIds(String query) {

Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,5 @@
package org.integratedmodelling.klab.services;

import java.util.*;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;

import org.integratedmodelling.common.authentication.Authentication;
import org.integratedmodelling.common.authentication.scope.AbstractServiceDelegatingScope;
import org.integratedmodelling.common.authentication.scope.ChannelImpl;
Expand All @@ -21,6 +15,12 @@
import org.integratedmodelling.klab.services.application.ServiceNetworkedInstance;
import org.integratedmodelling.klab.services.base.BaseService;

import java.util.*;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;

/**
* This class is a wrapper for a {@link KlabService} whose main purpose is to provide it with a
* {@link ServiceScope} to run under. The default service scope is produced using a k.LAB user certificate, so
Expand All @@ -40,9 +40,8 @@
* <p>
* Once a {@link ServiceInstance} has successfully booted, the wrapped {@link KlabService} can be used through
* its API and is available through {@link #klabService()}. The {@link ServiceInstance} does not provide
* network controllers, which can be provided through the outer wrapper
* {@link ServiceNetworkedInstance} after defining the
* controllers using Spring.
* network controllers, which can be provided through the outer wrapper {@link ServiceNetworkedInstance} after
* defining the controllers using Spring.
* <p>
* TODO move all startup/shutdown notifications to the wrapper
*
Expand All @@ -51,6 +50,7 @@
public abstract class ServiceInstance<T extends BaseService> {

AtomicBoolean initialized = new AtomicBoolean(false);
AtomicBoolean operationalized = new AtomicBoolean(false);

private ServiceStartupOptions startupOptions;
private T service;
Expand All @@ -70,14 +70,24 @@ public abstract class ServiceInstance<T extends BaseService> {
private boolean firstCall = true;

/**
* Return the type of any <em>other</em> services required for this service to be online. For each of
* these the {@link #createDefaultService(KlabService.Type, Scope, long)} function will be called and
* online status won't be set until all of these are available.
* Return the type of any <em>other</em> services required for this service to become online. The service
* chain must not have circular dependencies in these requirements. When at least one of each required
* service is available, the {@link BaseService#initializeService()} function will be called on the
* service.
*
* @return
*/
protected abstract List<KlabService.Type> getEssentialServices();

/**
* The services returned here, which must not overlap those returned by {@link #getEssentialServices()},
* are needed for full operation but do not prevent initialization. When all the remaining services listed
* here are available,
*
* @return
*/
protected abstract List<KlabService.Type> getOperationalServices();

public Identity getServiceOwner() {
return identity == null ? null : identity.getFirst();
}
Expand All @@ -87,7 +97,8 @@ public Identity getServiceOwner() {
*
* @return
*/
protected abstract T createPrimaryService(AbstractServiceDelegatingScope serviceScope, ServiceStartupOptions options);
protected abstract T createPrimaryService(AbstractServiceDelegatingScope serviceScope,
ServiceStartupOptions options);

/**
* Called only if the service(s) specified in the certificate are unavailable or missing. This will be
Expand Down Expand Up @@ -230,7 +241,8 @@ public boolean start(ServiceStartupOptions options) {
case Community community -> {
currentServices.put(KlabService.Type.COMMUNITY, community);
}
default -> {}
default -> {
}
}

bootTime = System.currentTimeMillis();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,25 +92,27 @@ private void createServiceSecret() {
}
}

// /**
// * If this returns true, the service will instruct the {@link ScopeManager} to automatically create scope
// * hierarchies when scope headers are received for session and context scopes that are unknown, as long as
// * the request is not anonymous or is otherwise privileged. Default is false.
// *
// * @return true if scopes can be created automatically
// */
// public boolean isProvideScopesAutomatically() {
// return provideScopesAutomatically;
// }

// /**
// * Set the flag returned by {@link #isProvideScopesAutomatically()}.
// *
// * @param b
// */
// protected void setProvideScopesAutomatically(boolean b) {
// this.provideScopesAutomatically = b;
// }
// /**
// * If this returns true, the service will instruct the {@link ScopeManager} to automatically
// create scope
// * hierarchies when scope headers are received for session and context scopes that are unknown,
// as long as
// * the request is not anonymous or is otherwise privileged. Default is false.
// *
// * @return true if scopes can be created automatically
// */
// public boolean isProvideScopesAutomatically() {
// return provideScopesAutomatically;
// }

// /**
// * Set the flag returned by {@link #isProvideScopesAutomatically()}.
// *
// * @param b
// */
// protected void setProvideScopesAutomatically(boolean b) {
// this.provideScopesAutomatically = b;
// }


public EmbeddedBroker getEmbeddedBroker() {
Expand Down Expand Up @@ -234,9 +236,19 @@ public AbstractServiceDelegatingScope serviceScope() {
return scope;
}

/**
* Called when all the essential services are available. The non-essential "operational" services will
* not necessarily be available yet.
*/
public abstract void initializeService();

/**
* Called when all non-essential operational services become available.
*/
public abstract void operationalizeService();

@Override

public boolean shutdown() {
_scopeManager.shutdown();
return true;
Expand Down Expand Up @@ -326,7 +338,8 @@ public ExternalAuthenticationCredentials.CredentialInfo addCredentials(String ho
* @return the ID of the new session created at server side, or null in case of failure.
*/
public String registerSession(SessionScope sessionScope) {
return sessionScope instanceof ServiceSessionScope serviceSessionScope ? serviceSessionScope.getId() : null;
return sessionScope instanceof ServiceSessionScope serviceSessionScope ?
serviceSessionScope.getId() : null;
}

/**
Expand All @@ -342,7 +355,8 @@ public String registerSession(SessionScope sessionScope) {
* @return the ID of the new context scope created at server side, or null in case of failure.
*/
public String registerContext(ContextScope contextScope) {
return contextScope instanceof ServiceContextScope serviceSessionScope ? serviceSessionScope.getId() : null;
return contextScope instanceof ServiceContextScope serviceSessionScope ?
serviceSessionScope.getId() : null;
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ public void initializeService() {

}

@Override
public void operationalizeService() {

}

@Override
public ServiceCapabilities capabilities(Scope scope) {
// TODO Auto-generated method stub
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ protected List<KlabService.Type> getEssentialServices() {
return List.of(KlabService.Type.RESOURCES);
}

@Override
protected List<KlabService.Type> getOperationalServices() {
return List.of();
}

@Override
protected ReasonerService createPrimaryService(AbstractServiceDelegatingScope serviceScope, ServiceStartupOptions options) {
return new ReasonerService(serviceScope, options);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,11 @@ public void initializeService() {

}

@Override
public void operationalizeService() {

}

@SuppressWarnings("unchecked")
private void loadAuthority(ProjectConfiguration authority) {
if (authority.getUrl().startsWith("classpath:")) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ protected List<KlabService.Type> getEssentialServices() {
return List.of(KlabService.Type.RESOURCES);
}

@Override
protected List<KlabService.Type> getOperationalServices() {
return List.of();
}

@Override
protected ReasonerService createPrimaryService(AbstractServiceDelegatingScope serviceScope, ServiceStartupOptions options) {
return new ReasonerService(serviceScope, options);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ protected List<KlabService.Type> getEssentialServices() {
return List.of(KlabService.Type.REASONER, KlabService.Type.RESOURCES);
}

@Override
protected List<KlabService.Type> getOperationalServices() {
return List.of();
}

@Override
protected ResolverService createPrimaryService(AbstractServiceDelegatingScope serviceScope,
ServiceStartupOptions options) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -155,19 +155,12 @@ public String serviceId() {
*/
public Resolution computeResolution(Observation observation, ContextScope scope) {

var resolutionGeometry = scope.getConstraint(ResolutionConstraint.Type.Geometry,
observation.getGeometry());

var resolutionGeometry = ContextScope.getResolutionGeometry(scope);
if (resolutionGeometry == null || resolutionGeometry.isEmpty()) {
if (scope.getContextObservation() != null) {
resolutionGeometry = scope.getContextObservation().getGeometry();
}
if ((resolutionGeometry == null || resolutionGeometry.isEmpty()) && scope.getObserver() != null) {
resolutionGeometry = scope.getObserver().getObserverGeometry();
}
resolutionGeometry = observation.getGeometry();
}

if (resolutionGeometry == null) {
if (resolutionGeometry == null || resolutionGeometry.isEmpty()) {
return ResolutionImpl.empty(observation, scope);
}

Expand Down Expand Up @@ -355,8 +348,13 @@ private ResolutionImpl resolveStrategy(ObservationStrategy strategy, Scale scale
case OBSERVE -> {

/*
Find models and compile them in, merge resolutions until satisfied
Find models and compile them in, merge resolutions until satisfied. We pass the scale
through scope constraints.
*/
scope = scope.withResolutionConstraints(
ResolutionConstraint.of(ResolutionConstraint.Type.Geometry,
scale.as(Geometry.class)));

ret = new ResolutionImpl(operation.getObservable(), scale, scope, parent);
for (Model model : queryModels(operation.getObservable(), scope, scale)) {
ResolutionImpl resolution = resolveModel(model, operation.getObservable(),
Expand Down Expand Up @@ -881,6 +879,11 @@ public void initializeService() {

}

@Override
public void operationalizeService() {

}

@Override
public String encodeDataflow(Dataflow<Observation> dataflow) {

Expand Down
Loading

0 comments on commit 1647e13

Please sign in to comment.