Skip to content

Conversation

@Alw3ys
Copy link
Member

@Alw3ys Alw3ys commented Oct 22, 2025

Idle Mode (20 seconds):

  • Default state when there are no commands
  • Pings home every 20 seconds

Active Mode (1 second):

  • Switches to this mode immediately when commands are received
  • Pings home every 1 second for fast command execution

Back to Idle:

  • After 60 consecutive ticks with empty commands, switches back to 20-second interval
  • In active mode (1 second), this means 60 seconds of inactivity

@Alw3ys Alw3ys requested a review from LudeeD October 22, 2025 12:14
@coderabbitai
Copy link

coderabbitai bot commented Oct 22, 2025

Walkthrough

Adds adaptive polling to Postman: tracks inactivity via a new idle_ticks_count field and switches polling between active (1s) and idle (20s) intervals based on command queue activity, logging mode transitions; no public API changes.

Changes

Cohort / File(s) Change Summary
Postman polling mode implementation
smithd/src/postman/mod.rs
Adds idle_ticks_count: u32 and initializes it. Introduces constants IDLE_INTERVAL_SECS (20), ACTIVE_INTERVAL_SECS (1), IDLE_THRESHOLD_TICKS (60). Main loop now switches to active polling when commands are present (resets idle_ticks_count), increments idle_ticks_count when idle, switches to idle polling after threshold, and logs mode transitions. update_interval behavior preserved.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant CmdSrc as ExternalCommandSource
  participant Postman
  participant Queue as CommandQueue
  participant Timer as KeepAliveTimer
  participant Net as Network

  Note over Postman,Timer: Postman maintains idle_ticks_count and keep_alive_interval

  CmdSrc->>Postman: enqueue command
  Postman->>Queue: check for commands
  alt commands present
    Postman->>Postman: keep_alive_interval = ACTIVE_INTERVAL_SECS (1)\nidle_ticks_count = 0
    Postman->>Timer: schedule next tick (1s)
  else no commands
    Postman->>Postman: idle_ticks_count += 1
    alt idle_ticks_count >= IDLE_THRESHOLD_TICKS
      Postman->>Postman: keep_alive_interval = IDLE_INTERVAL_SECS (20)\nidle_ticks_count = 0
      Postman->>Timer: schedule next tick (20s)
    else
      Postman->>Timer: schedule next tick (current interval)
    end
  end

  Timer->>Postman: tick
  Postman->>Net: send keep-alive / perform update
  Net-->>Postman: response
Loading

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat: idle mode' directly and clearly describes the main feature being added to the Postman module - an idle mode with dynamic polling interval switching.
Description check ✅ Passed The description provides relevant details about the idle/active mode switching behavior, explaining the three states and their intervals, which aligns with the changeset modifications.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/idle-mode

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a 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

🧹 Nitpick comments (1)
smithd/src/postman/mod.rs (1)

90-92: Consider moving constants to module or impl level.

The constants are correctly defined, but they're currently function-scoped. Consider moving them to module level or as associated constants of the Postman impl block for better visibility and potential reusability.

Example:

