Question
· Nov 21, 2023

Scheduled task or scheduled message to run a BPL

How do we trigger a BPL Business Process on a time schedule?

We are building a production that takes a steady stream of (HL7) lab results messages, processes them and stores them in a temporary database table. At scheduled points during the day (eg 0800, 1300, 1600) the database is queried and messages sent on to the downstream system. Aiming that the Processes to be implemented in BPL if possible - but we are having trouble triggering code in a BPL as a scheduled job.

We can get an ObjectScript class method to be run via the Task Manager - but we are not clear how to pass control into the BPL business process. We also wondered about having a blank message triggered somehow which then initiated the BPL... but not sure how to do that either.

Any suggestions welcome!

(If using BPL isn't possible, it would be useful to know that so we can crack on with implementing directly in ObjectScript.)

Product version: Ensemble 2018.1
$ZV: Cache for Windows (x86-64) 2018.1 (Build 184U) Wed Sep 19 2018 09:09:22 EDT
Discussion (12)3
Log in or sign up to continue

Hello @Colin Brough 

Can you try is this approach is suitable. Create a Business Service with Ens.InboundAdapter or without adapter. Call your BPL process as usual interoperability production flow.  Eventually Create your custom Task and invoke your Business service from the OnTask Inherited Method

Class HL7Task.Test Extends %SYS.Task.Definition
{
Method OnTask() As %Status
{
    Set status =  $$$OK
    Try {
        #dim service As Ens.BusinessService 
        Set status = ##class(Ens.Director).CreateBusinessService("HL7.Feed.TriggerService",.service)
        if $isobject(service) {
            do service.OnProcessInput(pInput,.pOutpt)
        }
    }
    Catch(ex) {
        Set status = ex.AsStatus()
    }
    return status
}
}

Business service

Class HL7.Feed.TriggerService Extends Ens.BusinessService
{

Parameter ADAPTER = "Ens.InboundAdapter";
Property TargetConfigName As Ens.DataType.ConfigName;
Parameter SETTINGS = "TargetConfigName:Basic";
Method OnProcessInput(pInput As %RegisteredObject, Output pOutput As %RegisteredObject) As %Status
{
	Do ..SendRequestSync(..TargetConfigName,pInput,.pOutput)
	Quit $$$OK
}

}

Thanks @Ashok Kumar , with a bit of tweaking that got us to where we needed to go. For clarity for anyone coming along and reading this later the steps would be:

  1. Create the BPL Business Process you want to call - at least have something in place you can call
  2. Create the HL7Task.Test class in ObjectScript from the example above - renamed as appropriate. The argument to CreateBusinessService is the name in the Production of the Service you will be calling (created below). Also you need to set pInput as a class suitable for use as a request, such as Ens.Request or (we used for an example) Ens.StringContainer
  3. Create the HL7.Feed.TriggerService class in ObjectScript from the example above, renamed as appropriate. 
  4. In the Production, create a new service (whose name is that used in step 2), and whose class is the one created in step 3. Set the TargetConfigName on the service to the name of the BPL. Set the Pool Size to zero.
  5. Create a new scheduled task - run it in the appropriate namespace, and pick the class name from step 2 in the Task Type dropdown - and schedule as appropriate.

Once all this is in place, you can call a BPL Business Process from a scheduled task.

do service.OnProcessInput(pInput,.pOutpt)

You are not supposed to call the OnProcessInput() callback method directly, instead the ProcessInput() method should be called.

Sometime calling OnProcessInput() works, sometimes create problems.

I think InterSystems should have made OnProcessInput() [private] as most of the callback methods (like %OnNew() for instance).

Enrico

Can I clarify: "Run at a scheduled time" could mean either:

  1. Run during a designated period of time, thus making the service / business process available to be triggered at anytime during that period but not outside that period, or
  2. Run once at a specific time, and never otherwise be triggered.

We are interested in the second of these - we want a batch job to run at 0800, at 1300, and at 1600 each day. When it runs it will scoop all the current labs results out of the database table where they have been accumulating, and send them on to the downstream system.

@Colin Brough , Documentation sys  (https://docs.intersystems.com/healthconnect20211/csp/docbook/DocBook.UI....)   - "When it is time to start, if the item is enabled, the scheduler starts it; when it is time to stop, if the item is running, the scheduler stops it."

Production item will active between start and end time but it is can be controlled (to some extent) by the production component implementation.  We have a service that process files from a folder using the file adapter and it is using the schedule functionality. Schedule is set to start at 22:00 and stop at 23:00. Everyday service start at 22:00 and once it finish processing all files from the folder it remain inactive until next day 22:00. In our case since the file copy to the folder from external system only happens during the day time, when the service is started it is same as running service just once between 22:00 and 23:00. 

Hope that helps. 

Thanks, helpful to explore another potential option. If I'm reading https://docs.intersystems.com/iris20233/csp/docbook/DocBook.UI.Page.cls?... correctly then we'd need to use the OnProductionStart method of the business process to run when the job is scheduled - and not sure that's obviously accessible in a BPL business process. There are otherwise no incoming messages to trigger action.

Hi. It's been a long time since I dealt with this, but when I was trying to get a stats extract to run once a day I used ADAPTER = "Ens.InboundAdapter" (with some custom params for which operation to send to and an email address) and in the production set up a schedule as described above to define a run for a few minutes each day, but then defined CallInterval as 999999. Thus it ran once at start of interval, and not again. I don't know if it was the best solution, but it seemed to work and kept the schedule visible in the production should we need to change it. The service just did queries on the cache database, but you could use a SQL adapter to query other databases.

update - just found that I actually used that same trick for middle of the night SQL extractions (mass update of medical instrument reference data).

and looking back at the original question: the answer is that in the ideal solution (not always the best) things should not "magically" appear in the middle of a BPL, there should be a service starting from the left sending stuff to the right in a visible path, even when the input is from "inside" the system. So here you might need that SQL adapter reading rows and sending a message per row. (Though the solution might get a lot more complex, I know mine did, with special message objects, streams and stored procedures!)