Kernel 8.0 APIs Banner
Office of Information and Technology (OIT) Banner
[skip navigation]

^%ZTLOAD: Queue a Task

Reference Type: Supported, Category: TaskMan, ICR#: 10063

Description

^%ZTLOAD is the main API used to create and schedule tasks (commonly referred to as "queuing"). Queuing tells TaskMan to use a background partition to DO a certain API at a certain time, with certain other conditions established as described by the input variables.

The ^%ZTLOAD API, as used in code, behaves consistently so most queuers strongly resemble one another. The queuer can be written so that it is either interactive with the user or so that it is not interactive. The standard variations on this structure deserve attention.

Format

  ^%ZTLOAD

Make sure to perform the following steps before calling this API:

  1. NEW all non-namespaced variables.

  2. Set all input variables.

  3. Call the API.

Input Variables

ZTRTN:

(required) The API TaskMan will DO to start the task. You can specify it as any of the following:

  • "LABEL^ROUTINE"

  • "^ROUTINE"

  • "ROUTINE"

If it is not passed, the original API is used.

ZTDESC:

(required) Task description, up to 200 characters describing the task, with the software application name at the front. While not required, use of this variable is recommended.

ZTDTH:

(optional) Start time when TaskMan should start the task. It must be a date and time in VA FileMan or $HOROLOG format. Setting it to @ causes the task to be created but not scheduled. If ZTDTH is not set, ^%ZTLOAD asks the user for the start time.

ZTIO:

(optional) The I/O device the task should use. If ZTIO is NULL, no device is used. If undefined, the current I/O variables is used to select a device. ZTIO should only be used when the current I/O variables do not describe the needed device. If you do not need a device for a job, SET ZTIO="". The ZTIO variable accepts the same I/O formatting string as the IOP variable in the ^%ZIS API.

REF: For more information, see the "Device Handler: Developer Tools" section in the Kernel 8.0 & Kernel Toolkit 7.3 Developer's Guide.

ZTUCI:

(optional) UCI the task should use. The current UCI is used if ZTUCI is undefined.

ZTCPU:

(optional) Volume Set:CPU. Specifies the name of the volume set and CPU on which the task should run. The volume set can be passed in the first :-piece, and the CPU in the second. Neither piece of information is required; either can be passed without the other. If the CPU alone is passed, it must still be preceded by a ":" (e.g., :KDAISC6A1). If the volume set is not passed, TaskMan runs the task on the volume set it came from or on a print server. If the CPU is not passed, TaskMan runs the task on the CPU where TaskMan resides. Any volume set and/or CPU specified by the task's I/O device takes precedence over the same information passed here.

NOTE: On Caché systems, specifying which CPU a job should run on only works if you are running TaskMan from a DCL context. If you specify the CPU, but are not running TaskMan from a DCL context, the job may not run correctly.

ZTPRI:

(optional) The CPU priority the task should receive. It should be an integer between 1 (low) and 10 (high). The site's default for tasks is used if this is undefined.

ZTSAVE():

(optional) Input variable array. An array whose nodes specify input variables to the task beyond the usual set all tasks receive. There are four kinds of nodes this array can have:

  • ZTSAVE("VARIABLE")—Set equal to NULL or to a value.

    • If NULL, the current value of that variable is copied for the task.

    • The variable is created with the value assigned [e.g., ZTSAVE("PSIN")=42].

    The variable can be local or global, and it can be a variable or an individual array node.

  • ZTSAVE("OPEN ARRAY REFERENCE")—Set to NULL to declare a set of nodes within an array to be input variables to the task
    [e.g., ZTSAVE("^UTILITY($J,")].

  • ZTSAVE("NAMESPACE*")—Set to NULL to save all local variables in a certain namespace [e.g., ZTSAVE("LR*")].

  • ZTSAVE("*")—Used to save all local variables. Non-namespaced variables (esp. %, X, Y, etc.) may or may not be saved. Saving individual variables is more efficient. ZTSAVE nodes are saved just as they are typed, so special variables like $J have one value when used to save the variables, and a different value when used to restore them for the task.
