Create task to run a business service just once

Hi,

I have a business service that needs to run only once a day at an specific time. It is important that the service only runs once.

I have tried the scheduler but you can only define the times (start-stop) when the service will be running...so this will not work for me as I need this to run only once.

Looking at the documentation I found "tasks". Apparently this is exactly what I need. As per documentation:

The recommended approach is to configure the business service with Pool Size = 0 and then use the Task Manager to launch a task that calls CreateBusinessService() on it and invokes ProcessInput() on the resulting service instance object. The advantage of calling a business service this way is that you call it at the time you want and it runs only once. If Ensemble happens to be down at that time, your task can register an error. 

The problem is that I have no idea how to create a new task. I can figure out how to add code to create the business service and invoke process input method...something like this:

Set tSC = ##class(Ens.Director).CreateBusinessService("service name",.tService)

If ($IsObject(tService)) {
   Set input = ##class(service class??).%New()
   Set input.Value = 22
   Set tSC = tService.ProcessInput(input,.output)
}

Anyone knows how can I create that task so I can add that code in?

Thanks

  • 0
  • 0
  • 430
  • 5
  • 2

Answers

An alternative solution that works for us is to use the "Schedule" setting to run it for 30m (to allow some leeway as the job takes a while), and then set the "Call Interval" setting to something very large like "999999". This is for an Inbound SQL adaptor. (If something goes wrong with this overnight run then we manually remove the "Schedule" setting and restart the Service. Once complete, we put back the setting ready for the next night.)

It worked. What I did is the following:

Start & stop with a few seconds diff. so the service runs but stop immediately.

START:WEEK-*-03T10:45:00

,STOP:WEEK-*-03T10:45:10

and use "Call Interval=999999999" so the following run during start/stop times is longer than that time so it will only run once.

Thanks

 ClassMethod  Createtask() As %Status
{

Set tStatus = $$$OK
Try 
{

Set tTaskName = "Task Name"
Set tTaskClass = "Task.Classname"
Set tTaskDesc = "Task Desc"

Set tSql="select ID from %SYS.Task where NameSpace = ? and TaskClass = ?"
Set tRS = ##class(%SQL.Statement).%ExecDirect(,tSql, $Namespace, tTaskClass)
If (tRS.%Next())
{
 "Updating Task: "_tTaskName
Set tTaskObj = ##class(%SYS.Task).%OpenId(tRS.ID)
}
Else 
{
"Creating Task: "_tTaskName
Set tTaskObj = ##class(%SYS.Task).%New()
}

Set tTaskObj.NameSpace = $Namespace
Set tTaskObj.Name = tTaskName
Set tTaskObj.TaskClass = tTaskClass
Set tTaskObj.Description = tTaskDesc
Set tTaskObj.RunAsUser = "_system"
//Run task daily at 2 am
Set tTaskObj.TimePeriod = tTaskObj.TimePeriodDisplayToLogical("Daily")
Set tTaskObj.TimePeriodEvery = 1 // Every day (7 days a week)
Set tTaskObj.DailyFrequency = tTaskObj.DailyFrequencyDisplayToLogical("Once") // Run once daily
Set tTaskObj.DailyStartTime = (60*60*2) // 2:00am

"Saving task"
Set tStatus = tTaskObj.%Save()
$$$ThrowOnError(tStatus)

"Saved task ID: "_tTaskObj.%Id()

Do $SYSTEM.Task.Resume(tTaskObj.%Id())
 
}
Catch ex {
Set tStatus = ex.AsStatus()
}
Quit tStatus
}

Thanks for your quick response.

As far as I can understand, that code is to create the task...and that can be done in ensemble as in ..."System Operation/Task Manager/New Task". The problem is that when creating the task you must specify a "Task Type" and there is no way that those types can be created easily...a part from in Studio.  In the "New Task" screen I can read the following:

For user-defined tasks you must first create a new subclass of the %SYS.Task.Definition class which will then be selectable as a 'Task type'.

Which means there is a way to create a class that creates a "Task Type" that later can be selected when creating a new task. But this is my problem. I don't know how to create that class and if needs to be stored in a specific location for ensemble to get that new type.

Thanks

Task Type in UI is nothing but the Class in which you are wrapping your code.

Class Task.Classname Extends %SYS.Task.Definition

{

Set tSC ##class(Ens.Director).CreateBusinessService("service name",.tService)

If ($IsObject(tService)) {
   Set input ##class(service class??).%New()
   Set input.Value = 22
   Set tSC tService.ProcessInput(input,.output

}

}

Here's a sample task.

tl;dr:

  • Should extend %SYS.Task.Definition
  • Parameter TaskName = "TASK NAME";
  • OnTask method is called once every time the task is run
  • Class properties become task parameters