Conversation
There was a problem hiding this comment.
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_tandatbus::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
Show autofix suggestion
Hide autofix suggestion
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
truevs.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.
- The case where
- 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.
| @@ -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(); |
| 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
Show autofix suggestion
Hide autofix suggestion
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
forloop infind_top_level_operatorat lines ~941–942 into awhileloop that initializesito 0 and loops whilei < content.size(). - Move the default increment
++iinto the body, at a single, unified point reached on every iteration that doesn’tcontinueorreturn. This ensuresiis only ever modified in one place and that each control-flow path either:- Increments
ionce and falls through to the next iteration, or - Returns early (for the
return i;path when the operator is found).
- Increments
- 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 charin theforloop withi += 2; continue;in thewhileloop, and ensure the common++iat the end of the loop is not run in that branch. - Replace
++i;after detecting${withi += 2; continue;, again skipping the common increment.
- Replace
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.
| @@ -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; | ||
| } |
| } | ||
| if (content[i] == '$' && i + 1 < content.size() && content[i + 1] == '{') { | ||
| ++depth; | ||
| ++i; |
Check notice
Code scanning / CodeQL
For loop variable changed in body Note
Show autofix suggestion
Hide autofix suggestion
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
++ito skip the next char, justcontinueand let the loop header incrementiby 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 increasedepthandcontinue. On the next iteration,inaturally advances to the{, which will not changedepthand 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.
| @@ -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] == '}') { |
No description provided.