changeset 6445:68de7e892eaa queues-timeout

renaming supports_extended_queues as supports_reserve_queue_value
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 18 Nov 2025 18:34:51 +0100
parents 31197da4a994
children 11f76e2aaed1
files NEWS OrthancServer/Plugins/Engine/OrthancPluginDatabaseV4.cpp OrthancServer/Plugins/Engine/OrthancPlugins.cpp OrthancServer/Plugins/Include/orthanc/OrthancCPlugin.h OrthancServer/Plugins/Include/orthanc/OrthancDatabasePlugin.proto OrthancServer/Plugins/Samples/Common/OrthancPluginCppWrapper.cpp OrthancServer/Plugins/Samples/Common/OrthancPluginCppWrapper.h OrthancServer/Sources/Database/IDatabaseWrapper.h OrthancServer/Sources/Database/SQLiteDatabaseWrapper.cpp OrthancServer/Sources/Database/StatelessDatabaseOperations.cpp OrthancServer/Sources/Database/StatelessDatabaseOperations.h OrthancServer/Sources/OrthancRestApi/OrthancRestSystem.cpp OrthancServer/UnitTestsSources/ServerIndexTests.cpp
diffstat 13 files changed, 88 insertions(+), 75 deletions(-) [+]
line wrap: on
line diff
--- a/NEWS	Tue Nov 18 17:50:39 2025 +0100
+++ b/NEWS	Tue Nov 18 18:34:51 2025 +0100
@@ -21,6 +21,15 @@
 * C-Move and C-Get jobs and HTTP responses now include a new "Details" field with the "DimseErrorStatus"
   of each operation and the list of "RetrievedInstancesIds".
 
+Plugin SDK
+----------
+
+* New primitives for handling queues to ensure that no messages are lost if
+  Orthanc is stopped while a plugin is processing a message:
+  - OrthancPluginReserveQueueValue() is a replacement for OrthancPluginDequeueValue(). This flavour
+    does not directly remove the value from the queue but reserves it for a certain duration.
+  - OrthancPluginAcknowledgeQueueValue() removes a reserved value from a queue.
+
 Maintenance
 -----------
 
@@ -53,16 +62,6 @@
   - civetweb 1.16, including patch for CVE-2025-55763
   - SQLite 3.50.4
 
-Plugin SDK
-----------
-
-* New primitives for handling queues:
-  - OrthancPluginReserveQueueValue is a replacement for OrthancPluginDequeueValue.  This flavour
-    does not directly remove the value from the queue but reserves it for a certain duration.
-  - OrthancPluginAcknowledgeQueueValue removes a reserved value from a queue.
-  - With these 2 primitives, one can ensure not to loose any message in case Orthanc is stopped
-    while handling a message.
-
 
 Version 1.12.9 (2025-08-11)
 ===========================
--- a/OrthancServer/Plugins/Engine/OrthancPluginDatabaseV4.cpp	Tue Nov 18 17:50:39 2025 +0100
+++ b/OrthancServer/Plugins/Engine/OrthancPluginDatabaseV4.cpp	Tue Nov 18 18:34:51 2025 +0100
@@ -2058,7 +2058,7 @@
                                    QueueOrigin origin,
                                    uint32_t releaseTimeout) ORTHANC_OVERRIDE
     {
-      if (database_.GetDatabaseCapabilities().HasExtendedQueuesSupport())
+      if (database_.GetDatabaseCapabilities().HasReserveQueueValueSupport())
       {
         DatabasePluginMessages::TransactionRequest request;
         request.mutable_reserve_queue_value()->set_queue_id(queueId);
@@ -2103,7 +2103,7 @@
                                        uint64_t valueId) ORTHANC_OVERRIDE
     {
 
-      if (database_.GetDatabaseCapabilities().HasExtendedQueuesSupport())
+      if (database_.GetDatabaseCapabilities().HasReserveQueueValueSupport())
       {
         DatabasePluginMessages::TransactionRequest request;
         request.mutable_acknowledge_queue_value()->set_queue_id(queueId);
@@ -2210,7 +2210,7 @@
       dbCapabilities_.SetHasFindSupport(systemInfo.supports_find());
       dbCapabilities_.SetKeyValueStoresSupport(systemInfo.supports_key_value_stores());
       dbCapabilities_.SetQueuesSupport(systemInfo.supports_queues());
-      dbCapabilities_.SetExtendedQueuesSupport(systemInfo.supports_extended_queues());
+      dbCapabilities_.SetReserveQueueValueSupport(systemInfo.supports_reserve_queue_value());
       dbCapabilities_.SetAttachmentCustomDataSupport(systemInfo.has_attachment_custom_data());
     }
 
--- a/OrthancServer/Plugins/Engine/OrthancPlugins.cpp	Tue Nov 18 17:50:39 2025 +0100
+++ b/OrthancServer/Plugins/Engine/OrthancPlugins.cpp	Tue Nov 18 18:34:51 2025 +0100
@@ -4723,9 +4723,9 @@
     }
   }
 
-  static void CheckExtendedQueuesSupport(ServerContext& context)
-  {
-    if (!context.GetIndex().HasExtendedQueuesSupport())
+  static void CheckReserveQueueValueSupport(ServerContext& context)
+  {
+    if (!context.GetIndex().HasReserveQueueValueSupport())
     {
       throw OrthancException(ErrorCode_NotImplemented, "The database engine does not support queues (extended)");
     }
@@ -4772,7 +4772,7 @@
   {
     PImpl::ServerContextReference lock(*pimpl_);
 
-    CheckExtendedQueuesSupport(lock.GetContext());
+    CheckReserveQueueValueSupport(lock.GetContext());
 
     std::string value;
     uint64_t valueId;
@@ -4793,7 +4793,7 @@
   {
     PImpl::ServerContextReference lock(*pimpl_);
 
-    CheckExtendedQueuesSupport(lock.GetContext());
+    CheckReserveQueueValueSupport(lock.GetContext());
 
     lock.GetContext().GetIndex().AcknowledgeQueueValue(parameters.queueId, parameters.valueId);
   }
--- a/OrthancServer/Plugins/Include/orthanc/OrthancCPlugin.h	Tue Nov 18 17:50:39 2025 +0100
+++ b/OrthancServer/Plugins/Include/orthanc/OrthancCPlugin.h	Tue Nov 18 18:34:51 2025 +0100
@@ -10770,11 +10770,11 @@
 
   /**
    * @brief Acknowledge that a queue value has been properly consumed by the plugin
-   * and can be definitely removed from the queue.
+   * and can be permanently removed from the queue.
    *
    * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
    * @param queueId A unique identifier identifying both the plugin and the queue.
-   * @param valueId The opaque identifier for the value obtained from OrthancPluginReserveQueueValue().
+   * @param valueId The opaque identifier for the value provided by OrthancPluginReserveQueueValue().
    * @return 0 if success, other value if error.
    **/
   ORTHANC_PLUGIN_SINCE_SDK("1.12.10")
--- a/OrthancServer/Plugins/Include/orthanc/OrthancDatabasePlugin.proto	Tue Nov 18 17:50:39 2025 +0100
+++ b/OrthancServer/Plugins/Include/orthanc/OrthancDatabasePlugin.proto	Tue Nov 18 18:34:51 2025 +0100
@@ -175,7 +175,7 @@
     bool supports_key_value_stores = 10;  // New in Orthanc 1.12.8
     bool supports_queues = 11;            // New in Orthanc 1.12.8
     bool has_attachment_custom_data = 12; // New in Orthanc 1.12.8
-    bool supports_extended_queues = 13;   // New in Orthanc 1.12.10
+    bool supports_reserve_queue_value = 13;   // New in Orthanc 1.12.10
   }
 }
 
@@ -1067,20 +1067,6 @@
   }
 }
 
-message ReserveQueueValue {
-  message Request {
-    string queue_id = 1;
-    QueueOrigin origin = 2;
-    uint32 release_timeout = 3;
-  }
-
-  message Response {
-    bool found = 1;
-    bytes value = 2;
-    uint64 value_id = 3;
-  }
-}
-
 message GetQueueSize {
   message Request {
     string queue_id = 1;
@@ -1091,17 +1077,6 @@
   }
 }
 
-message AcknowledgeQueueValue {
-  message Request {
-    string queue_id = 1;
-    uint64 value_id = 2;
-  }
-
-  message Response {
-  }
-}
-
-
 message GetAttachmentCustomData {
   message Request {
     string uuid = 1;
@@ -1122,6 +1097,30 @@
   }
 }
 
