changeset 2566:c09ce3c038fc jobs

improved handling of eta
author Sebastien Jodogne <s.jodogne@gmail.com>
date Mon, 07 May 2018 13:51:23 +0200
parents 0f06b4d5b3d0
children 3caca43371f5
files UnitTestsSources/MultiThreadingTests.cpp
diffstat 1 files changed, 115 insertions(+), 23 deletions(-) [+]
line wrap: on
line diff
--- a/UnitTestsSources/MultiThreadingTests.cpp	Mon May 07 13:20:29 2018 +0200
+++ b/UnitTestsSources/MultiThreadingTests.cpp	Mon May 07 13:51:23 2018 +0200
@@ -393,7 +393,7 @@
 
   public:
     JobStatus() :
-      errorCode_(ErrorCode_Success),
+      errorCode_(ErrorCode_InternalError),
       progress_(0),
       description_(Json::objectValue)
     {
@@ -442,7 +442,9 @@
     JobState                          state_;
     boost::posix_time::ptime          timestamp_;
     boost::posix_time::ptime          creationTime_;
+    boost::posix_time::ptime          lastStateChangeTime_;
     boost::posix_time::time_duration  runtime_;
+    bool                              hasEta_;
     boost::posix_time::ptime          eta_;
     JobStatus                         status_;
 
@@ -452,18 +454,30 @@
             JobState state,
             const JobStatus& status,
             const boost::posix_time::ptime& creationTime,
+            const boost::posix_time::ptime& lastStateChangeTime,
             const boost::posix_time::time_duration& runtime) :
       id_(id),
       priority_(priority),
       state_(state),
       timestamp_(boost::posix_time::microsec_clock::universal_time()),
       creationTime_(creationTime),
+      lastStateChangeTime_(lastStateChangeTime),
       runtime_(runtime),
+      hasEta_(false),
       status_(status)
     {
-      float ms = static_cast<float>(runtime_.total_milliseconds());
-      float remaining = boost::math::llround(1.0f - status_.GetProgress()) * ms;
-      eta_ = timestamp_ + boost::posix_time::milliseconds(remaining);
+      if (state_ == JobState_Running)
+      {
+        float ms = static_cast<float>(runtime_.total_milliseconds());
+
+        if (status_.GetProgress() > 0.01f &&
+            ms > 0.01f)
+        {
+          float remaining = boost::math::llround(1.0f - status_.GetProgress()) * ms;
+          eta_ = timestamp_ + boost::posix_time::milliseconds(remaining);
+          hasEta_ = true;
+        }
+      }
     }
 
     JobInfo() :
@@ -471,8 +485,9 @@
       state_(JobState_Failure),
       timestamp_(boost::posix_time::microsec_clock::universal_time()),
       creationTime_(timestamp_),
+      lastStateChangeTime_(timestamp_),
       runtime_(boost::posix_time::milliseconds(0)),
-      eta_(timestamp_)
+      hasEta_(false)
     {
     }
 
@@ -506,9 +521,39 @@
       return runtime_;
     }
 
+    bool HasEstimatedTimeOfArrival() const
+    {
+      return hasEta_;
+    }
+
+    bool HasCompletionTime() const
+    {
+      return (state_ == JobState_Success ||
+              state_ == JobState_Failure);
+    }
+
     const boost::posix_time::ptime& GetEstimatedTimeOfArrival() const
     {
-      return eta_;
+      if (hasEta_)
+      {
+        return eta_;
+      }
+      else
+      {
+        throw OrthancException(ErrorCode_BadSequenceOfCalls);
+      }
+    }
+
+    const boost::posix_time::ptime& GetCompletionTime() const
+    {
+      if (HasCompletionTime())
+      {
+        return lastStateChangeTime_;
+      }
+      else
+      {
+        throw OrthancException(ErrorCode_BadSequenceOfCalls);
+      }
     }
 
     const JobStatus& GetStatus() const
@@ -526,14 +571,24 @@
       target = Json::objectValue;
       target["ID"] = id_;
       target["Priority"] = priority_;
-      target["ErrorCode"] = EnumerationToString(status_.GetErrorCode());
+      target["ErrorCode"] = static_cast<int>(status_.GetErrorCode());
+      target["ErrorDescription"] = EnumerationToString(status_.GetErrorCode());
       target["State"] = EnumerationToString(state_);
       target["Timestamp"] = boost::posix_time::to_iso_string(timestamp_);
       target["CreationTime"] = boost::posix_time::to_iso_string(creationTime_);
