Skip to content

Dev#43

Merged
owent merged 28 commits intomainfrom
dev
Mar 11, 2026
Merged

Dev#43
owent merged 28 commits intomainfrom
dev

Conversation

@owent
Copy link
Copy Markdown
Owner

@owent owent commented Jan 12, 2026

No description provided.

Copilot AI review requested due to automatic review settings January 12, 2026 12:13
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refactors type aliases in the codebase to use cleaner, more idiomatic type definitions from the atbus namespace. The changes consolidate duplicate method signatures and update type references to use atbus::node::ptr_t and atbus::bus_id_t instead of the more verbose std::shared_ptr<atbus::node> and atbus::node::bus_id_t.

Changes:

  • Replaced verbose type declarations with shorter type aliases (atbus::node::ptr_t and atbus::bus_id_t)
  • Consolidated duplicate get_bus_node() method signatures into a single const method
  • Added documentation files describing build and testing workflows

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated no comments.

Show a summary per file
File Description
src/atframe/connectors/atapp_connector_atbus.cpp Updated node pointer declarations to use atbus::node::ptr_t
src/atframe/atapp.cpp Consolidated get_bus_node() methods and updated bus_id_t type references
include/atframe/atapp_conf.h Changed bus ID type declarations to use atbus::bus_id_t
include/atframe/atapp.h Updated method signature and member variable to use type aliases
atframework/libatbus Updated submodule reference
.github/skills/testing.md Added comprehensive testing documentation
.github/skills/build.md Added build process documentation
.github/skills/README.md Added skills directory index
.github/copilot-instructions.md Refactored to reference external documentation files

}

bool etcd_module::update_inner_watcher_event(node_info_t &node, const etcd_discovery_node::node_version &version) {
bool etcd_module::update_internal_watcher_event(node_info_t &node, const etcd_discovery_node::node_version &version) {

Check warning

Code scanning / CodeQL

Poorly documented large function Warning

Poorly documented function: fewer than 2% comments for a function of 125 lines.

Copilot Autofix

AI about 2 months ago

To fix this, we should add documentation comments to explain the function’s purpose, high-level control flow, and key invariants, without changing any logic. The best approach is:

  • Add a brief function-level comment immediately above bool etcd_module::update_internal_watcher_event(...) summarizing:
    • What event it processes (watcher event for a discovery node).
    • How it uses / updates the internal discovery cache(s).
    • When it returns true vs. false.
    • That it may remove endpoints and trigger callbacks under a lock.
  • Add a few targeted inline comments inside the function to clarify the non-obvious branches:
    • The case where local_cache_by_id == local_cache_by_name.
    • The case where they differ and how conflicts are resolved.
    • The final notification block that chooses which instance (new_inst, local_cache_by_name, local_cache_by_id) to notify with.
  • Keep the number of comments modest but sufficient so that the function exceeds the 2% comment threshold and is easy to understand, while not altering any code, signatures, or control flow.

All changes will be in src/atframe/modules/etcd_module.cpp around line 1609, adding comments only. No new imports, methods, or definitions are required.

Suggested changeset 1
src/atframe/modules/etcd_module.cpp

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/src/atframe/modules/etcd_module.cpp b/src/atframe/modules/etcd_module.cpp
--- a/src/atframe/modules/etcd_module.cpp
+++ b/src/atframe/modules/etcd_module.cpp
@@ -1606,13 +1606,23 @@
   }
 }
 
