Copilot commented on code in PR #2224:
URL: https://github.com/apache/nifi-minifi-cpp/pull/2224#discussion_r3711075953
##########
minifi_rust/minifi_native/src/lib.rs:
##########
@@ -94,6 +94,7 @@ macro_rules! declare_minifi_extension {
let extension_definition =
minifi_native::sys::minifi_extension_definition {
name: env!("CARGO_PKG_NAME").as_minifi_c_type(),
version: env!("CARGO_PKG_VERSION").as_minifi_c_type(),
+ group_name: env!("CARGO_PKG_NAME").as_minifi_c_type(),
deinit: None,
user_data: std::ptr::null_mut(),
};
Review Comment:
`group_name` is currently set to `CARGO_PKG_NAME`, which is the
artifact/name, not a Maven-style group. This will keep producing incorrect
bundle group names in manifests for Rust extensions. Prefer a dedicated
build-time group (e.g. `MINIFI_EXTENSION_GROUP_NAME`) with a sensible default.
##########
minifi-api/include/minifi-api.h:
##########
@@ -208,6 +208,7 @@ struct minifi_controller_service_definition {
struct minifi_extension_definition {
struct minifi_string_view name;
struct minifi_string_view version;
+ struct minifi_string_view group_name;
void (*deinit)(void* user_data);
void* user_data;
};
Review Comment:
Adding `group_name` to `minifi_extension_definition` changes the struct
layout for all C extensions. To preserve binary compatibility,
`MINIFI_API_VERSION` should be bumped (and/or the loader should gate this field
on the reported API version) so older extensions don’t get their fields
misinterpreted at runtime.
##########
minifi-api/include/minifi-cpp/agent/agent_docs.h:
##########
@@ -51,32 +55,119 @@ struct ClassDescription {
bool isSingleThreaded_ = false;
};
-struct Components {
- std::vector<ClassDescription> processors;
- std::vector<ClassDescription> controller_services;
- std::vector<ClassDescription> parameter_providers;
- std::vector<ClassDescription> other_components;
-
- [[nodiscard]] bool empty() const noexcept {
- return processors.empty() && controller_services.empty() &&
parameter_providers.empty() && other_components.empty();
- }
-};
-
struct BundleIdentifier {
std::string name;
+ std::string group_name;
std::string version;
auto operator<=>(const BundleIdentifier& rhs) const = default;
};
+class Components {
+ public:
+ explicit Components(BundleIdentifier bundle_identifier) :
bundle_identifier_(std::move(bundle_identifier)) {
+ }
+ Components(const Components& rhs) = default;
+ Components(Components&& rhs) = default;
+ Components& operator=(const Components& rhs) = default;
+ Components& operator=(Components&& rhs) = default;
+ virtual ~Components() = default;
+
+ void addClassDescription(ClassDescription component, ResourceType
resource_type) {
+ switch (resource_type) {
+ case ResourceType::Processor: {
+ processors_.emplace_back(std::move(component));
+ break;
+ }
+ case ResourceType::ControllerService: {
+ controller_services_.emplace_back(std::move(component));
+ break;
+ }
+ case ResourceType::ParameterProvider: {
+ parameter_providers_.emplace_back(std::move(component));
+ break;
+ }
+ default: {
+ other_components_.emplace_back(std::move(component));
+ break;
+ }
+ }
+ };
+
+ const std::vector<ClassDescription>& getProcessors() const {
+ return processors_;
+ }
+ const std::vector<ClassDescription>& getControllerServices() const {
+ return controller_services_;
+ }
+ const std::vector<ClassDescription>& getParameterProviders() const {
+ return parameter_providers_;
+ }
+ const std::vector<ClassDescription>& getOtherComponents() const {
+ return other_components_;
+ }
+
+ const BundleIdentifier& getBundleIdentifier() const {
+ return bundle_identifier_;
+ }
+
+ [[nodiscard]] bool empty() const noexcept {
+ return processors_.empty() && controller_services_.empty() &&
parameter_providers_.empty() && other_components_.empty();
+ }
+
+ static void sortClassDescription(minifi::ClassDescription&
class_description) {
+ std::ranges::sort(class_description.class_properties_, {},
&minifi::core::Property::getName);
+ std::ranges::sort(class_description.dynamic_properties_, {},
&minifi::core::DynamicProperty::name);
+ std::ranges::sort(class_description.class_relationships_, {},
&minifi::core::Relationship::getName);
+ std::ranges::sort(class_description.output_attributes_, {},
&minifi::core::OutputAttribute::name);
+ std::ranges::sort(class_description.api_implementations, {},
&minifi::core::ControllerServiceType::type);
Review Comment:
This header now uses `std::ranges::sort`, `std::ranges::copy`,
`std::back_inserter`, and `minifi::utils::string::toLower` in inline member
functions, but it does not include the standard/library headers that declare
them (`<algorithm>`, `<iterator>`, and the project header that provides
`utils::string::toLower`, typically `utils/StringUtils.h`). This can break
consumers depending on include order.
##########
core-framework/include/agent/agent_docs.h:
##########
@@ -59,12 +59,11 @@ std::string classNameWithDots() {
} // namespace detail
template<typename Class, ResourceType Type>
-void ClassDescriptionRegistry::createClassDescription(std::string bundle_name,
std::string class_name, std::string version) {
- const BundleIdentifier group_details{.name = std::move(bundle_name),
.version = std::move(version)};
- auto& [processors, controller_services, parameter_providers,
other_components] = getMutableClassDescriptions()[group_details];
-
+void ClassDescriptionRegistry::createClassDescription(const BundleIdentifier&
bundle_identifier, std::string class_name) {
+ auto [it, _success] =
getMutableClassDescriptions().try_emplace(bundle_identifier, bundle_identifier);
+ auto& [id, components] = *it;
if constexpr (Type == ResourceType::Processor) {
Review Comment:
The structured binding introduces two unused variables (`_success` and `id`)
which can trigger -Wunused-variable under common warning settings. Prefer
binding only what’s needed and explicitly discarding the boolean.
##########
minifi-api/include/minifi-cpp/agent/agent_docs.h:
##########
@@ -51,32 +55,119 @@ struct ClassDescription {
bool isSingleThreaded_ = false;
};
-struct Components {
- std::vector<ClassDescription> processors;
- std::vector<ClassDescription> controller_services;
- std::vector<ClassDescription> parameter_providers;
- std::vector<ClassDescription> other_components;
-
- [[nodiscard]] bool empty() const noexcept {
- return processors.empty() && controller_services.empty() &&
parameter_providers.empty() && other_components.empty();
- }
-};
-
struct BundleIdentifier {
std::string name;
+ std::string group_name;
std::string version;
auto operator<=>(const BundleIdentifier& rhs) const = default;
};
+class Components {
+ public:
+ explicit Components(BundleIdentifier bundle_identifier) :
bundle_identifier_(std::move(bundle_identifier)) {
+ }
+ Components(const Components& rhs) = default;
+ Components(Components&& rhs) = default;
+ Components& operator=(const Components& rhs) = default;
+ Components& operator=(Components&& rhs) = default;
+ virtual ~Components() = default;
+
Review Comment:
`Components` is stored by value in `std::map<BundleIdentifier, Components>`
and doesn’t appear to be used polymorphically. A `virtual` destructor makes it
a polymorphic type (adds a vtable), increasing object size and complicating ABI
for a public header without a clear need.
##########
extensions/python/PythonCreator.h:
##########
@@ -174,7 +174,8 @@ class PythonCreator : public
minifi::core::CoreComponentImpl {
.inputRequirement_ = toString(processor->getInputRequirement()),
.isSingleThreaded_ = processor->isSingleThreaded()};
-
minifi::ClassDescriptionRegistry::getMutableClassDescriptions()[details].processors.push_back(description);
+ auto [it, _success] =
ClassDescriptionRegistry::getMutableClassDescriptions().try_emplace(details,
details);
+ it->second.addClassDescription(description, ResourceType::Processor);
Review Comment:
`BundleIdentifier` now includes `group_name`, but this path never sets it,
so Python-loaded bundles will serialize with an empty group in the manifest
(regressing the exact issue this PR is fixing). Please set `details.group_name`
to the appropriate group for Python processors (likely the extension group)
before inserting into the registry.
##########
libminifi/src/minifi-api.cpp:
##########
@@ -328,14 +327,16 @@ minifi_status minifi_register_processor(minifi_extension*
extension, const minif
}
const minifi::BundleIdentifier bundle{
.name = extension_info->name,
+ .group_name = extension_info->group_name,
.version = extension_info->version
};
- auto& bundle_components =
minifi::ClassDescriptionRegistry::getMutableClassDescriptions()[bundle];
+ auto [it, _success] =
minifi::ClassDescriptionRegistry::getMutableClassDescriptions().try_emplace(bundle,
bundle);
+ auto& bundle_components = it->second;
minifi::utils::useCProcessorClassDescription(*processor, [&] (const auto&
description, const auto& c_class_description) {
Review Comment:
The `try_emplace` return value’s boolean (`_success`) is unused here and may
trigger -Wunused-variable. Either discard it explicitly or bind only the
iterator.
This issue also appears on line 356 of the same file.
##########
extensions/standard-processors/tests/unit/ManifestTests.cpp:
##########
@@ -125,7 +126,8 @@ TEST_CASE("Test Relationships", "[rel1]") {
}
TEST_CASE("Test Dependent", "[dependent]") {
- const auto standard_processor_bundle_id = minifi::BundleIdentifier{.name =
"minifi-standard-processors", .version = minifi::AgentBuild::VERSION};
+ const auto standard_processor_bundle_id = minifi::BundleIdentifier{.name =
"minifi-standard-processors", .group_name = "org.apache.nifi.minifi", .version
= minifi::AgentBuild::VERSION};
+ const auto class_desc =
minifi::ClassDescriptionRegistry::getClassDescriptions();
const auto standard_processors_components =
minifi::ClassDescriptionRegistry::getClassDescriptions().at(standard_processor_bundle_id);
Review Comment:
This variable is unused and may trigger -Wunused-variable under common
warning settings. It can be removed.
##########
extensions/standard-processors/tests/unit/ManifestTestHelper.h:
##########
@@ -0,0 +1,127 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include <optional>
+#include <string>
+#include <string_view>
+#include <vector>
+
+#include "minifi-cpp/core/state/Value.h"
+#include "range/v3/algorithm/find_if.hpp"
+
+namespace org::apache::nifi::minifi::state::response {
+struct SerializedResponseNode;
+}
+enum ComponentType {
+ kProcessor,
+ kControllerService,
+};
+
+struct AllowedType {
+ std::string type;
+ std::string group;
+ std::string artifact;
+
+ auto operator<=>(const AllowedType&) const = default;
+};
+
+using org::apache::nifi::minifi::state::response::SerializedResponseNode;
+
+const SerializedResponseNode* getBundle(const
std::vector<SerializedResponseNode>& manifest, const std::string_view
bundle_artifact_name) {
Review Comment:
These helper functions are defined in a header with external linkage. If the
header is included by multiple translation units in the same test binary, this
will cause multiple-definition linker errors. Mark header-defined free
functions `inline` (or `static`) to make ODR-safe.
This issue also appears in the following locations of the same file:
- line 58
- line 83
- line 106
##########
extensions/stable-api-testing/ZooProcessor.cpp:
##########
@@ -37,6 +37,10 @@ minifi_status
ZooProcessor::onTriggerImpl(api::core::ProcessContext& process_con
logger_->log_critical("{} has {} legs", num_of_legs_name,
num_legs->numberOfLegs());
}
}
+ if (auto ssl_data = process_context.getSslData(SSLContextService)) {
+ logger_->log_critical("Has ssl_data? {}", ssl_data.has_value());
+ }
Review Comment:
`ProcessContext::getSslData()` returns a `std::expected<...>`. The `if (auto
ssl_data = ...)` branch already guarantees `ssl_data.has_value()` is true, so
the log always prints `true` and doesn’t reflect whether SSL data is actually
present. Check the inner `std::optional` instead.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]