+message ReserveQueueValue {
+  message Request {
+    string queue_id = 1;
+    QueueOrigin origin = 2;
+    uint32 release_timeout = 3;
+  }
+
+  message Response {
+    bool found = 1;
+    bytes value = 2;
+    uint64 value_id = 3;
+  }
+}
+
+message AcknowledgeQueueValue {
+  message Request {
+    string queue_id = 1;
+    uint64 value_id = 2;
+  }
+
+  message Response {
+  }
+}
+
 
 message TransactionRequest {
   sfixed64              transaction = 1;
--- a/OrthancServer/Plugins/Samples/Common/OrthancPluginCppWrapper.cpp	Tue Nov 18 17:50:39 2025 +0100
+++ b/OrthancServer/Plugins/Samples/Common/OrthancPluginCppWrapper.cpp	Tue Nov 18 18:34:51 2025 +0100
@@ -4684,7 +4684,8 @@
   }
 #endif
 
-#if HAS_ORTHANC_PLUGIN_EXTENDED_QUEUES == 1
+
+#if HAS_ORTHANC_PLUGIN_RESERVE_QUEUE_VALUE == 1
   bool Queue::ReserveInternal(std::string& value, uint64_t& valueId, OrthancPluginQueueOrigin origin, uint32_t releaseTimeout)
   {
     uint8_t found = false;
@@ -4707,21 +4708,29 @@
       return false;
     }
   }
-
+#endif
+
+
+#if HAS_ORTHANC_PLUGIN_RESERVE_QUEUE_VALUE == 1
   bool Queue::ReserveBack(std::string& value, uint64_t& valueId, uint32_t releaseTimeout)
   {
     return ReserveInternal(value, valueId, OrthancPluginQueueOrigin_Back, releaseTimeout);
   }
-    
+#endif
+
+
+#if HAS_ORTHANC_PLUGIN_RESERVE_QUEUE_VALUE == 1
   bool Queue::ReserveFront(std::string& value, uint64_t& valueId, uint32_t releaseTimeout)
   {
     return ReserveInternal(value, valueId, OrthancPluginQueueOrigin_Front, releaseTimeout);
   }
-
+#endif
+
+
+#if HAS_ORTHANC_PLUGIN_RESERVE_QUEUE_VALUE == 1
   void Queue::Acknowledge(uint64_t valueId)
   {
     OrthancPluginAcknowledgeQueueValue(OrthancPlugins::GetGlobalContext(), queueId_.c_str(), valueId);
   }
 #endif
-
 }
--- a/OrthancServer/Plugins/Samples/Common/OrthancPluginCppWrapper.h	Tue Nov 18 17:50:39 2025 +0100
+++ b/OrthancServer/Plugins/Samples/Common/OrthancPluginCppWrapper.h	Tue Nov 18 18:34:51 2025 +0100
@@ -143,9 +143,9 @@
 #endif
 
 #if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 12, 10)
-#  define HAS_ORTHANC_PLUGIN_EXTENDED_QUEUES   1
+#  define HAS_ORTHANC_PLUGIN_RESERVE_QUEUE_VALUE   1
 #else
-#  define HAS_ORTHANC_PLUGIN_EXTENDED_QUEUES   0
+#  define HAS_ORTHANC_PLUGIN_RESERVE_QUEUE_VALUE   0
 #endif
 
 
@@ -1723,7 +1723,7 @@
 
     bool DequeueInternal(std::string& value, OrthancPluginQueueOrigin origin);
 
-#if HAS_ORTHANC_PLUGIN_EXTENDED_QUEUES == 1
+#if HAS_ORTHANC_PLUGIN_RESERVE_QUEUE_VALUE == 1
     bool ReserveInternal(std::string& value, uint64_t& valueId, OrthancPluginQueueOrigin origin, uint32_t releaseTimeout);
 #endif
 
@@ -1746,14 +1746,14 @@
       Enqueue(value.empty() ? NULL : value.c_str(), value.size());
     }
 
-    // Use ReserveBack instead
+    // Use ReserveBack() instead
     ORTHANC_PLUGIN_DEPRECATED
     bool DequeueBack(std::string& value)
     {
       return DequeueInternal(value, OrthancPluginQueueOrigin_Back);
     }
 
