public class Orchestrator extends Object
A task can be any POJO which can have any number of @Work or
@PassThru annotated methods, which we refer to as task methods.
Once added, execute() will execute those methods either if they have
no arguments or once those arguments become available as a result of
executing other tasks. A task method's arguments will never be null, so no
null checks are required in task methods. For any POJO added as a task,
either its @Work or its @PassThru method(s) will be
executed (never both), depending on whether it was added by
addWork(Object) or by addPassThru(Object).
@PassThru is intended for use when a task needs to do only simple
bookkeeping but otherwise is not actively contributing to the overall result.
Typically a given POJO will have just one @Work and possibly one
@PassThru method, but can have any number of these; at runtime,
whichever method matches based on available inputs will fire (execute).
An example pojo invoked with BascomTask might be as follows:
class MyTask {
@Work void exec(MyOtherTask x, SomeOtherTask y) {...}
}
Orchestrator orc = Orchestrator.create();
orc.addWork(new new MyTask());
orc.addWork(new new MyOtherTask());
orc.addWork(new new SomeOtherTask());
orc.execute();
If MyOtherTask and SomOtherTask have no common dependencies then they may be
executed in parallel in different threads. BascomTask is dataflow driven,
attempting to execute tasks in parallel where possible while avoiding
wasteful creation of threads where possible.
Multiple instances of a given POJO class can also be added, each being
executed separately and each being supplied to all downstream task methods
with that type as an argument. If two instances of MyOtherTask were added to
the previous example, each would start in its own thread and MyTask.exec()
would be invoked twice, each time with a different MyOtherTask instance. The
default behavior for a task that receives multiple calls is simply to allow
them to proceed independently each firing in turn to any downstream tasks.
This assumes that the task (MyTask in the above example) is thread-safe.
There are several options for varying this behavior by adding a scope
argument to @Work, see
Scope for a description of options.
Even simpler is to simply change a task argument to a list, in which case all
instances of that type will be received at once.
| Modifier and Type | Class and Description |
|---|---|
class |
Orchestrator.ExecutionStats |
| Modifier and Type | Method and Description |
|---|---|
ITask |
addConditionally(Object task,
boolean cond)
A convenience method, adds a task with a default name that is either
active or passive depending on the given condition.
|
ITask |
addIgnoreTaskMethods(Object task)
Adds an object without considering any @Work or
@PassThru methods even if they exist, as if the object did not
have such methods in the first place.
|
ITask |
addPassThru(Object task)
Adds a task whose @PassThru methods (rather than its
@@Work methods) will be invoked, always in the calling thread
-- no separate thread is created to execute a @PassThru method
since it assumed to perform simple actions like providing a default or
passing-through its arguments with no or little change.
|
ITask |
addWork(Object task)
Adds a task to be made available to other task's task (@Work
or @PassThru) methods, and whose own @Work methods
will only be invoked (fired) when its task arguments have so fired.
|
ITask |
asAdded(Object targetTask)
Returns the ITask wrapper for a POJO task that has already been added to this orchestrator
|
Orchestrator |
closureGenerator(ITaskClosureGenerator generator)
Sets a closure generator to use for this orchestrator, rather than the
default which is retrieved from whichever IBascomConfig is active.
|
static Orchestrator |
create() |
void |
execute()
Calls
execute(long) with a default from current
IBascomConfig.getDefaultOrchestratorTimeoutMs() |
void |
execute(long maxExecutionTimeMillis) |
void |
execute(long maxExecutionTimeMillis,
String pass)
Begins processing of previously added tasks within the calling thread,
spawning new threads where possible to exploit parallel execution and
returning when all no-wait tasks are finished.
|
void |
execute(String pass) |
String |
getGraphState()
Returns a newline-separated list of all calls of all tasks.
|
String |
getId()
Returns an id for this instance which has very low probability of
clashing with other ids.
|
String |
getName()
The name previously set by
name(String) |
Orchestrator.ExecutionStats |
getNoWaitStats()
Returns a snapshot of execution statistics resulting from a previous
execution, including any nowait tasks.
|
int |
getNumberOfOpenThreads()
Returns the number of threads that have been spawned but not yet
completed.
|
int |
getNumberOfThreadsCreated()
Returns the number of additional threads (not including the starting
thread) used in computing the result from this orchestrator.
|
Orchestrator.ExecutionStats |
getStats()
Returns a snapshot of execution statistics resulting from a previous
execution, excluding any nowait tasks.
|
TaskThreadStat |
getThreadStatForCurrentThread() |
Orchestrator |
name(String name)
Sets a name used on entry and exit debugging statements, useful for
identify which orchestrator is being invoked when there are many
involved.
|
void |
recordException(com.ebay.bascomtask.main.Call.Instance callInstance,
Exception e) |
void |
recordException(Exception e) |
String |
toString() |
public static Orchestrator create()
public Orchestrator.ExecutionStats getStats()
public Orchestrator.ExecutionStats getNoWaitStats()
public Orchestrator name(String name)
name - to include in debug statementspublic String getName()
name(String)public String getId()
public Orchestrator closureGenerator(ITaskClosureGenerator generator)
generator - to use in place of defaultIBascomConfig.getExecutionHook(Orchestrator,
String)public TaskThreadStat getThreadStatForCurrentThread()
public int getNumberOfThreadsCreated()
public int getNumberOfOpenThreads()
execute() if there are nowait tasks.public ITask addConditionally(Object task, boolean cond)
task - java POJO to add as taskcond - if true then add as active else add as passivepublic ITask addWork(Object task)
The rules for execution are as follows:
Regarding the last point, although it is common to add just one instance
of a given POJO type, it is safe to add any number. The default behavior
of @Work methods receiving argument sequences with multiple
instances is that each is executed potentially in parallel. Different
options can be set through @Work.scope, see
Scope. Alternatively,
a @{literal @}Work method parameter can simply be a
List of tasks in which case the entire set of matching
instances will be made available once all instances are available.
An added task will have no effect until execute(long) is called,
either directly or implicitly as a result of a nested task method
completing.
A @Work can return a boolean result or simply be void, which
equates to returning true. A return value of false
indicates that downstream tasks should not fire: any task fires only if
all of its inputs have fired, except for List
parameters, which never prevent firing but instead any false-returning
tasks will be excluded from the list (which means that a list parameter
may be empty).
task - java POJO to add as taskpublic ITask addPassThru(Object task)
addWork(Object).task - java POJO to add as taskpublic ITask addIgnoreTaskMethods(Object task)
task - to addpublic ITask asAdded(Object targetTask)
targetTask - to matchpublic void recordException(com.ebay.bascomtask.main.Call.Instance callInstance,
Exception e)
public void recordException(Exception e)
public void execute()
execute(long) with a default from current
IBascomConfig.getDefaultOrchestratorTimeoutMs()public void execute(String pass)
public void execute(long maxExecutionTimeMillis)
public void execute(long maxExecutionTimeMillis,
String pass)
Consistency checks are performed prior to any task being started, and if a violation is found a subclass of InvalidGraph is thrown.
If any task throws an exception, which would have to be a non-checked exception, it will be propagated from this call. Once such an exception is thrown, the orchestrator ceases to start new tasks and instead waits for all open threads to finish before returning (by throwing the exception in question).
maxExecutionTimeMillis - to timeoutpass - description passed to config executorsRuntimeException - generated from a taskRuntimeGraphError.Timeout - when the requested timeout has been
exceededRuntimeGraphError.Multi - if more than one exception is thrown from
different tasksInvalidTask.AlreadyAdded - if the same task instance was added more
than onceInvalidTask.BadParam - if a task method has a parameter that cannot
be processedInvalidGraph.MissingDependents - if a task cannot be exited because
it has no matching @Work dependentsInvalidGraph.Circular - if a circular reference between two tasks
is detectedInvalidGraph.MultiMethod - if a task has more than one callable
method and is not marked multiMethodOk()InvalidGraph.ViolatedProvides - if a task was indicated to
ITask.provides(Class) an
instance but this was not done (or @PassThru)
method that has all of its parameters available as instancespublic String getGraphState()
Copyright © 2018. All rights reserved.