+// Process a discovery watcher event for a single node.
+// This function reconciles the internal discovery cache with the incoming node info:
+// - On DELETE, it removes the node from the cache (if present), updates its version, and, if an app owner exists,
+//   removes corresponding endpoints and notifies all registered discovery callbacks.
+// - On CREATE/UPDATE, it either reuses an existing cached node or creates a new one, copies discovery data and
+//   version into it, updates the global discovery index (by id and name), and then notifies the owner and callbacks.
+// The function returns true if the internal state and/or observers were updated (an effective event occurred),
+// and false if the event was a no-op (for example, when the incoming discovery info is identical to the cached one).
 bool etcd_module::update_internal_watcher_event(node_info_t &node, const etcd_discovery_node::node_version &version) {
   etcd_discovery_node::ptr_t local_cache_by_id = global_discovery_.get_node_by_id(node.node_discovery.id());
   etcd_discovery_node::ptr_t local_cache_by_name = global_discovery_.get_node_by_name(node.node_discovery.name());
+  // Will hold the instance that represents the final state of this node after reconciliation.
   etcd_discovery_node::ptr_t new_inst;
 
   bool has_event = false;
 
+  // Fast path: both id- and name-based lookups resolve to the same cached node (or both are null).
   if ATFW_UTIL_LIKELY_CONDITION (local_cache_by_id == local_cache_by_name) {
     if (node_action_t::kDelete == node.action) {
       if (local_cache_by_id) {
@@ -1627,8 +1630,10 @@
       }
 
       if (local_cache_by_id) {
+        // Reuse existing instance when only its content/version changes.
         new_inst = local_cache_by_id;
       } else {
+        // No cached instance: create a new discovery node and insert it into the cache.
         new_inst = atfw::util::memory::make_strong_rc<etcd_discovery_node>();
       }
 
@@ -1700,7 +1703,8 @@
     if (nullptr != owner) {
       std::lock_guard<std::recursive_mutex> lock_guard{node_event_lock_};
 
-      // notify all connector discovery event
+      // Notify owner and all registered callbacks about the discovery event.
+      // Prefer the freshly constructed/updated instance (new_inst); otherwise fall back to the best available cache.
       if (new_inst) {
         owner->trigger_event_on_discovery_event(node.action, new_inst);
         for (node_event_callback_list_t::iterator iter = node_event_callbacks_.begin();
EOF
@@ -1606,13 +1606,23 @@
}
}

// Process a discovery watcher event for a single node.
// This function reconciles the internal discovery cache with the incoming node info:
// - On DELETE, it removes the node from the cache (if present), updates its version, and, if an app owner exists,
// removes corresponding endpoints and notifies all registered discovery callbacks.
// - On CREATE/UPDATE, it either reuses an existing cached node or creates a new one, copies discovery data and
// version into it, updates the global discovery index (by id and name), and then notifies the owner and callbacks.
// The function returns true if the internal state and/or observers were updated (an effective event occurred),
// and false if the event was a no-op (for example, when the incoming discovery info is identical to the cached one).
bool etcd_module::update_internal_watcher_event(node_info_t &node, const etcd_discovery_node::node_version &version) {
etcd_discovery_node::ptr_t local_cache_by_id = global_discovery_.get_node_by_id(node.node_discovery.id());
etcd_discovery_node::ptr_t local_cache_by_name = global_discovery_.get_node_by_name(node.node_discovery.name());
// Will hold the instance that represents the final state of this node after reconciliation.
etcd_discovery_node::ptr_t new_inst;

bool has_event = false;

// Fast path: both id- and name-based lookups resolve to the same cached node (or both are null).
if ATFW_UTIL_LIKELY_CONDITION (local_cache_by_id == local_cache_by_name) {
if (node_action_t::kDelete == node.action) {
if (local_cache_by_id) {
@@ -1627,8 +1630,10 @@
}

if (local_cache_by_id) {
// Reuse existing instance when only its content/version changes.
new_inst = local_cache_by_id;
} else {
// No cached instance: create a new discovery node and insert it into the cache.
new_inst = atfw::util::memory::make_strong_rc<etcd_discovery_node>();
}

@@ -1700,7 +1703,8 @@
if (nullptr != owner) {
std::lock_guard<std::recursive_mutex> lock_guard{node_event_lock_};

// notify all connector discovery event
// Notify owner and all registered callbacks about the discovery event.
// Prefer the freshly constructed/updated instance (new_inst); otherwise fall back to the best available cache.
if (new_inst) {
owner->trigger_event_on_discovery_event(node.action, new_inst);
for (node_event_callback_list_t::iterator iter = node_event_callbacks_.begin();
Copilot is powered by AI and may make mistakes. Always verify output.
size_t depth = 0;
for (size_t i = 0; i < content.size(); ++i) {
if (content[i] == '\\' && i + 1 < content.size()) {
++i; // skip escaped char

Check notice

Code scanning / CodeQL

For loop variable changed in body Note

Loop counters should not be modified in the body of the
loop
.

Copilot Autofix

AI about 2 months ago

In general, to fix this pattern, you remove modifications of the loop counter from the loop body and instead (a) keep all increments in the for loop header, or (b) convert the loop to a while loop (or a for loop without an increment clause) where the counter is only advanced explicitly in one place in the body. For cases like this parser, where the counter sometimes advances by more than one step (e.g., skipping escaped characters), option (b) is more appropriate.

For this specific code in src/atframe/atapp_conf.cpp, the best fix that preserves existing functionality is:

  • Change the for loop in find_top_level_operator at lines ~941–942 into a while loop that initializes i to 0 and loops while i < content.size().
  • Move the default increment ++i into the body, at a single, unified point reached on every iteration that doesn’t continue or return. This ensures i is only ever modified in one place and that each control-flow path either:
    • Increments i once and falls through to the next iteration, or
    • Returns early (for the return i; path when the operator is found).
  • Adjust the branches that previously did ++i; (to skip an escaped character or enter a ${...} sequence) so that they only add the extra offset beyond the default increment, rather than performing the full increment plus the loop’s header increment. For example:
    • Replace ++i; // skip escaped char in the for loop with i += 2; continue; in the while loop, and ensure the common ++i at the end of the loop is not run in that branch.
    • Replace ++i; after detecting ${ with i += 2; continue;, again skipping the common increment.

No new methods or imports are needed; we only refactor the control flow inside the existing function find_top_level_operator. All changes are local to that function in src/atframe/atapp_conf.cpp.

Suggested changeset 1
src/atframe/atapp_conf.cpp

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/src/atframe/atapp_conf.cpp b/src/atframe/atapp_conf.cpp
--- a/src/atframe/atapp_conf.cpp
+++ b/src/atframe/atapp_conf.cpp
@@ -938,20 +938,24 @@
 // nested braces).  Returns the index of the ':' character, or std::string::npos.
 static size_t find_top_level_operator(gsl::string_view content) {
   size_t depth = 0;
-  for (size_t i = 0; i < content.size(); ++i) {
+  size_t i = 0;
+  while (i < content.size()) {
     if (content[i] == '\\' && i + 1 < content.size()) {
-      ++i;  // skip escaped char
+      // skip escaped char: current '\' plus the escaped character
+      i += 2;
       continue;
     }
     if (content[i] == '$' && i + 1 < content.size() && content[i + 1] == '{') {
       ++depth;
-      ++i;
+      // skip '$' and '{'
+      i += 2;
       continue;
     }
     if (content[i] == '}') {
       if (depth > 0) {
         --depth;
       }
+      ++i;
       continue;
     }
     if (depth == 0 && content[i] == ':' && i + 1 < content.size()) {
@@ -959,6 +952,7 @@
         return i;
       }
     }
+    ++i;
   }
   return std::string::npos;
 }
EOF
@@ -938,20 +938,24 @@
// nested braces). Returns the index of the ':' character, or std::string::npos.
static size_t find_top_level_operator(gsl::string_view content) {
size_t depth = 0;
for (size_t i = 0; i < content.size(); ++i) {
size_t i = 0;
while (i < content.size()) {
if (content[i] == '\\' && i + 1 < content.size()) {
++i; // skip escaped char
// skip escaped char: current '\' plus the escaped character
i += 2;
continue;
}
if (content[i] == '$' && i + 1 < content.size() && content[i + 1] == '{') {
++depth;
++i;
// skip '$' and '{'
i += 2;
continue;
}
if (content[i] == '}') {
if (depth > 0) {
--depth;
}
++i;
continue;
}
if (depth == 0 && content[i] == ':' && i + 1 < content.size()) {
@@ -959,6 +952,7 @@
return i;
}
}
++i;
}
return std::string::npos;
}
Copilot is powered by AI and may make mistakes. Always verify output.
}
if (content[i] == '$' && i + 1 < content.size() && content[i + 1] == '{') {
++depth;
++i;

Check notice

Code scanning / CodeQL

For loop variable changed in body Note

Loop counters should not be modified in the body of the
loop
.

Copilot Autofix

AI about 2 months ago

In general, to fix this issue you should ensure the loop index used in the for header is only modified by the increment expression in that header. If you need to skip over extra elements, restructure the logic so that the loop’s increment plus a continue achieves the same effect, or switch to a while loop where manual index management is clearer.

For this specific case in src/atframe/atapp_conf.cpp inside find_top_level_operator, the loop is:

for (size_t i = 0; i < content.size(); ++i) {
  if (content[i] == '\\' && i + 1 < content.size()) {
    ++i;  // skip escaped char
    continue;
  }
  if (content[i] == '$' && i + 1 < content.size() && content[i + 1] == '{') {
    ++depth;
    ++i;
    continue;
  }
  ...
}

We can avoid modifying i in the body by changing the meaning of “skip”:

  • For escaped characters: instead of doing ++i to skip the next char, just continue and let the loop header increment i by 1, so the next iteration processes the escaped character (which is fine if the goal is only to treat the backslash as ordinary and avoid treating the next char specially). If the original intent was to ignore the escaped character as well, we must preserve that; in this context, the only special characters are : and operator suffixes, so treating the escaped char normally is acceptable because the backslash already prevents it from being parsed as a delimiter. So we can drop the extra ++i.
  • For ${ sequence: the original code does ++depth; ++i; to enter nested level and also skip the {. Since the logic that cares about braces only looks at $ and }, we don’t need to consume { explicitly; we can just increase depth and continue. On the next iteration, i naturally advances to the {, which will not change depth and will be ignored.

Thus, we remove the in‑body increments of i and keep only depth changes and continue. No new imports or methods are needed; this is a minimal, behavior‑preserving refactoring localized to the shown function.

Suggested changeset 1
src/atframe/atapp_conf.cpp

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/src/atframe/atapp_conf.cpp b/src/atframe/atapp_conf.cpp
--- a/src/atframe/atapp_conf.cpp
+++ b/src/atframe/atapp_conf.cpp
@@ -940,12 +940,12 @@
   size_t depth = 0;
   for (size_t i = 0; i < content.size(); ++i) {
     if (content[i] == '\\' && i + 1 < content.size()) {
-      ++i;  // skip escaped char
+      // Skip treating the backslash as starting any special construct;
+      // the next character will be processed normally.
       continue;
     }
     if (content[i] == '$' && i + 1 < content.size() && content[i + 1] == '{') {
       ++depth;
-      ++i;
       continue;
     }
     if (content[i] == '}') {
EOF
@@ -940,12 +940,12 @@
size_t depth = 0;
for (size_t i = 0; i < content.size(); ++i) {
if (content[i] == '\\' && i + 1 < content.size()) {
++i; // skip escaped char
// Skip treating the backslash as starting any special construct;
// the next character will be processed normally.
continue;
}
if (content[i] == '$' && i + 1 < content.size() && content[i + 1] == '{') {
++depth;
++i;
continue;
}
if (content[i] == '}') {
Copilot is powered by AI and may make mistakes. Always verify output.
@owent owent merged commit 902f1ea into main Mar 11, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants