-
Notifications
You must be signed in to change notification settings - Fork 7
MultiStepsJobPlugin
Welcome to our tutorial lesson 14 concerning the development of Orthanc plugins. In this lesson we enhance the OneStepJobPlugin
, developed in lesson 13, to execute multiple steps. To simulate the behavior of tasks doing hard work for a long time, we put the task in sleep mode during 10 seconds in each step. To simulate an error arriving during the execution of a real task, we generate a random number between 1 and 100 in each step. When the number exceeds a defined threshold, we throw a failure message.
In the MyJob.h header file we add two private member variables to the class MyJob:
float counter_
float maxSteps_
We initialize the counter_
with zero and increment it in each step. If the counter_
equals the maxSteps_
limit, the job is finished and stopped with a success message.
To generate the random number, we add an additional public method bool RandomGenerator()
to the class.
Here is the complete code of the MyJob.h header file.
#pragma once
#include <string>
#include <Plugins/Samples/Common/OrthancPluginCppWrapper.h>
class MyJob : public OrthancPlugins::OrthancJob {
std::string jobName_;
float counter_;
float maxSteps_;
public:
explicit MyJob(std::string jobType);
~MyJob();
OrthancPluginJobStepStatus Step();
void Stop(OrthancPluginJobStopReason reason);
void Reset();
bool RandomGenerator();
};
The MyJob.cpp file of the MultiStepsJobPlugin
contains more stuff than the corresponding file in the OneStepJobPlugin
.
We must include additional libraries to implement the random and sleep features. In the MyJob
constructor we must initialise the variables counter_
and maxSteps_
. We set the steps limit to 10.
In the Step()
function we check the value of the counter_
. If it equals maxSteps_
, we reset the counter_
to 0, update the job progress indicator with 1.0 and terminate the job with success
. If it equals zero, we initialise the random seed.
The RandomGenerator()
function is called and returns a boolean OK = true
value if the generated randon number is lower than 94. If true, the counter_
is incremented, the progress indicator is updated with the
fraction counter_ / maxSteps_
and the job is continued. If false, the job is terminated with a failure message.
The Stop()
function provides the reason for a job termination. Two reasons are obvious: success or failure. But a multisteps job, which takes some time, can be paused or cancelled. These are two additional stop reasons.
The following panel presents the whole code of the MyJob.cpp file.
#include <Plugins/Samples/Common/OrthancPluginCppWrapper.h>
#include <Core/Toolbox.h>
#include <Core/Logging.h>
#include <stdlib.h> /* srand, rand */
#include <time.h> /* time */
#include <string>
#include <thread>
#include "MyJob.h"
// constructor
MyJob::MyJob(std::string jobType)
:
OrthancPlugins::OrthancJob(jobType),
jobName_(jobType),
counter_(0.0),
maxSteps_(10.0) {
LOG(INFO) << "*** MyJob " << jobName_ << " constructor";
}
// destructor
MyJob::~MyJob() {
LOG(INFO) << "*** MyJob destructor";
}
OrthancPluginJobStepStatus MyJob::Step() {
if (MyJob::counter_ == MyJob::maxSteps_) {
MyJob::counter_ = 0;
MyJob::UpdateProgress(1.0);
Json::Value detailInfo;
detailInfo = Json::objectValue;
detailInfo["Project"] = "RadioLogic Tutorial MultipleStepsJob";
detailInfo["Author"] = "Marco Barnig";
MyJob::UpdateContent(detailInfo);
LOG(INFO) << "*** MyJob " << MyJob::jobName_ << " Step() Success";
return OrthancPluginJobStepStatus_Success;
} else {
if (MyJob::counter_ == 0) {
MyJob::UpdateProgress(0.0);
// initialize random seed
srand(time(0));
}
bool ok = MyJob::RandomGenerator();
if (ok == true) {
MyJob::counter_++;
MyJob::UpdateProgress(MyJob::counter_ / MyJob::maxSteps_);
LOG(INFO) << "*** MyJob " << MyJob::jobName_ << " Step() Continue";
return OrthancPluginJobStepStatus_Continue;
} else {
LOG(INFO) << "*** MyJob " << MyJob::jobName_ << " Step() Failure";
return OrthancPluginJobStepStatus_Failure;
}
}
}
void MyJob::Stop(OrthancPluginJobStopReason reason) {
switch (reason) {
case OrthancPluginJobStopReason_Success :
LOG(INFO) << "*** MyJob " << MyJob::jobName_ << " Stop() Success";
break;
case OrthancPluginJobStopReason_Paused :
LOG(INFO) << "*** MyJob " << MyJob::jobName_ << " Stop() Pause";
break;
case OrthancPluginJobStopReason_Failure :
LOG(INFO) << "*** MyJob " << MyJob::jobName_ << " Stop() Failure";
break;
case OrthancPluginJobStopReason_Canceled :
LOG(INFO) << "*** MyJob " << MyJob::jobName_ << " Stop() Cancel";
break;
default :
LOG(INFO) << "*** Job-Error: " << MyJob::jobName_ << " the stop-reason is out of enum range";
}
}
void MyJob::Reset() {
LOG(INFO) << "*** MyJob " << MyJob::jobName_ << " Reset()";
}
bool MyJob::RandomGenerator() {
std::this_thread::sleep_for(std::chrono::seconds(10));
// generate random number between 1 and 100
int randomNumber = rand() % 100;
LOG(INFO) << "*** Random Number: " << randomNumber;
if (randomNumber > 94) {
return false;
} else {
return true;
}
}
The MultiStepsJobPlugin.cpp is virtually identical to the OneStepJobPlugin.cpp. The only differences are the name of the job (MultiStepsJob
) and the callback URL /start-multiple-steps-job
.
Except the names, the CMakeLists.txt is identical to the same file of the OneStepJobPlugin
.
After 15 lessons, building and installing a plugin in the RadioLogicArchive has become a routine. Pointing the browser to the relative URL /start-multiple-steps-job
displays the following webpage:
The Jobs webpage lists our job now in the panel of the currently running jobs.
If we click inside the job panel, the general information about the job is shown, together with a Pause job
and a Cancel job
button.
Clicking the Pause job
button, the job is moved inside the pending jobs panel with the tag paused
.
Another click displays a panel with a Resume job
button to continue the job.
The next two figures show the inactive job panel with the successfully completed job and the panel with the general and detailed information about the job.
A job terminated with failure is shown in the next figure.
A failed job can be resubmitted in the general information panel. This works only for soft errors (for example temporary connection problems or transmission errors). Hard errors, caused by wrong filenames or missing data, can't be recovered. Our simulated failure with a random generator is a sort of soft error. Resubmitting our job has great chance to be successful. The job will continue at the step where it failed.
This time we don't want to explore the log files because there will be nothing new to discover. We keep all our energy for the next lesson. Be curious!