-      target["Runtime"] = static_cast<uint32_t>(runtime_.total_milliseconds());
-      target["EstimatedTimeOfArrival"] = boost::posix_time::to_iso_string(eta_);
+      target["Runtime"] = static_cast<uint32_t>(runtime_.total_milliseconds());      
       target["Progress"] = boost::math::iround(status_.GetProgress() * 100.0f);
       target["Description"] = status_.GetDescription();
+
+      if (HasEstimatedTimeOfArrival())
+      {
+        target["EstimatedTimeOfArrival"] = boost::posix_time::to_iso_string(GetEstimatedTimeOfArrival());
+      }
+
+      if (HasCompletionTime())
+      {
+        target["CompletionTime"] = boost::posix_time::to_iso_string(GetCompletionTime());
+      }
     }
   };
 
@@ -552,7 +607,7 @@
     bool                              pauseScheduled_;
     JobStatus                         lastStatus_;
 
-    void SetStateInternal(JobState state) 
+    void Touch()
     {
       const boost::posix_time::ptime now = boost::posix_time::microsec_clock::universal_time();
 
@@ -561,9 +616,14 @@
         runtime_ += (now - lastStateChangeTime_);
       }
 
+      lastStateChangeTime_ = now;
+    }
+
+    void SetStateInternal(JobState state) 
+    {
       state_ = state;
-      lastStateChangeTime_ = now;
       pauseScheduled_ = false;
+      Touch();
     }
 
   public:
@@ -583,6 +643,8 @@
       {
         throw OrthancException(ErrorCode_NullPointer);
       }
+
+      lastStatus_ = JobStatus(ErrorCode_Success, *job);
     }
 
     const std::string& GetId() const
@@ -674,6 +736,11 @@
       return creationTime_;
     }
 
+    const boost::posix_time::ptime& GetLastStateChangeTime() const
+    {
+      return lastStateChangeTime_;
+    }
+
     const boost::posix_time::time_duration& GetRuntime() const
     {
       return runtime_;
@@ -687,6 +754,7 @@
     void SetLastStatus(const JobStatus& status)
     {
       lastStatus_ = status;
+      Touch();
     }
   };
 
@@ -943,6 +1011,7 @@
                                     handler.GetState(),
                                     handler.GetLastStatus(),
                                     handler.GetCreationTime(),
+                                    handler.GetLastStateChangeTime(),
                                     handler.GetRuntime());
       }
     }
@@ -2035,22 +2104,45 @@
   engine.SetWorkersCount(3);
   engine.Start();
 
-  boost::this_thread::sleep(boost::posix_time::milliseconds(200));
+  boost::this_thread::sleep(boost::posix_time::milliseconds(100));
+
+  {
+    typedef std::map<std::string, JobInfo> Jobs;
+
+    Jobs jobs;
+    engine.GetRegistry().GetJobsInfo(jobs);
+
+    Json::Value v;
+    for (Jobs::const_iterator it = jobs.begin(); it != jobs.end(); ++it)
+    {
+      Json::Value vv;
+      it->second.Format(vv);
+      v[it->first] = vv;
+    }
+
+    std::cout << v << std::endl;
+  }
+  std::cout << "====================================================" << std::endl;
+
+  boost::this_thread::sleep(boost::posix_time::milliseconds(100));
   
   engine.Stop();
 
-  typedef std::map<std::string, JobInfo> Jobs;
 
-  Jobs jobs;
-  engine.GetRegistry().GetJobsInfo(jobs);
-
-  Json::Value v;
-  for (Jobs::const_iterator it = jobs.begin(); it != jobs.end(); ++it)
   {
-    Json::Value vv;
-    it->second.Format(vv);
-    v[it->first] = vv;
+    typedef std::map<std::string, JobInfo> Jobs;
+
+    Jobs jobs;
+    engine.GetRegistry().GetJobsInfo(jobs);
+
+    Json::Value v;
+    for (Jobs::const_iterator it = jobs.begin(); it != jobs.end(); ++it)
+    {
+      Json::Value vv;
+      it->second.Format(vv);
+      v[it->first] = vv;
+    }
+
+    std::cout << v << std::endl;
   }
-
-  std::cout << v << std::endl;
 }