-
Notifications
You must be signed in to change notification settings - Fork 0
remove prototype trait #39
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
WalkthroughAdds a new CheckAuth RPC, strengthens error handling and safer lookups across binaries, renames server config field Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes
Pre-merge checks and finishing touches❌ Failed checks (1 inconclusive)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (3)
engine/src/bin/server.rs (3)
411-419: Inconsistent task ID parsing pattern.This code uses
split(":")which will break if task names contain colons. However,create_task(line 596) usessplitn(2, ':')which correctly handles this case. Consider applying the samesplitnapproach here for consistency:- let alen = &task_id.split(":").collect::<Vec<&str>>().len(); - if *alen != 2 { + let parts: Vec<&str> = task_id.splitn(2, ':').collect(); + if parts.len() != 2 || parts[0].is_empty() || parts[1].is_empty() { info!("Invalid task ID format: {}", task_id); return Err(Status::invalid_argument( "Invalid task ID format, expected 'namespace:name", )); } - let namespace = &task_id.split(":").collect::<Vec<&str>>()[0]; - let task_name = &task_id.split(":").collect::<Vec<&str>>()[1]; + let namespace = parts[0]; + let task_name = parts[1];
495-500: Same inconsistent parsing pattern asaquire_task.Apply the same
splitn(2, ':')approach used increate_taskfor consistency:- let alen = &task_id.split(":").collect::<Vec<&str>>().len(); - if *alen != 2 { + let parts: Vec<&str> = task_id.splitn(2, ':').collect(); + if parts.len() != 2 || parts[0].is_empty() || parts[1].is_empty() { return Err(Status::invalid_argument("Invalid Params")); } - let namespace = &task_id.split(":").collect::<Vec<&str>>()[0]; - let task_name = &task_id.split(":").collect::<Vec<&str>>()[1]; + let namespace = parts[0]; + let task_name = parts[1];
275-282: Unused variableendin pagination logic.The
endvariable is computed but never used. The pagination on lines 278-281 usesdata.page_sizedirectly instead of the clamped value. This appears to be dead code, or the pagination limit isn't being enforced as intended:let index = data.page * data.page_size as u64; - let end = index + (api.cfg.config_toml.pagination_limit.min(data.page_size) as u64); + let clamped_page_size = api.cfg.config_toml.pagination_limit.min(data.page_size) as usize; let final_vec: Vec<_> = q .iter() .skip(index as usize) - .take(data.page_size as usize) + .take(clamped_page_size) .cloned() .collect();
🧹 Nitpick comments (1)
engine/src/bin/packer.rs (1)
195-272: Consider reducing nesting with early returns or the?operator.The error handling logic is correct, but the deep nesting (8+ levels) reduces readability. Consider extracting the pack logic into a helper function that returns
Result<(), Box<dyn Error>>and uses?for propagation, or use crates likeanyhowfor ergonomic error handling in CLI tools.Example pattern:
fn pack_tasks(api: &mut EngineAPI, input: &Path) -> Result<(), Box<dyn std::error::Error>> { let toml_str = std::fs::read_to_string(input)?; let raw: RawDoc = toml::from_str(&toml_str)?; let entries = parse_entries(raw); // ... process entries ... let data = bincode::serialize(&api.task_queue)?; let mut file = File::create("output.rustforge.bin")?; file.write_all(&data)?; Ok(()) }Then call it with:
if let Err(e) = pack_tasks(&mut api, &input.input) { error!("Pack failed: {}", e); }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
Cargo.lockis excluded by!**/*.lock
📒 Files selected for processing (7)
engine/proto/engine.proto(1 hunks)engine/src/bin/packer.rs(1 hunks)engine/src/bin/server.rs(10 hunks)engine/src/lib.rs(1 hunks)enginelib/src/config.rs(1 hunks)enginelib/src/events/start_event.rs(2 hunks)enginelib/src/task.rs(0 hunks)
💤 Files with no reviewable changes (1)
- enginelib/src/task.rs
🧰 Additional context used
🧬 Code graph analysis (4)
engine/proto/engine.proto (1)
enginelib/src/events/auth_event.rs (1)
Events(43-68)
enginelib/src/events/start_event.rs (1)
enginelib/src/events/mod.rs (1)
start_event(9-9)
engine/src/bin/packer.rs (3)
enginelib/src/events/mod.rs (1)
ID(11-13)enginelib/src/task.rs (2)
StoredExecutingTask(17-22)StoredTask(12-15)enginelib/src/api.rs (1)
EngineAPI(53-164)
engine/src/bin/server.rs (6)
engine/src/lib.rs (1)
get_auth(11-17)enginelib/src/events/admin_auth_event.rs (1)
CheckAdminAuth(72-81)enginelib/src/config.rs (1)
new(31-43)enginelib/tests/event_tests.rs (1)
id(18-20)enginelib/src/events/mod.rs (1)
ID(11-13)engine/src/bin/packer.rs (1)
bincode(140-140)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
- GitHub Check: Rust project - latest (nightly)
- GitHub Check: Rust project - latest (stable)
- GitHub Check: Rust project - latest (beta)
- GitHub Check: Analyze (rust)
🔇 Additional comments (14)
engine/src/bin/packer.rs (2)
113-124: LGTM!Solid error handling for file creation and writing with clear success/failure logging.
140-165: LGTM!Good defensive pattern: verifying task bytes before deserializing with
from_bytes(), and proper logging for unknown templates.engine/src/lib.rs (1)
3-17: Clean idiomatic refactoring of metadata extraction.The functional chain using
and_then,map, andunwrap_or_defaultis a concise and safe pattern for extracting optional metadata values. Both functions handle missing or invalid UTF-8 metadata gracefully by returning an empty string.enginelib/src/events/start_event.rs (1)
3-4: Good observability addition for startup logging.Logging the host at startup aids debugging and operational visibility. The change correctly references the renamed
hostfield from configuration.Also applies to: 24-24
engine/proto/engine.proto (1)
11-11: New authentication check endpoint added.The
CheckAuthRPC provides a dedicated endpoint for verifying admin credentials. The implementation inserver.rsreturnspermission_deniedon failure and an empty response on success, which is appropriate for an auth-check endpoint.enginelib/src/config.rs (1)
9-9: Field rename fromporttohostis semantically accurate.The rename correctly reflects that this field contains the full socket address (host:port), not just a port number.
Note: This is a breaking change for users with existing
config.tomlfiles—they will need to renameporttohost. Consider documenting this in release notes or migration guide.Also applies to: 16-16
engine/src/bin/server.rs (8)
37-50: Newcheck_authendpoint implementation looks correct.The implementation follows the established pattern for admin authentication checks. Passing an empty identifier
("".into(), "".into())for the target is consistent with the general auth check use case where no specific resource is being accessed.
57-65: Admin auth check for delete_task is appropriate.Task deletion is correctly gated behind admin authentication rather than user-level auth.
347-353: Improved lock handling prevents panic on poisoned lock.The
matchonout.read()gracefully handles the poisoned lock case by returning an empty payload instead of panicking. Good defensive programming.
431-476: Significant improvement in task acquisition safety and error handling.Key improvements:
- Safe key-based lookup with proper empty check before
remove(0)- Serialization and DB insertion errors now return proper
Status::internalinstead of panickingunwrap_or_default()for optional collections prevents panic on missing keys
517-574: Consistent error handling improvements in publish_task.All serialization and DB operations now properly return
Status::internalon failure. Theunwrap_or_default()pattern for optional collections is consistently applied.
596-602: Improved task ID parsing withsplitn.Using
splitn(2, ':')correctly handles task names that might contain colons, only splitting on the first occurrence. The validation for empty parts prevents accepting malformed IDs like:taskornamespace:.
643-651: Safe address parsing with fallback.The fallback to
127.0.0.1:50051handles cases where the configured IPv6 address[::1]:50051fails to parse (e.g., on IPv4-only systems). This provides good resilience.
656-668: Clean error handling for server startup.Mapping errors to
Box<dyn std::error::Error>enables consistent error propagation with?throughout the main function.
remove prototype trait
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
engine/src/bin/packer.rs (1)
39-41: Validate compound key format to prevent silent failures.If
compound_keylacks a colon or is malformed,idwill be an empty string (andnamespacewill be the full key or empty). Downstream lookups at lines 167 and 217-218 will then useID(namespace, "")orID("", id), which may silently fail to match any template in the registry.Consider validating the split result or logging a warning when namespace or id is empty.
for (compound_key, records) in raw.0 { // split on colon: "widget:button" -> ("widget", "button") let mut parts = compound_key.splitn(2, ':'); let namespace = parts.next().unwrap_or("").to_string(); let id = parts.next().unwrap_or("").to_string(); + + if namespace.is_empty() || id.is_empty() { + error!("Invalid compound key format '{}': expected 'namespace:id'", compound_key); + continue; + } for data in records {
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
engine/src/bin/packer.rs(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
engine/src/bin/packer.rs (3)
enginelib/src/config.rs (1)
new(31-43)enginelib/src/events/mod.rs (1)
ID(11-13)enginelib/tests/event_tests.rs (1)
id(18-20)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Analyze (rust)
🔇 Additional comments (3)
engine/src/bin/packer.rs (3)
113-124: Well-structured error handling.The nested match statements properly log failures at both the file creation and write stages, preventing silent failures.
163-204: Past review feedback properly addressed.The output file is now written only when deserialization succeeds (inside the
if let Some(k) = maybe_queueblock). This prevents the issue flagged in the previous review where an empty output file was created even when errors occurred.
210-288: Robust error handling throughout the Pack command.The nested match structure ensures that:
- File read failures are logged and prevent further processing
- TOML parse errors are logged and prevent serialization
- Per-entry template lookup and conversion failures are logged without stopping processing of other entries
- Serialization and file write failures are properly logged
This comprehensive approach prevents silent failures and provides clear diagnostic information.
| let mut final_out: Vec<String> = Vec::new(); | ||
|
|
||
| for tasks in k.tasks { | ||
| match api.task_registry.tasks.get(&tasks.0.clone()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Search for all task_registry access patterns
rg -n 'task_registry\.(tasks\.)?get' --type rust -C 2Repository: GrandEngineering/engine
Length of output: 1224
🏁 Script executed:
#!/bin/bash
# Read lines around 217-218 in packer.rs
sed -n '210,225p' engine/src/bin/packer.rs
# Search for TaskRegistry struct definition
rg -n 'struct TaskRegistry|impl.*TaskRegistry' --type rust -A 5Repository: GrandEngineering/engine
Length of output: 1585
🏁 Script executed:
#!/bin/bash
# Find TaskRegistry struct definition
rg -n 'struct.*TaskRegistry|pub struct.*TaskRegistry' --type rust -A 10
# Find Registry trait definition
rg -n 'trait Registry' --type rust -A 10Repository: GrandEngineering/engine
Length of output: 1086
🏁 Script executed:
#!/bin/bash
# Read full context around line 167 to understand usage
sed -n '165,175p' engine/src/bin/packer.rsRepository: GrandEngineering/engine
Length of output: 727
🏁 Script executed:
#!/bin/bash
# Find the actual implementation of the get() method for EngineTaskRegistry
rg -n 'fn get' enginelib/src/api.rs -A 5 | head -20Repository: GrandEngineering/engine
Length of output: 315
Use the consistent .get() method instead of direct field access.
Line 167 uses api.task_registry.tasks.get(...) (direct HashMap access) while the rest of the codebase uses api.task_registry.get(...) (the Registry trait method). Both work functionally but return different types—Arc<dyn Task> vs Box<dyn Task> respectively. For consistency with the Registry API pattern used elsewhere (e.g., lines 217-218, server.rs:528, server.rs:603), use .get() instead.
🤖 Prompt for AI Agents
In engine/src/bin/packer.rs around line 167, replace the direct HashMap access
api.task_registry.tasks.get(&tasks.0.clone()) with the Registry API call
api.task_registry.get(&tasks.0) to match the rest of the codebase; update any
downstream handling to accept the type returned by api.task_registry.get (adjust
variable ownership/borrowing or convert the returned Box/Arc as needed) so the
code uses the registry's .get() method consistently.
Summary by CodeRabbit
New Features
Bug Fixes
Configuration Changes
Breaking Changes
✏️ Tip: You can customize this high-level summary in your review settings.