Skip to content

feat: add time-based gRPC stream optimization#1000

Open
thlorenz wants to merge 5 commits intomasterfrom
thlorenz/gprc-optimization-timer
Open

feat: add time-based gRPC stream optimization#1000
thlorenz wants to merge 5 commits intomasterfrom
thlorenz/gprc-optimization-timer

Conversation

@thlorenz
Copy link
Collaborator

@thlorenz thlorenz commented Feb 26, 2026

Summary

Add time-based optimization interval to guarantee per-second optimizations in the gRPC chain laser actor, preventing optimization starvation when subscription count thresholds aren't reached.

Details

The chain laser actor previously relied solely on subscription count thresholds to trigger stream optimizations. This could lead to unoptimized streams persisting indefinitely if subscriptions didn't exceed the limits. The new time-based interval ensures streams are optimized at least once per configured interval (defaults to 60 seconds), providing a safety mechanism for consistent performance.

Configuration

Added max_time_without_optimization_secs configuration parameter to the gRPC config with a default value of 60 seconds. This can be overridden via the MBV_GRPC__MAX_TIME_WITHOUT_OPTIMIZATION_SECS environment variable.

Chain Laser Actor

Integrated a tokio interval timer into the actor's main event loop that periodically triggers optimization if unoptimized streams exist. The interval is reset whenever an optimization occurs (either event-based or time-based), preventing redundant optimizations. This uses a simple flag-based approach to communicate optimization completion between the stream manager and actor.

Stream Manager

Added helper methods to support the time-based optimization mechanism:

  • has_unoptimized_streams() - checks if old unoptimized handles exist
  • take_optimized_flag() - retrieves and resets the optimization flag

Summary by CodeRabbit

  • New Features

    • Time-based periodic optimization: the system now triggers optimization checks at regular, configurable intervals in addition to event-driven triggers.
  • Configuration

    • Added a new setting to control the optimization interval (default: 60 seconds); configurable via config or environment.
  • Tests

    • Added tests verifying the new configuration is parsed and applied.
  • Documentation

    • Minor example config/comment clean-up.

@github-actions
Copy link

github-actions bot commented Feb 26, 2026

Manual Deploy Available

You can trigger a manual deploy of this PR branch to testnet:

Deploy to Testnet 🚀

Alternative: Comment /deploy on this PR to trigger deployment directly.

⚠️ Note: Manual deploy requires authorization. Only authorized users can trigger deployments.

Comment updated automatically when the PR is synchronized.

@thlorenz thlorenz marked this pull request as draft February 26, 2026 05:38
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 26, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1afb191 and 73d096e.

📒 Files selected for processing (1)
  • magicblock-chainlink/src/remote_account_provider/chain_laser_actor/actor.rs

📝 Walkthrough

Walkthrough

Adds a new gRPC configuration max_time_without_optimization_secs (default 60) on GrpcConfig. ChainLaserActor gains an optimization_interval_duration field initialized from that config (minimum 10s) and runs a tokio interval to trigger periodic stream_manager.optimize() when unoptimized streams exist, resetting the interval when optimizations occur or are observed. StreamManager adds has_unoptimized_streams() and take_optimized_flag() backed by an internal optimized_since_last_check flag. Tests and example config parsing were updated to cover the new field and env var override.

Suggested reviewers

  • GabrielePicco
✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch thlorenz/gprc-optimization-timer

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.

❤️ Share

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

Copy link
Contributor

@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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
magicblock-config/src/tests.rs (1)

479-553: 🧹 Nitpick | 🔵 Trivial

Add a boundary test for MBV_GRPC__MAX_TIME_WITHOUT_OPTIMIZATION_SECS=0.

Great coverage for defaults and overrides; please also lock in behavior for 0 (reject or clamp) to prevent regressions around interval construction.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@magicblock-config/src/tests.rs` around lines 479 - 553, Add a new unit test
(e.g., test_env_vars_grpc_zero_timeout) that sets
MBV_GRPC__MAX_TIME_WITHOUT_OPTIMIZATION_SECS to "0" using EnvVarGuard (same
pattern as test_env_vars_full_coverage), calls run_cli(vec![]) and then asserts
the resulting config.grpc.max_time_without_optimization_secs equals 0 to lock in
the zero-boundary behavior for the interval parsing in the gRPC config; place
the new test near test_env_vars_full_coverage and reference the
MBV_GRPC__MAX_TIME_WITHOUT_OPTIMIZATION_SECS env var and the
config.grpc.max_time_without_optimization_secs field in the assertion.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@magicblock-chainlink/src/remote_account_provider/chain_laser_actor/actor.rs`:
- Around line 231-233: The code constructs optimization_interval_duration from
grpc_config.max_time_without_optimization_secs and later uses it to create a
tokio::time::interval which panics on a zero Duration; update the construction
of optimization_interval_duration (and/or validate
grpc_config.max_time_without_optimization_secs earlier) to enforce a minimum of
1 second (e.g., clamp the value to at least 1 when computing
optimization_interval_duration used by Self and by the tokio::time::interval
call), or return an error if the config is invalid; reference the symbols
optimization_interval_duration, grpc_config.max_time_without_optimization_secs,
and the tokio::time::interval usage in actor.rs when applying the fix.

---

