diff options
| author | diogo464 <[email protected]> | 2025-06-19 10:03:56 +0100 |
|---|---|---|
| committer | diogo464 <[email protected]> | 2025-06-19 10:03:56 +0100 |
| commit | 5101d9c410a7c901ea20636d2a4e56b3282a1c14 (patch) | |
| tree | 4b229f6ced108f14957a7e80c2c30880f7174811 /IMPLEMENTATION_PLAN.md | |
| parent | 7b7dbf8948fa063d040a744a4903be1df75ca943 (diff) | |
Add wait subcommand for blocking until process termination
Implements a new 'wait' subcommand that blocks until a specified daemon process terminates, with configurable timeout and polling interval.
Features:
- Default 30-second timeout, configurable with --timeout flag
- Infinite wait with --timeout 0
- Configurable polling interval with --interval flag (default 1 second)
- Quiet operation - only shows errors on failure
- Preserves PID files (doesn't clean up)
- Exit codes: 0 for success, 1 for failure
Usage examples:
- demon wait my-process # Wait 30s
- demon wait my-process --timeout 0 # Wait indefinitely
- demon wait my-process --timeout 60 --interval 2 # Custom timeout/interval
Added comprehensive test suite covering:
- Non-existent processes
- Already terminated processes
- Normal process termination
- Timeout scenarios
- Infinite timeout behavior
- Custom polling intervals
Updated documentation:
- README.md with wait command reference and usage examples
- LLM guide with detailed wait command documentation
- Integration examples for development workflows
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <[email protected]>
Diffstat (limited to 'IMPLEMENTATION_PLAN.md')
| -rw-r--r-- | IMPLEMENTATION_PLAN.md | 140 |
1 files changed, 139 insertions, 1 deletions
diff --git a/IMPLEMENTATION_PLAN.md b/IMPLEMENTATION_PLAN.md index eaa1e64..56c3caf 100644 --- a/IMPLEMENTATION_PLAN.md +++ b/IMPLEMENTATION_PLAN.md | |||
| @@ -172,4 +172,142 @@ The implementation follows the planned modular structure: | |||
| 172 | - **File Operations**: Manages PID files and log redirection ✅ | 172 | - **File Operations**: Manages PID files and log redirection ✅ |
| 173 | - **Output Display**: Implements both cat and tail functionality ✅ | 173 | - **Output Display**: Implements both cat and tail functionality ✅ |
| 174 | 174 | ||
| 175 | The tool is ready for production use! \ No newline at end of file | 175 | --- |
| 176 | |||
| 177 | # Wait Subcommand Implementation Plan | ||
| 178 | |||
| 179 | ## Overview | ||
| 180 | Add a `wait` subcommand to the demon CLI that blocks until a specified process terminates, with configurable timeout and polling interval. | ||
| 181 | |||
| 182 | ## Requirements Summary | ||
| 183 | - **Default timeout**: 30 seconds | ||
| 184 | - **Infinite timeout**: Use `--timeout 0` | ||
| 185 | - **Exit codes**: 0 for success, 1 for failure | ||
| 186 | - **PID file**: Leave untouched (don't clean up) | ||
| 187 | - **Output**: Quiet operation, only show error messages | ||
| 188 | - **Polling interval**: 1 second default, configurable with `--interval` flag | ||
| 189 | |||
| 190 | ## Implementation Details | ||
| 191 | |||
| 192 | ### 1. Command Structure | ||
| 193 | ```rust | ||
| 194 | /// Wait for a daemon process to terminate | ||
| 195 | Wait(WaitArgs), | ||
| 196 | ``` | ||
| 197 | |||
| 198 | ### 2. Arguments Structure | ||
| 199 | ```rust | ||
| 200 | #[derive(Args)] | ||
| 201 | struct WaitArgs { | ||
| 202 | /// Process identifier | ||
| 203 | id: String, | ||
| 204 | |||
| 205 | /// Timeout in seconds (0 = infinite) | ||
| 206 | #[arg(long, default_value = "30")] | ||
| 207 | timeout: u64, | ||
| 208 | |||
| 209 | /// Polling interval in seconds | ||
| 210 | #[arg(long, default_value = "1")] | ||
| 211 | interval: u64, | ||
| 212 | } | ||
| 213 | ``` | ||
| 214 | |||
| 215 | ### 3. Core Function Implementation | ||
| 216 | ```rust | ||
| 217 | fn wait_daemon(id: &str, timeout: u64, interval: u64) -> Result<()> { | ||
| 218 | // 1. Check if PID file exists | ||
| 219 | // 2. Read PID from file | ||
| 220 | // 3. Check if process exists initially | ||
| 221 | // 4. If timeout == 0, loop indefinitely | ||
| 222 | // 5. Otherwise, loop with timeout tracking | ||
| 223 | // 6. Poll every `interval` seconds | ||
| 224 | // 7. Return appropriate exit codes | ||
| 225 | } | ||
| 226 | ``` | ||
| 227 | |||
| 228 | ### 4. Logic Flow | ||
| 229 | 1. **Initial validation**: | ||
| 230 | - Check if PID file exists → error if not | ||
| 231 | - Read PID from file → error if invalid | ||
| 232 | - Check if process is running → error if already dead | ||
| 233 | |||
| 234 | 2. **Waiting loop**: | ||
| 235 | - If timeout = 0: infinite loop | ||
| 236 | - Otherwise: track elapsed time | ||
| 237 | - Poll every `interval` seconds using `is_process_running_by_pid()` | ||
| 238 | - Break when process terminates or timeout reached | ||
| 239 | |||
| 240 | 3. **Exit conditions**: | ||
| 241 | - Process terminates → exit 0 | ||
| 242 | - Timeout reached → error message + exit 1 | ||
| 243 | - Initial errors → error message + exit 1 | ||
| 244 | |||
| 245 | ### 5. Error Messages | ||
| 246 | - "Process '{id}' not found (no PID file)" | ||
| 247 | - "Process '{id}' is not running" | ||
| 248 | - "Timeout reached waiting for process '{id}' to terminate" | ||
| 249 | |||
| 250 | ## Testing Strategy | ||
| 251 | |||
| 252 | ### New Tests | ||
| 253 | 1. **test_wait_nonexistent_process**: Should fail with appropriate error | ||
| 254 | 2. **test_wait_already_dead_process**: Should fail when process already terminated | ||
| 255 | 3. **test_wait_process_terminates**: Should succeed when process terminates normally | ||
| 256 | 4. **test_wait_timeout**: Should fail when timeout is reached | ||
| 257 | 5. **test_wait_infinite_timeout**: Test with timeout=0 (use short-lived process) | ||
| 258 | 6. **test_wait_custom_interval**: Test with different polling intervals | ||
| 259 | |||
| 260 | ### Updated Tests | ||
| 261 | Replace `std::thread::sleep(Duration::from_millis(100))` with `demon wait` in: | ||
| 262 | - `test_run_creates_files` → `demon wait test --timeout 5` | ||
| 263 | - `test_run_with_complex_command` → `demon wait complex --timeout 5` | ||
| 264 | - Similar tests that wait for process completion | ||
| 265 | |||
| 266 | ## Files to Modify | ||
| 267 | |||
| 268 | ### 1. src/main.rs | ||
| 269 | - Add `Wait(WaitArgs)` to `Commands` enum (around line 146) | ||
| 270 | - Add `WaitArgs` struct after other Args structs (around line 206) | ||
| 271 | - Add `Commands::Wait(args) => wait_daemon(&args.id, args.timeout, args.interval)` to match statement (around line 246) | ||
| 272 | - Implement `wait_daemon()` function (add after other daemon functions) | ||
| 273 | |||
| 274 | ### 2. tests/cli.rs | ||
| 275 | - Add new test functions for wait subcommand | ||
| 276 | - Update existing tests to use wait instead of sleep where appropriate | ||
| 277 | |||
| 278 | ### 3. README.md | ||
| 279 | - Add wait command to command reference section | ||
| 280 | - Add examples showing wait usage | ||
| 281 | |||
| 282 | ### 4. LLM Guide (print_llm_guide function) | ||
| 283 | - Add wait command documentation | ||
| 284 | - Add to available commands list | ||
| 285 | - Add usage examples | ||
| 286 | |||
| 287 | ## Command Usage Examples | ||
| 288 | |||
| 289 | ```bash | ||
| 290 | # Wait with default 30s timeout | ||
| 291 | demon wait my-process | ||
| 292 | |||
| 293 | # Wait indefinitely | ||
| 294 | demon wait my-process --timeout 0 | ||
| 295 | |||
| 296 | # Wait with custom timeout and interval | ||
| 297 | demon wait my-process --timeout 60 --interval 2 | ||
| 298 | ``` | ||
| 299 | |||
| 300 | ## Implementation Order | ||
| 301 | 1. Implement core functionality in main.rs | ||
| 302 | 2. Add comprehensive tests | ||
| 303 | 3. Update existing tests to use wait | ||
| 304 | 4. Update documentation (README + LLM guide) | ||
| 305 | 5. Test full integration | ||
| 306 | |||
| 307 | ## Key Implementation Notes | ||
| 308 | - Use existing `is_process_running_by_pid()` function for consistency | ||
| 309 | - Use existing `PidFile::read_from_file()` for PID file handling | ||
| 310 | - Follow existing error handling patterns with anyhow | ||
| 311 | - Use `std::thread::sleep(Duration::from_secs(interval))` for polling | ||
| 312 | - Track elapsed time for timeout implementation | ||
| 313 | - Maintain quiet operation - no progress messages \ No newline at end of file | ||