-    // Use ReserveFront instead
+    // Use ReserveFront() instead
     ORTHANC_PLUGIN_DEPRECATED
     bool DequeueFront(std::string& value)
     {
@@ -1762,11 +1762,15 @@
 
     uint64_t GetSize();
 
-#if HAS_ORTHANC_PLUGIN_EXTENDED_QUEUES == 1
+#if HAS_ORTHANC_PLUGIN_RESERVE_QUEUE_VALUE == 1
     bool ReserveBack(std::string& value, uint64_t& valueId, uint32_t releaseTimeout);
+#endif
     
+#if HAS_ORTHANC_PLUGIN_RESERVE_QUEUE_VALUE == 1
     bool ReserveFront(std::string& value, uint64_t& valueId, uint32_t releaseTimeout);
+#endif
 
+#if HAS_ORTHANC_PLUGIN_RESERVE_QUEUE_VALUE == 1
     void Acknowledge(uint64_t valueId);
 #endif
   };
--- a/OrthancServer/Sources/Database/IDatabaseWrapper.h	Tue Nov 18 17:50:39 2025 +0100
+++ b/OrthancServer/Sources/Database/IDatabaseWrapper.h	Tue Nov 18 18:34:51 2025 +0100
@@ -59,7 +59,7 @@
       bool hasAttachmentCustomDataSupport_;
       bool hasKeyValueStoresSupport_;
       bool hasQueuesSupport_;
-      bool hasExtendedQueuesSupport_;
+      bool hasReserveQueueValueSupport_;
 
     public:
       Capabilities() :
@@ -74,7 +74,7 @@
         hasAttachmentCustomDataSupport_(false),
         hasKeyValueStoresSupport_(false),
         hasQueuesSupport_(false),
-        hasExtendedQueuesSupport_(false)
+        hasReserveQueueValueSupport_(false)
       {
       }
 
@@ -188,14 +188,14 @@
         return hasQueuesSupport_;
       }
 
-      void SetExtendedQueuesSupport(bool value)
+      void SetReserveQueueValueSupport(bool value)
       {
-        hasExtendedQueuesSupport_ = value;
+        hasReserveQueueValueSupport_ = value;
       }
 
-      bool HasExtendedQueuesSupport() const
+      bool HasReserveQueueValueSupport() const
       {
-        return hasExtendedQueuesSupport_;
+        return hasReserveQueueValueSupport_;
       }
 
     };
@@ -484,8 +484,8 @@
       virtual uint64_t GetQueueSize(const std::string& queueId) = 0;
 
       // New in Orthanc 1.12.10
-      virtual bool ReserveQueueValue(std::string& value,
-                                     uint64_t& valueId, 
+      virtual bool ReserveQueueValue(std::string& value /* out */,
+                                     uint64_t& valueId /* out */, 
                                      const std::string& queueId,
                                      QueueOrigin origin,
                                      uint32_t releaseTimeout) = 0;
--- a/OrthancServer/Sources/Database/SQLiteDatabaseWrapper.cpp	Tue Nov 18 17:50:39 2025 +0100
+++ b/OrthancServer/Sources/Database/SQLiteDatabaseWrapper.cpp	Tue Nov 18 18:34:51 2025 +0100
@@ -2652,8 +2652,8 @@
     dbCapabilities_.SetHasFindSupport(HasIntegratedFind());
     dbCapabilities_.SetKeyValueStoresSupport(true);
     dbCapabilities_.SetQueuesSupport(true);
-    dbCapabilities_.SetExtendedQueuesSupport(true);
     dbCapabilities_.SetAttachmentCustomDataSupport(true);
+    dbCapabilities_.SetReserveQueueValueSupport(true);
     db_.Open(path);
   }
 
@@ -2670,8 +2670,8 @@
     dbCapabilities_.SetHasFindSupport(HasIntegratedFind());
     dbCapabilities_.SetKeyValueStoresSupport(true);
     dbCapabilities_.SetQueuesSupport(true);
-    dbCapabilities_.SetExtendedQueuesSupport(true);
     dbCapabilities_.SetAttachmentCustomDataSupport(true);
+    dbCapabilities_.SetReserveQueueValueSupport(true);
     db_.OpenInMemory();
   }
 
--- a/OrthancServer/Sources/Database/StatelessDatabaseOperations.cpp	Tue Nov 18 17:50:39 2025 +0100
+++ b/OrthancServer/Sources/Database/StatelessDatabaseOperations.cpp	Tue Nov 18 18:34:51 2025 +0100
@@ -3228,10 +3228,10 @@
     return db_.GetDatabaseCapabilities().HasQueuesSupport();
   }
 
