This is an automated email from the ASF dual-hosted git repository.

martinzink pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/nifi-minifi-cpp.git


The following commit(s) were added to refs/heads/main by this push:
     new 74f052275 MINIFICPP-2917 Dont schedule ClassifyImage/DetectObject 
without valid… (#2276)
74f052275 is described below

commit 74f0522757edc97bdd5f396f86b7cc2e6807a7ce
Author: Martin Zink <[email protected]>
AuthorDate: Wed Oct 7 13:20:59 2026 +0200

    MINIFICPP-2917 Dont schedule ClassifyImage/DetectObject without valid… 
(#2276)
    
    * MINIFICPP-2917 Dont schedule ClassifyImage/DetectObject/InvokeTractModel 
without valid TractModelService
---
 .../minifi_tensor/features/classification.feature     | 19 +++++++++++++++++++
 .../src/low_level_processors/invoke_tract_model.rs    |  5 +++--
 .../minifi_tensor/src/processors/classify_image.rs    |  1 +
 .../minifi_tensor/src/processors/detect_object.rs     | 10 +++-------
 4 files changed, 26 insertions(+), 9 deletions(-)

diff --git 
a/minifi_rust/extensions/minifi_tensor/features/classification.feature 
b/minifi_rust/extensions/minifi_tensor/features/classification.feature
index 20be0f6b1..ca0c26874 100644
--- a/minifi_rust/extensions/minifi_tensor/features/classification.feature
+++ b/minifi_rust/extensions/minifi_tensor/features/classification.feature
@@ -126,3 +126,22 @@ Feature: Image classification with MobileNetV2
     And the Minifi logs contain the following message: "key:mime.type 
value:application/json" in less than 1 seconds
     And at least one file in "/tmp/output" content match the following regex: 
"\"class_name\":\"(military uniform|bulletproof vest|suit|Windsor tie)\"" in 
less than 30 seconds
     And the Minifi logs do not contain errors
+
+  Scenario: ClassifyImage shouldn't schedule with invalid TractModelService
+    Given a TractModelService controller service named "MobileNet" is set up 
and the "Model File Path" property set to "/tmp/models/invalid.onnx"
+
+    And a GetFile processor with the "Input Directory" property set to 
"/tmp/input"
+    And the "Keep Source File" property of the GetFile processor is set to 
"false"
+
+    And a ClassifyImage processor with the "Target width" property set to "224"
+    And the "Target height" property of the ClassifyImage processor is set to 
"224"
+    And the "Tract model service" property of the ClassifyImage processor is 
set to "MobileNet"
+
+    And the "success" relationship of the GetFile processor is connected to 
the ClassifyImage
+    And ClassifyImage's failure relationship is auto-terminated
+    And ClassifyImage's success relationship is auto-terminated
+
+    When the MiNiFi instance starts up
+
+    Then the Minifi logs contain the following message: "(ClassifyImage): 
Process Schedule Operation: Error while scheduling processor" in less than 3 
seconds
+    And the Minifi logs contain the following message: "[error] Error during 
schedule: 
minifi_process_context_get_controller_service_from_property::<"minifi_tensor::services::tract_model_service::TractModelService">("Tract
 model service"), validation failed" in less than 3 seconds
diff --git 
a/minifi_rust/extensions/minifi_tensor/src/low_level_processors/invoke_tract_model.rs
 
b/minifi_rust/extensions/minifi_tensor/src/low_level_processors/invoke_tract_model.rs
index 5485c1b64..63de151c2 100644
--- 
a/minifi_rust/extensions/minifi_tensor/src/low_level_processors/invoke_tract_model.rs
+++ 
b/minifi_rust/extensions/minifi_tensor/src/low_level_processors/invoke_tract_model.rs
@@ -33,13 +33,14 @@ mod invoke_tract_model_def;
 pub(crate) struct InvokeTractModel {}
 
 impl Schedule for InvokeTractModel {
-    fn schedule<Ctx: GetProperty, L: Logger>(
-        _context: &Ctx,
+    fn schedule<Ctx: GetProperty + GetControllerService, L: Logger>(
+        context: &Ctx,
         _logger: &L,
     ) -> Result<Self, MinifiError>
     where
         Self: Sized,
     {
+        let _tract_model_service = 
context.get_controller_service(&TRACT_MODEL_SERVICE)?;
         Ok(Self {})
     }
 }
diff --git 
a/minifi_rust/extensions/minifi_tensor/src/processors/classify_image.rs 
b/minifi_rust/extensions/minifi_tensor/src/processors/classify_image.rs
index 7df8a8956..6c2f448e9 100644
--- a/minifi_rust/extensions/minifi_tensor/src/processors/classify_image.rs
+++ b/minifi_rust/extensions/minifi_tensor/src/processors/classify_image.rs
@@ -44,6 +44,7 @@ impl Schedule for ClassifyImage {
     {
         let image_to_tensor = ImageToTensor::schedule(context, logger)?;
         let classify_output = ClassifyOutput::schedule(context, logger)?;
+        let _tract_model_service = 
context.get_controller_service(&TRACT_MODEL_SERVICE)?;
         Ok(Self {
             image_to_tensor,
             classify_output,
diff --git 
a/minifi_rust/extensions/minifi_tensor/src/processors/detect_object.rs 
b/minifi_rust/extensions/minifi_tensor/src/processors/detect_object.rs
index a70f2bd18..a2bb56b53 100644
--- a/minifi_rust/extensions/minifi_tensor/src/processors/detect_object.rs
+++ b/minifi_rust/extensions/minifi_tensor/src/processors/detect_object.rs
@@ -47,6 +47,7 @@ impl Schedule for DetectObject {
     {
         let image_to_tensor = ImageToTensor::schedule(context, logger)?;
         let filter_bounding_boxes = FilterBoundingBoxes::schedule(context, 
logger)?;
+        let _tract_model_service = 
context.get_controller_service(&TRACT_MODEL_SERVICE)?;
         Ok(Self {
             image_to_tensor,
             filter_bounding_boxes,
@@ -100,7 +101,6 @@ mod tests {
         PIXEL_DIVISOR, TARGET_HEIGHT, TARGET_WIDTH,
     };
     use minifi_native::{MockLogger, MockProcessContext};
-    use std::io::Cursor;
 
     #[test]
     fn test_missing_controller_service_errors() {
@@ -108,13 +108,9 @@ mod tests {
         context.properties.insert(TARGET_HEIGHT.name(), "100");
         context.properties.insert(TARGET_WIDTH.name(), "100");
         context.properties.insert(PIXEL_DIVISOR.name(), "1.0");
-        let processor =
-            DetectObject::schedule(&context, 
&MockLogger::new()).expect("Expected to schedule");
-        let mut input_stream = Cursor::new(vec![]);
-
-        let result = processor.transform(&context, &mut input_stream, 
&MockLogger::new());
+        let processor = DetectObject::schedule(&context, &MockLogger::new());
         assert!(
-            result.is_err(),
+            processor.is_err(),
             "Should error when TractModelService is missing"
         );
     }

Reply via email to