+const IDLE_INTERVAL_SECS: u64 = 20;
+const ACTIVE_INTERVAL_SECS: u64 = 1;
+const IDLE_THRESHOLD_TICKS: u32 = 60;
+
 struct Postman {
     shutdown: ShutdownSignals,
     ...

Or as associated constants:

 impl Postman {
+    const IDLE_INTERVAL_SECS: u64 = 20;
+    const ACTIVE_INTERVAL_SECS: u64 = 1;
+    const IDLE_THRESHOLD_TICKS: u32 = 60;
+
     fn new(
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 66aa3ca and ff1942b.

📒 Files selected for processing (1)
  • smithd/src/postman/mod.rs (4 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
smithd/src/postman/mod.rs (1)
smithd/src/commander/mod.rs (1)
  • execute_api_batch (246-253)
🔇 Additional comments (3)
smithd/src/postman/mod.rs (3)

28-28: LGTM!

The field addition is appropriate for tracking consecutive idle ticks.


54-54: LGTM!

Proper initialization of the idle tick counter.


94-94: LGTM!

Proper initialization using the idle interval constant.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
smithd/src/postman/mod.rs (1)

128-139: Optional: Consider incrementing counter only in active mode.

While the current implementation is correct, you could optimize by only incrementing idle_ticks_count when in active mode, avoiding unnecessary counting during idle periods:

                 } else {
-                    self.idle_ticks_count += 1;
-                    if self.idle_ticks_count >= IDLE_THRESHOLD_TICKS {
-                        let current_period = keep_alive_interval.period();
-                        if current_period.as_secs() != IDLE_INTERVAL_SECS {
-                            info!("Switching to idle polling mode (20 second interval)");
-                            keep_alive_interval = time::interval(Duration::from_secs(IDLE_INTERVAL_SECS));
-                            keep_alive_interval.reset();
-                        }
-                        self.idle_ticks_count = 0;
+                    let current_period = keep_alive_interval.period();
+                    if current_period.as_secs() == ACTIVE_INTERVAL_SECS {
+                        self.idle_ticks_count += 1;
+                        if self.idle_ticks_count >= IDLE_THRESHOLD_TICKS {
+                            info!("Switching to idle polling mode (20 second interval)");
+                            keep_alive_interval = time::interval(Duration::from_secs(IDLE_INTERVAL_SECS));
+                            keep_alive_interval.reset();
+                            self.idle_ticks_count = 0;
+                        }
                     }
                 }

This eliminates the counter cycling 0→59 every 20 minutes while already idle. However, the current explicit approach is also acceptable.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ff1942b and f238783.

📒 Files selected for processing (1)
  • smithd/src/postman/mod.rs (4 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
smithd/src/postman/mod.rs (1)
smithd/src/commander/mod.rs (1)
  • execute_api_batch (246-253)
⏰ 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: test
🔇 Additional comments (5)
smithd/src/postman/mod.rs (5)

90-92: LGTM! Constants align with PR objectives.

The constants correctly implement the intended behavior: 20-second idle polling, 1-second active polling, and 60 ticks (= 60 seconds at active rate) before returning to idle.


28-28: Appropriate field addition.

The idle_ticks_count: u32 field correctly tracks consecutive ticks without commands, with sufficient range for the counter.


94-94: Correct initial state.

Starting with IDLE_INTERVAL_SECS properly implements the "Default Idle Mode" requirement from the PR objectives.


117-127: Active mode switching implemented correctly.

The logic properly:

  • Resets the idle counter when commands arrive
  • Checks if already in active mode before switching (avoiding unnecessary interval recreation)
  • Uses reset() to start the new interval fresh
  • Logs the transition for observability

128-139: Idle mode logic is correct and addresses previous review concern.

The implementation properly handles the transition to idle mode:

  • Increments counter when no commands arrive
  • When threshold is reached, checks if already in idle mode before switching
  • Importantly, line 137 resets idle_ticks_count = 0 unconditionally (outside the inner conditional), which fixes the unbounded counter growth issue flagged in the previous review

The behavior is correct: in active mode, 60 ticks = 60 seconds of inactivity triggers the switch to idle, as intended.

Co-authored-by: Søren Hansen <soerenhh@pm.me>
@Alw3ys Alw3ys requested a review from dduuukk as a code owner December 18, 2025 10:44
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (2)
smithd/src/postman/mod.rs (2)

90-95: LGTM! Interval setup is correct.

The constants clearly define the polling behavior, and starting in idle mode (20s interval) with MissedTickBehavior::Skip aligns with the PR objectives and prevents API spam if the system is slow.

💡 Optional: Consider module-level constants for better organization

Moving the constants to module level (above the Postman struct) would improve organization and make them easier to tune:

+const IDLE_INTERVAL_SECS: u64 = 20;
+const ACTIVE_INTERVAL_SECS: u64 = 1;
+const IDLE_THRESHOLD_TICKS: u32 = 60;
+
 struct Postman {
     ...

Then remove the const declarations inside run().


118-140: Logic is correct and handles mode transitions properly.

The implementation correctly:

  • Switches from idle to active immediately when commands arrive
  • Switches from active to idle after 60 seconds of inactivity
  • Resets idle_ticks_count unconditionally at line 138 (fixing the unbounded growth issue from past reviews)
💡 Optional: Eliminate unnecessary counter increments in idle mode

Currently, idle_ticks_count increments even when already in idle mode, wasting CPU cycles every 20 seconds. Consider only incrementing the counter when in active mode:

                 } else {
-                    self.idle_ticks_count += 1;
-                    if self.idle_ticks_count >= IDLE_THRESHOLD_TICKS {
-                        let current_period = keep_alive_interval.period();
-                        if current_period.as_secs() != IDLE_INTERVAL_SECS {
-                            info!("Switching to idle polling mode (20 second interval)");
-                            keep_alive_interval = time::interval(Duration::from_secs(IDLE_INTERVAL_SECS));
-                            keep_alive_interval.reset();
-                        }
-                        self.idle_ticks_count = 0;
+                    let current_period = keep_alive_interval.period();
+                    if current_period.as_secs() == ACTIVE_INTERVAL_SECS {
+                        self.idle_ticks_count += 1;
+                        if self.idle_ticks_count >= IDLE_THRESHOLD_TICKS {
+                            info!("Switching to idle polling mode (20 second interval)");
+                            keep_alive_interval = time::interval(Duration::from_secs(IDLE_INTERVAL_SECS));
+                            keep_alive_interval.reset();
+                            self.idle_ticks_count = 0;
+                        }
                     }
                 }

This avoids counting and resetting every 60 ticks (20 minutes) when already idle.

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f238783 and 7c95bb1.

📒 Files selected for processing (1)
  • smithd/src/postman/mod.rs (4 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
smithd/src/postman/mod.rs (1)
smithd/src/commander/mod.rs (1)
  • execute_api_batch (246-253)
⏰ 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: test
🔇 Additional comments (2)
smithd/src/postman/mod.rs (2)

28-28: LGTM!

The idle_ticks_count field is appropriately typed as u32 and integrates cleanly into the struct.


54-54: LGTM!

Initialization to 0 is correct for tracking idle ticks from the start.


let mut keep_alive_interval = time::interval(Duration::from_secs(20));
const IDLE_INTERVAL_SECS: u64 = 20;
const ACTIVE_INTERVAL_SECS: u64 = 1;
Copy link
Contributor

Choose a reason for hiding this comment

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

This could potentially bombard the api when you multiply across all the devices. Think we should be pretty careful here. What is the reason for this change?

Copy link
Contributor

@SorenHolstHansen SorenHolstHansen Jan 8, 2026

Choose a reason for hiding this comment

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

Perhaps we should reconsider our polling setup altogether if this is a requirement. Why not just use websockets at this point, or a broker of some sort if we want to deal with that

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.

2 participants