-  bool StatelessDatabaseOperations::HasExtendedQueuesSupport()
+  bool StatelessDatabaseOperations::HasReserveQueueValueSupport()
   {
     boost::shared_lock<boost::shared_mutex> lock(mutex_);
-    return db_.GetDatabaseCapabilities().HasExtendedQueuesSupport();
+    return db_.GetDatabaseCapabilities().HasReserveQueueValueSupport();
   }
 
   void StatelessDatabaseOperations::ExecuteCount(uint64_t& count,
--- a/OrthancServer/Sources/Database/StatelessDatabaseOperations.h	Tue Nov 18 17:50:39 2025 +0100
+++ b/OrthancServer/Sources/Database/StatelessDatabaseOperations.h	Tue Nov 18 18:34:51 2025 +0100
@@ -637,7 +637,7 @@
 
     bool HasQueuesSupport();
 
-    bool HasExtendedQueuesSupport();
+    bool HasReserveQueueValueSupport();
 
     void GetExportedResources(Json::Value& target,
                               int64_t since,
--- a/OrthancServer/Sources/OrthancRestApi/OrthancRestSystem.cpp	Tue Nov 18 17:50:39 2025 +0100
+++ b/OrthancServer/Sources/OrthancRestApi/OrthancRestSystem.cpp	Tue Nov 18 18:34:51 2025 +0100
@@ -97,9 +97,9 @@
     static const char* const HAS_EXTENDED_CHANGES = "HasExtendedChanges";
     static const char* const HAS_KEY_VALUE_STORES = "HasKeyValueStores";
     static const char* const HAS_QUEUES = "HasQueues";
-    static const char* const HAS_EXTENDED_QUEUES = "HasExtendedQueues";
     static const char* const HAS_EXTENDED_FIND = "HasExtendedFind";
     static const char* const READ_ONLY = "ReadOnly";
+    static const char* const HAS_RESERVE_QUEUE_VALUE = "HasReserveQueueValue";
 
     if (call.IsDocumentation())
     {
@@ -148,7 +148,9 @@
         .SetAnswerField(HAS_LABELS, RestApiCallDocumentation::Type_Boolean,
                         "Whether the database back-end supports labels (new in Orthanc 1.12.0)")
         .SetAnswerField(CAPABILITIES, RestApiCallDocumentation::Type_JsonObject,
-                        "Whether the back-end supports optional features like 'HasExtendedChanges', 'HasExtendedFind' (new in Orthanc 1.12.5) ")
+                        "Whether the database back-end supports optional features like 'HasExtendedChanges', 'HasExtendedFind' "
+                        "(new in Orthanc 1.12.5), 'HasKeyValueStores', 'HasQueues' (new in Orthanc 1.12.8), "
+                        "and 'HasReserveQueueValue' (new in Orthanc 1.12.10)")
         .SetAnswerField(READ_ONLY, RestApiCallDocumentation::Type_Boolean,
                         "Whether Orthanc is running in read only mode (new in Orthanc 1.12.5)")
         .SetHttpGetSample("https://orthanc.uclouvain.be/demo/system", true);
@@ -214,7 +216,7 @@
     result[CAPABILITIES][HAS_EXTENDED_FIND] = OrthancRestApi::GetIndex(call).HasFindSupport();
     result[CAPABILITIES][HAS_KEY_VALUE_STORES] = OrthancRestApi::GetIndex(call).HasKeyValueStoresSupport();
     result[CAPABILITIES][HAS_QUEUES] = OrthancRestApi::GetIndex(call).HasQueuesSupport();
-    result[CAPABILITIES][HAS_EXTENDED_QUEUES] = OrthancRestApi::GetIndex(call).HasExtendedQueuesSupport();
+    result[CAPABILITIES][HAS_RESERVE_QUEUE_VALUE] = OrthancRestApi::GetIndex(call).HasReserveQueueValueSupport();
     
     call.GetOutput().AnswerJson(result);
   }
--- a/OrthancServer/UnitTestsSources/ServerIndexTests.cpp	Tue Nov 18 17:50:39 2025 +0100
+++ b/OrthancServer/UnitTestsSources/ServerIndexTests.cpp	Tue Nov 18 18:34:51 2025 +0100
@@ -1319,7 +1319,7 @@
   db.Close();
 }
 
-TEST(SQLiteDatabaseWrapper, QueuesExtended)
+TEST(SQLiteDatabaseWrapper, ReserveQueueValue)
 {
   SQLiteDatabaseWrapper db;   // The SQLite DB is in memory
   db.Open();
@@ -1429,4 +1429,4 @@
   }
 
   transaction_->DeleteResource(patient);
-}
\ No newline at end of file
+}