Question
Kenneth Poindexter · Sep 30, 2017

Passing an array to a class method on a job command

hi-

Can someone give me an example of how to JOB a class method that requires an array of values to be passed to it by reference.  

This is what I tried, but am getting compile errors because of the .params

job ##class(%SYSTEM.OBJ.FM2Class).All(.params)::5

Any thoughts on how to accomplish this, the simplest way.  I would like to avoid writing all of this to some global and having to write some wrapper to pick it up and then call the class method, which I certainly could do.  but is this the only way to do it?

00
2 0 9 832
Log in or sign up to continue

Replies

Looking further, it would seem that we can not pass an array as an argument to a JOB command so I need to come up with a new way to get this array of parameters to the JOBed process.

If you know all possible arguments just create a wrapper method that accepts all arguments and job that.

Eduard, there are dozens.  params contains any number of values, not all required.

Thinking the easiest way may be to just save params to a subscripted global, job off a wrapper, passing the subscript.  Grab the array out of the global and then start the class method, killing the global.

 

Thanks Robert-

I dont think I have a choice here.  the All method of the %SYSTEM.OBJ.FM2Class expects the array to be passed by reference.  I did come up with a solution though....

/// Run FM2Class in background fo rnewly created namespace

ClassMethod ConfigFM2Class(Namespace As %String, LocalPath As %String) As %String
{
new $namespace set curnsp=$namespace,$namespace=Namespace
write !,"Starting FM2Class for Namespace ",Namespace," in background"
; Build Up Parameters
set params("childTableNameFormat")="SUB_<FILENAME>,<FILENUMBER>"
    set params("compile")=1
    set params("compileQSpec")="/display=all/lock=0"
    set params("dateType")="%Library.FilemanDate"
    set params("datetimeType")="%Library.FilemanTimeStamp"
    set params("deleteQSpec")="/display=all"
    set params("display")=0
    set params("expandPointers")=0
    set params("expandSetOfCodes")=0
    set params("extendedMapping")=""
    set params("fieldNameFormat")="Exact"
    set params("ienFieldName")="IEN"
    set params("logFile")=LocalPath_"fm2class_"_Namespace_".log"
    set params("nameLength")=180
    set params("owner")="_SYSTEM"
    set params("package")="VISTA"
    set params("readonly")=0
    set params("recursion")=2
    set params("requiredType")=0
    set params("retainClass")=1
    set params("setOfCodesEnum")=1
    set params("strictData")=0
    set params("superClasses")=""
    set params("tableNameFormat")="<FILENAME>,<FILENUMBER>"
    set params("variablePointerValueField")=0
    set params("wpIsList")=0
    kill ^UTILITY(Namespace,$j,"ISC.HealthConnect.Installer") merge ^UTILITY($j,"ISC.HealthConnect.Installer")=params
    set $namespace=curnsp
    job ##class(ISC.HealthConnect.Installer).jobfm(Namespace,$j)::5
set zSC=1
if '$t set zSC=0
quit zSC
}
ClassMethod jobfm(Namespace,job)
{
;Startup FM2Class
new $namespace set $namespace=Namespace
merge params=^UTILITY(job,"ISC.HealthConnect.Installer")
kill ^UTILITY(job,"ISC.HealthConnect.Installer")
do ##class(%SYSTEM.OBJ.FM2Class).All(.params)
quit

}

Definately agree.  Pretty sure my UTILITY global is mapped to CACHETEMP.

 

It's better to use CACHETEMP mapped global, e.g. ^CacheTempUserYourGlobal($job,...).

BTW there is another option: having a wrapper job, pass it an array serialized to JSON, other steps are evidient. I used it in one of my projects, and it was quicker than using of ^CacheTemp* intermediate global, while performance gain was not too sufficient (AFAIR)

The approach with a global is apparently easier, so I'd use it if performance would not of great importantance.

For passing array by reference try to use the class $system.WorkMgr instead of job.

Sample:

Class demo.test Abstract ]
{

ClassMethod Test(arrayAs %Status
{
  ^CacheTempUser.dbg
  ^CacheTempUser.dbg($zp)=array
  ^CacheTempUser.dbg($zp,"$j")=$j
  q $$$OK
}

}

demo()
  queue,arr

  arr(1)="qwe"
  arr(2)="asd"
  
  "$j = ",$j,!
  queue=$system.WorkMgr.Initialize("/multicompile=1",,1)
  queue.Queue("##class(demo.test).Test",.arr)
  queue.WaitForComplete()
  
  zw ^CacheTempUser.dbg
  q

Result:

USER>^demo
$j = 7600
^CacheTempUser.dbg(8488,1)="qwe"
^CacheTempUser.dbg(8488,2)="asd"
^CacheTempUser.dbg(8488,"$j")=8348

This was not the exact requirement i had. But using JOB there are issues handling files, specially in APPEND mode.

Using this workMgr, its fantastic. Its the best way to SPAWNS multiple jobs and get your work done.

A big THANK YOU! Save my last 2 weeks of effort.