Outside diff comments:
In `@magicblock-config/src/tests.rs`:
- Around line 479-553: Add a new unit test (e.g.,
test_env_vars_grpc_zero_timeout) that sets
MBV_GRPC__MAX_TIME_WITHOUT_OPTIMIZATION_SECS to "0" using EnvVarGuard (same
pattern as test_env_vars_full_coverage), calls run_cli(vec![]) and then asserts
the resulting config.grpc.max_time_without_optimization_secs equals 0 to lock in
the zero-boundary behavior for the interval parsing in the gRPC config; place
the new test near test_env_vars_full_coverage and reference the
MBV_GRPC__MAX_TIME_WITHOUT_OPTIMIZATION_SECS env var and the
config.grpc.max_time_without_optimization_secs field in the assertion.

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1271b9f and 8040112.

📒 Files selected for processing (5)
  • config.example.toml
  • magicblock-chainlink/src/remote_account_provider/chain_laser_actor/actor.rs
  • magicblock-chainlink/src/remote_account_provider/chain_laser_actor/stream_manager.rs
  • magicblock-config/src/config/grpc.rs
  • magicblock-config/src/tests.rs

Copy link
Contributor

@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.

♻️ Duplicate comments (1)
magicblock-chainlink/src/remote_account_provider/chain_laser_actor/actor.rs (1)

231-233: ⚠️ Potential issue | 🔴 Critical

Prevent runtime panic when the optimization interval is configured as 0.

Line 232 accepts max_time_without_optimization_secs as-is, and Line 263 passes it to tokio::time::interval. If config/env sets it to 0, actor startup will panic.

Proposed fix
-        let optimization_interval_duration =
-            Duration::from_secs(grpc_config.max_time_without_optimization_secs);
+        let configured_secs = grpc_config.max_time_without_optimization_secs;
+        let optimization_interval_duration =
+            Duration::from_secs(configured_secs.max(1));
+        if configured_secs == 0 {
+            warn!(
+                client_id = %client_id,
+                "MBV_GRPC__MAX_TIME_WITHOUT_OPTIMIZATION_SECS=0 is invalid; clamping to 1s"
+            );
+        }

Use this read-only script to verify whether a zero guard exists at actor/config boundaries:

#!/bin/bash
set -euo pipefail

echo "=== Interval construction and source value ==="
rg -n "max_time_without_optimization_secs|optimization_interval_duration|tokio::time::interval|Duration::from_secs" \
  magicblock-chainlink/src/remote_account_provider/chain_laser_actor/actor.rs \
  magicblock-config/src/config/grpc.rs \
  magicblock-config/src/tests.rs

echo
echo "=== Zero-value guards/validation checks ==="
rg -n "max_time_without_optimization_secs.*==\\s*0|==\\s*0.*max_time_without_optimization_secs|max\\(1\\)|NonZeroU64|assert!\\(.*max_time_without_optimization_secs" \
  magicblock-chainlink/src/remote_account_provider/chain_laser_actor/actor.rs \
  magicblock-config/src/config/grpc.rs \
  magicblock-config/src/tests.rs || true

Expected result: if no guard/validation hits appear, the panic path is still possible.

Also applies to: 262-263

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@magicblock-chainlink/src/remote_account_provider/chain_laser_actor/actor.rs`
around lines 231 - 233, The actor currently constructs
optimization_interval_duration directly from
grpc_config.max_time_without_optimization_secs and later passes it into
tokio::time::interval, which will panic if the value is 0; update the code that
creates optimization_interval_duration (the Duration::from_secs call that uses
max_time_without_optimization_secs) to guard or clamp zero values (e.g. treat 0
as 1) before constructing the Duration or validate and return an error, ensuring
the same check is applied at the config boundary or immediately inside the actor
initialization so tokio::time::interval never receives a zero duration; refer to
the symbols grpc_config.max_time_without_optimization_secs,
optimization_interval_duration and tokio::time::interval when making the change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@magicblock-chainlink/src/remote_account_provider/chain_laser_actor/actor.rs`:
- Around line 231-233: The actor currently constructs
optimization_interval_duration directly from
grpc_config.max_time_without_optimization_secs and later passes it into
tokio::time::interval, which will panic if the value is 0; update the code that
creates optimization_interval_duration (the Duration::from_secs call that uses
max_time_without_optimization_secs) to guard or clamp zero values (e.g. treat 0
as 1) before constructing the Duration or validate and return an error, ensuring
the same check is applied at the config boundary or immediately inside the actor
initialization so tokio::time::interval never receives a zero duration; refer to
the symbols grpc_config.max_time_without_optimization_secs,
optimization_interval_duration and tokio::time::interval when making the change.

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8040112 and dc6944a.

📒 Files selected for processing (1)
  • magicblock-chainlink/src/remote_account_provider/chain_laser_actor/actor.rs

@thlorenz thlorenz marked this pull request as ready for review February 26, 2026 06:49
Copy link
Contributor

@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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@magicblock-chainlink/src/remote_account_provider/chain_laser_actor/actor.rs`:
- Around line 263-267: The tokio interval created in actor.rs with let mut
optimization_interval =
tokio::time::interval(self.optimization_interval_duration) uses the default
Burst behavior which can emit many missed ticks after a stall; change it to
explicitly set the missed-tick behavior (for example call
optimization_interval.set_missed_tick_behavior(tokio::time::MissedTickBehavior::Delay)
right after creating the interval) so optimize() is not invoked in a rapid burst
after delays, and keep the existing optimization_interval.tick().await
consumption of the immediate first tick.

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between dc6944a and 1afb191.

📒 Files selected for processing (1)
  • magicblock-chainlink/src/remote_account_provider/chain_laser_actor/actor.rs

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.

1 participant