Common-scope

From Gcube Wiki
Revision as of 19:13, 18 April 2013 by Fabio.simeoni (Talk | contribs) (Created page with '{| align="right" || __TOC__ |} '''common-scope''' is a client library that provides facilities to manage the scope of calls to gCube services, including: * facilities to propag…')

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

common-scope is a client library that provides facilities to manage the scope of calls to gCube services, including:

  • facilities to propagate scope across client components and across threads in which those components execute;
  • facilities to inspect scopes;
  • facilities to discover endpoints of key services that operate in given scopes;

common-scope is available in our Maven repositories with the following coordinates:

<groupId>org.gcube.core</groupId>
<artifactId>common-scope</artifactId>
<version>...</version>

The library depends on common-scope-maps, a bundle of configuration files that provide common-scope with the addresses of of key middleware services that operate in given scopes.

Introduction

Endpoints of gCube services may operate on behalf of different groups of users. Since they may leave different traces for different groups, clients must mark their requests with an indication of the scope in which the endpoints should satisfy them. And since clients are often service endpoints in turn, there is a general requirement for propagating scope information across chains of service calls, starting from an original client request:

For example, a user logs in the portal to operate in the scope of a given group. He then triggers through the GUI a request for a front-end service (portlet), which discovers and calls a back-end service that operates in the same scope. This service may discover and call in turn another back-end service that operates in that scope, and so on until the original request is satisfied.

The requirement of scope propagation risks to intrude heavily in the design of all clients involved in a call chain. In the worst case, it may require clients to pass scope information across all the local components that are involved in the chain. common-scope offers facilities to limit this intrusion. The idea is that the first client component that becomes aware of the scope for the next outgoing requests places it in a shared context, as the current scope. Components that execute thereafter can ignore the existence of a current scope, except for components that needs to retrieve it from the shared context and mark outgoing requests with it. '

Overall, the idea is to require explicit scope handling only at the boundaries of the client's runtime. Components that operates at such boundaries are scope-aware, and may not know each other: those that set the current scope do so in the assumption that others will later retrieve it; those that retrieve it assume that others will have set it earlier. Components that operate instead inside the runtime's boundaries are instead scope-free, i.e. can ignore the existence of a scope and its requirements.

Scope-aware components can and usually are provided by general-purpose client libraries. For example, common-gcore-stubs provides components that set the current scope on outgoing requests made through the Featherweight Stack. Similarly, the gCube Application Framework (gCF) provides components that take the scope that marks incoming request to gCore services and sets is as the current scope.

Accordingly, many clients can remain by and large scope-free. In what follows, we address the subset of scope-aware components and discuss how common-scope helps managing scope.

Scope

A scope can be:

  • an entire e-Infrastructure. Syntactically, we represent it with a name, e.g. research-infrastructures.d4science.eu;
  • a Virtual Organisation (VO) within an e-Infrastructure. Syntactically, we represent it with the name of the e-Infrastructure and the name of the VO, separating the two with a forward slash, e.g. research-infrastructures.d4science.eu/FARM;
  • a Virtual Research Environment (VRE) within a VO. Syntactically, we represent it with the name of the e-Infrastructure of the VO, the name of the VO, and the name of the VRE, e.g. . research-infrastructures.d4science.eu/FARM/VRE.

Names are agreed upon and, clearly, cannot contain forward slashes.


'Note: the conditions under which clients and services operate in given scopes are independent from scope management requirements, and we will not discuss them here.


In code, common-scope models scopes as plain Strings, e.g.:

String scope = “a/b/c”;

Scope-aware components that need to analyse scopes can wrap Strings in ScopeBeans and use their APIs:

import org.gcube.common.scope.impl.ScopeBean;
import org.gcube.common.scope.impl.ScopeBean.Type;
 
ScopeBean scope = new ScopeBean(“a/b/c”);
assert(scope.is(Type.VRE));
assert(scope.type()==Type.VRE);
assert(scope.name().equals(“c”));
assert(scope.enclosingScope().name().equals(“b”));
assert(scope.toString().equals(“a/b/c”));

Scope Provider

common-scope offers a ScopeProvider as a repository for the current scope. Scope-aware components can set the current scope as follows:

import org.gcube.common.scope.api.ScopeProvider
 
ScopeProvider.instance.set(“a/b/c”);

Similarly, scope-aware components can retrieve the current scopes as follows:

String scope =ScopeProvider.instance.get();

In rare cases, scope-aware components may want to delete the current scope:

ScopeProvider.instance.reset();

Default Scope Provider

ScopeProvider is an interface. When the constant ScopeProvider.instance is first accessed, common-scope looks for an implementation of the interface on the classpath (using Java's ServiceLoder mechanism). If it finds none, it sets the constant to an instance of a default implementation, DefaultScopeProvider.

DefaultScopeProvider binds scope to threads, i.e. treats it as thread-local information. In particular, it:

  • stores the current scope in a InheritableThreadLocal. This means that the current scope propagates transparently to child threads. E..g:
final Scope scope = …
 
ScopeProvider.instance.set(scope);
 
new Thread() {
 
    public void run() {
 
       assert(scope.equals(ScopeProvider.instance.get());
    }
 
}
  • retrieves the current scope from the system property gcube.scope if none is associated with the current thread or its ancestors. This means that clients that operate in a statically known scope can configure the runtime for it, with no need to designate a scope-aware component to set it.

Scoped Tasks

The DefaultScopeProvider allows clients to remain scope-free even when they spawn new threads. Most commonly, however, clients will abstract over threads and send Callable or Runnable tasks to Java's ExecutorServices that preallocate thread pools to their executions. Since pooled threads are not necessarily in a parent-child relationship with the threads from which clients submits their tasks, the inheritance mechanisms of the DefaultScopeProvider cannot transparently propagate the scope. Clients must then become scope-aware, though common-scope offers facilities to limit this awarenes