ZTKIL:

(optional) KEEP UNTIL. Set this to the first day the Task File Cleanup can delete this task. It should be a date and time in VA FileMan or $HOROLOG format. Use of this variable is recommended when ZTDTH equals @.

ZTSYNC:

(optional) Name of a SYNC FLAG. Using SYNC FLAGs allows TaskMan to run the next task in a series of tasks only if the preceding task in the series completed successfully.

You can choose any name for a SYNC FLAG. You should namespace the name, however, and make it no longer than 30 characters in length.

To use SYNC FLAGs, the task must be queued to a device of type resource (through the ZTIO variable).

REF: For complete information on how to use SYNC FLAGs, see the "Using SYNC FLAGs to Control Sequences of Tasks" section in the Kernel 8.0 & Kernel Toolkit 7.3 Developer's Guide.

Output Variables

ZTSK:

(Usually returned) The task number assigned to a task, returned whenever a task is successfully created. It can be used as an input variable to the other TaskMan application mode APIs.

NOTE: If a task is queued to a volume set other than the one where it was created, it is usually assigned a new task number when it is moved.

If ZTSK is not defined after calling ^%ZTLOAD, either ZTRTN was not set up or the user canceled the creation when prompted for a start time. If a task is not created and if ^%ZTLOAD is being called by a foreground job, then ^%ZTLOAD displays a message to the user indicating that the task has been canceled.

NOTE: ZTSK is not a system variable. It is KILLed and manipulated in many places. If the software needs to remember a task number, ZTSK should be set into some properly namespaced variable the application can protect.

ZTSK("D"):

START TIME (usually returned) contains the task's requested start time in $HOROLOG format. It is returned whenever ZTSK is returned, and gives you a way to know the start time a user requests.

Interactive Use of ^%ZTLOAD

The VistA Standards and Conventions (SAC) require that anywhere you let a user pick the output device you also let the user choose to queue the output.

Often, one part of the queuer is a call to ^%ZIS (the Device Handler). When you set up the variables for your call, include a Q in the variable %ZIS, so the Device Handler lets the user pick queuing. After the Device Handler call [and after you check POP to ensure that a valid device was selected), you can check $DATA(IO("Q")] to see whether the user chose to queue to that device. If so, then you must queue the printout you were about to do directly, and your software should branch to the code to set up the task. A sample of the code for this kind of print queuer looks something like this:

SELECT	;select IO device for report
		S %ZIS="Q" D ^%ZIS
		I POP D CANCEL Q
		I $D(IO("Q")) D QUEUE Q
		D PRINT,^%ZISC Q
		;
