property DeleteTimeout as %Integer [ InitialExpression = 1 ];
When the work queue oref is killed or goes out of scope this is the timeout we pass to the call the destructor
makes to delete the work queue. The delete queue logic will wait for this timeout period for the worker/s to respond
but if the worker/s is/are still busy it will force these processes down.
property NumActiveWorkers as %Integer [ Calculated ];
For local WQM groups number of active workers attached to this group. If the system is at the limit
then we limit the number of worker jobs so you may need to wait for existing worker
jobs to become free in order to attach to your work group. If queue is
detached will return -1.
For local WQM group after the work group is created the number of workers allocated to this group.
Note this is the number of jobs we requested, not the number actively working for
this group at this moment. The active number is NumActiveWorkers.
Normally when a work group is deleted the delete/close is synchronous and so waits for all the worker jobs to finish
or be terminated before it returns to the caller. This means the caller can be sure all work has finished and it can
cleanup any temporary storage or resources the workers may have been using. This method allows you to specify a callback
to be run when the work group is fully deleted which makes the delete/close of the work group asynchronous. So when the
work group is deleted it can return immediately to the caller, but the caller can not assume all work has been terminated.
Some of the workers may still be finishing their work or may be in the process of being terminated, however once the
workers are stopped we will fully delete the work queue and run this 'Cleanup' callback. Note that this callback is not run
in a worker that we have called Setup() in.
Clear any existing work from this work queue, it does this by removing the queue and creating a new one.
This will wait for up to timeout seconds for the workers to finish their current task before killing
the jobs. When we return from this function all work on the group has terminated so you can cleanup any temporary
globals etc used by the workers.
Deprecated method implemented for compatibility with code used to calling 'Initialize' method but new users should call %New
to create an instance of this class.
If you queue a large number of units of work and there is some common setup needed by any process that will
run one of these units of work rather than having this setup work done for every work unit you can initalize the
worker process once with this method, then it can process any number of work units in this group and when it is done
it will run the TearDown(). So if you call this method for a work group we will ensure this Setup
entry point is called before the worker runs the first unit in this work group. This must be called before you queue
any work and the arguments are the same as for the Queue().
After work has been queued this will wait for all the workers to complete. It will display any output the work
writes to the current device and it will also combine all the %Status codes/exceptions that the units of work report and
return this combined %Status. If the work queue is created with no workers then this will execute all the work in the current job
during this phase. When this returns all the work queued up to this point has been completed (see Cleanup() for an exception).
This is the phase that will run the QueueCallback() callbacks as the workers jobs report that work
units are complete. In the function/method called in the QueueCallback() callback
you can reference the public variable '%workqueue' which is the oref pointing to the instance of the work queue class
to allow additional work to be queued.
This is a companion method to Setup() to restore a workers process to the previous state if
setup work was done.
The arguments are the same as for Queue(). This must be called before you queue work.
After work has been queued you can call this to process some work completion events and then return to the caller where the caller
will check the atend to see if all the work was processed and if not then you can call this method again
to process additional items until atend is true. atend will be true for the first time
when we have just received the last completion event for work that was queued.
The conditions which control when it will return to the caller are controlled by timeout argument which has a default of -1:
Positive number : Return to the caller after one work complete event is received or after the specified number of seconds has elapsed.
0 : Keep looking for work completion events until no completions are waiting, then return to the caller. Useful for polling to
check if all work has been completed but then going to do some other work in this process.
-1 : Requires a callback queued in QueueCallback(). In the callback set the public variable %exit to 1 to make this
'Wait' call return to the caller. If the %exit is not set we will continue to wait for additoinal completion events until all have been
received or until a callback sets %exit=1. This is the default
In the function/method called in the QueueCallback() callback
you can reference the public variable '%workqueue' which is the oref of the instance of the work queue class
in order to queue additional work.
Wait for one work unit to complete or we hit the timeout.
This is useful when you want to respond to individual completeion events in the parent process or you want to handle work unit errors
differently than WQM framework errors. If you only need to wait until all the work is completed then use the Sync().
Any errors in the WQM framework will be thrown as an exception which the caller should 'catch', in normal operation this will not occur.
The return value of the individual work unit or any errors thrown by running
the work unit are returned in the byref worksc %Status variable. If a timeout happens then we indicate this in the worksc
%Status variable as a error of $$$ERROR($$$MultiTimeout,timeout) error. You can check for this error code with 'If $$$ERRORISTYPE(sc,$$$MultiTimeout)'.
If a work unit was run then the array workargs is the argument list passed to the work unit, the first argument will be in workargs(1) and the second
argument will be in workargs(2) etc, so in the format when your function uses an 'workarg...' parameter. This provides context so you can understand any error
or other information the work unit has set.
When a work unit that is run sets result information into the public variable %result array this will be returned to the caller of WaitOne in the workresult byref array.
The method returns '1' to indicate it has either got a completion event or a timeout has occurred and '0' to indicate all completions have already been processed.
Any callback queued in QueueCallback() are run in this method in the same way they are for Sync() calls although when
using WaitOne there is no need for the callback mechanism.
Example use of this method is the following code. Any errors in WQM framework will be throw but return values from work units are returned in the workargs byref
value so they may be handled by the caller if wished.
Set queue=$system.WorkMgr.%New() If queue="" ; Report Error, can check %objlasterror for %Status code
For i=1:1:100 {
Set sc=queue.Queue("##class(MyClass).ClassMethod",i) If $$$ISERR(sc) ; Report Error
}
While queue.WaitOne(10,.sc,.args,.result) {
If $$$ISERR(sc) {
If $$$ERRORISTYPE(sc,$$$MultiTimeout) {
; Handle a timeout
} Else {
; Work unit returned %Status code or threw an expcetion, hanlde this here
}
} Else {
Write "Completed work unit ",args(1),! ; As we have access to the argument list provided on the 'Queue'
Zwrite result ; Any %result data from the work unit
}
}