QUEUE 	;queue the report
		S ZTRTN="PRINT^ZZREPORT"
		S ZTDESC="ZZ Application Daily Report 1"
		S ZTSAVE("ZZRANGE")=""
		D ^%ZTLOAD
		I $D(ZTSK)[0 W !!?5,"Report canceled!"
		E  W !!?5,"Report queued!"
		D HOME^%ZIS Q

The code to set up the task after the call to ^%ZIS has four steps:

  1. Set the ^%ZTLOAD input variables to define the task.

  2. Call ^%ZTLOAD to queue the task.

  3. Check $DATA(ZTSK)#2 to find out whether a task was really queued and provides appropriate feedback.

  4. Call HOME^%ZIS API to reset its IO variables.

NOTE: This queuer did not define ZTIO. Print queuers can take advantage of the fact that they directly follow a ^%ZIS call that sets up all the IO variables they need. Under these conditions, the queuer code can rely on ^%ZTLOAD to identify the task's IO device from the IO variables; thus, saving the developer the work of building the correct ZTIO string.

Notice also that when queuing output, we need not call ^%ZISC to close the IO device, because when the user chooses to queue output the Device Handler does not open the device. Thus, all we need to do here is reset our IO variables with a HOME^%ZIS call.

As usual in these kinds of queuers, we did not define ZTDTH, but instead let ^%ZTLOAD ask the user when the report should run.

Finally, notice that we tell the task to begin at PRINT, the same tag used by the trigger code to start the foreground print when the user chooses not to queue. Under most circumstances, print queuers can use most of the same code for their tasks that the foreground print uses.

Non-Interactive Use of ^%ZTLOAD

Under certain conditions, queuers must create and schedule their tasks with no interaction with the user. Examples include queuers operating out of tasks or queuers that need to run without the users' knowledge. Only two items must be changed from interactive queuers to make non-interactive queuers work:

  1. ZTDTH must be passed to ^%ZTLOAD, and must contain a valid date/time value.

  2. If the code to queue the task does not follow a call to ^%ZIS, you must define the ZTIO variable yourself. Either set it, or allow it to be built from the current I/O variables (if those I/O variables describe the proper device).

After the call to ^%ZTLOAD, you may (or may not) want to issue feedback messages.

Queuing Tasks Without an I/O Device

Certain tasks need no IO device. These include primarily tasks that rearrange large amounts of data but produce no report, such as filing and compiling tasks. Two different kinds of non-IO tasks exist:

Queuers for concurrent non-IO tasks need only set ZTIO to NULL, and TaskMan runs the task, with no IO device.

For sequential non-IO tasks, queuers must set the ZTIO variable to the name of a resource type device. TaskMan then ensures that the tasks run single file, one after the other in order by requested start time. Applications that need sequential non-IO tasks should instruct system managers in the Package Installation Guide to create a resource device with the desired characteristics so that these queuers can safely queue their tasks to them. Such devices should be namespaced by the software application that uses them. SYNC FLAGs can also be used to allow the next task in a series to start only if the previous task in the series completed successfully.

REF: For more information on SYNC FLAGs, see the "Using SYNC FLAGs to Control Sequences of Tasks" section in the Kernel 8.0 & Kernel Toolkit 7.3 Developer's Guide.

Example

This example is a job that consists of gathering information and then printing it. Assume that the gathering takes a few hours. You do not want the device that the user selects to be tied up for that time, so you divide the job into two tasks.

  1. The first task gathers the information.

  2. The second task prints it.

Use the following APIs:

  1. ^%ZIS API to select the device.

  2. ^%ZTLOAD API to queue the print task.

  3. ^%ZTLOAD API to schedule the gather task.

  4. REQ^ZTLOAD API to schedule the print task when the gather task finishes.

NOTE: This process is made easier by using the $$QQ^XUTMDEVQ and $$REQQ^XUTMDEVQ APIs.

Sample Code

ARHBQQ   ;SFVAMC/GB - Demo of 'gather' and 'print' in 2 tasks ;1/19/06  08:31
         ;;1.1
ZTLOAD   ;
         N ARH,ARHZTSK,X,ZTSAVE,%ZIS,ZTSK,ZTDTH,ZTRTN,ZTDESC,ZTIO,POP
         W !,"Queue the second task (the print task) first.",!
         ;Let's deal with the second task first.
         ;The user doesn't know it, but he's actually queuing the second task,
         ;the "print" portion of the job.  The only question the user will be
         ;asked is to select the device.
         ;
         S %ZIS="QM"
         S IOP="Q" ;Force queuing.
         D ^%ZIS Q:POP  ; Select Device
         W !,"Finished with %ZIS."
         ;
         S ZTDTH="@" ;Don't schedule the task to run, we'll do it later
         ;If we didn't need to set ZTDTH, we could use EN^XUTMDEVQ, but that
         ;API 'new's ZTDTH, so we can't set it.
         ;
         ;BTW, Did you know that there's a 5th parameter in EN^XUTMDEVQ?
         ;Usually, EN^XUTMDEVQ will 'new' ZTSK, so you can't get to it.
         ;If you put "1" as the 5th parameter, ZTSK will exist when EN returns.
         ;D EN^XUTMDEVQ("PRINT^ARHBQQ","ARHB Print",.ZTSAVE,.%ZIS,1)
         ;
         S ZTRTN="PRINT^ARHBQQ"
         S ZTDESC="ARHB Print"
         D ^%ZTLOAD
         D HOME^%ZIS
         W !,"ZTSK=",$G(ZTSK)
         Q:'$D(ZTSK)
         S ARHZTSK=ZTSK
         ;
         N ZTSAVE,%ZIS,ZTSK,ZTDTH,ZTRTN,ZTDESC,ZTIO,IOP
         W !,"Now queue the first task (the gather task).",!
         ;Now queue the first task, the "gather" portion of the job.
         ;Since we don't need a device,
         ;the user will only be asked when to start the task.
         ;(I wasn't able to get EN^XUTMDEVQ to work for me.  I tried setting
         ;IOP="Q;" to let it know that it should be queued and it didn't need
         ;a device, but it did nothing, and returned a null ZTSK.)
         F I="ARHZTSK" S ZTSAVE(I)="" ; Save the ZTSK of the "print" task.
         S ZTIO="" ; We don't need a device.
         S IOP="Q" ; Force queuing.
         S ZTRTN="GATHER^ARHBQQ"
         S ZTDESC="ARHB Gather"
         D ^%ZTLOAD
         D HOME^%ZIS
         W !,"ZTSK=",$G(ZTSK)
         Q
GATHER   ;
         N ARHJ
         S ZTREQ="@"
         S ARHJ="ARHB-QQ"_"-"_$J_"-"_$H ; namespace + unique ID
         K ^XTMP(ARHJ) ; Use ^XTMP to pass a lot of data between tasks.
         S ^XTMP(ARHJ,0)=$$FMADD^XLFDT(DT,1)_U_DT ; Save-thru and create dates.
         S ^XTMP(ARHJ)="HI MOM!" ; Pretend this is a lot of data.
         D SPRINT
         Q
SPRINT   ; Now schedule the "print" task to run.
         N ZTSK,ZTDTH,I,ZTRTN,ZTDESC,ZTIO,ZTSAVE ; Very important to NEW the
         ; input variables to REQ^%ZTLOAD, otherwise they retain the values of
         ; the currently running task, and you could unintentionally change the
         ; "print" task to rerun the "gather" task.
         F I="ARHJ" S ZTSAVE(I)="" ; Let the "print" task know the "$J" value.
         S ZTSK=ARHZTSK
         S ZTDTH=$H
         D REQ^%ZTLOAD
         ;Instead of the above 8 lines we could have simply:
         ;S X=$$REQQ^XUTMDEVQ(ARHZTSK,$H,"ARHJ")
         Q
PRINT    ;
         S ZTREQ="@"
         U IO ; Don't need this if invoked using a ^XUTMDEVQ API.
         W !,"The secret message is: '",$G(^XTMP(ARHJ)),"'"
         K ^XTMP(ARHJ)
         Q

Code Execution

VAH>D ZTLOAD^ARHBQQ
     
Queue the second task (the print task) first.
QUEUE TO PRINT ON
DEVICE: HOME// P-MESS

 1 P-MESSAGE-ENGWO-HFS-VXD   HFS FILE ==> MAILMESSAGE
 2 P-MESSAGE-HFS-VXD   HFS FILE ==> MAILMESSAGE
Choose 1-2> 2 <Enter>  P-MESSAGE-HFS-VXD  HFS FILE ==> MAILMESSAGE

Subject: MY PRINT

     Select one of the following:

          M         Me
          P         Postmaster

From whom: Postmaster// <Enter>
Send mail to: XUUSER,ONE// <Enter>  XUUSER,ONE
Select basket to send to: IN// <Enter>
And Send to: <Enter>
Finished with %ZIS.
ZTSK=2921497
Now queue the first task (the gather task).

Requested Start Time: NOW// <Enter>  (JAN 25, 2005@11:30:35)
ZTSK=2921499

Output

Subj: MY PRINT  [#28881111] 01/25/05@11:30  2 lines
From: POSTMASTER (Sender: XUUSER,ONE - COMPUTER SPECIALIST)  In 'IN' 
basket.
Page 1  *New*
-------------------------------------------------------------------------------

The secret message is: 'HI MOM!'

Enter message action (in IN basket): Ignore//