-
Notifications
You must be signed in to change notification settings - Fork 19
feat: enhance subscription management with metrics and reconnection #621
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
base: master
Are you sure you want to change the base?
Conversation
* master: hotfix: unregistered metric COMMITTOR_INTENT_CU_USAGE (#612) feat: add metrics for intent execution time (#607) fix: don't increment subscription id for dups (#610) chore: broaden dependency range on the magic program api (#609) feat: parallel CI integration tests (#605) Handle uncleaned buffers + generalized tx send retries (#597) fix: support binary opcode (#604) fix: correct log imports (#606)
Manual Deploy AvailableYou can trigger a manual deploy of this PR branch to testnet: Alternative: Comment
Comment updated automatically when the PR is synchronized. |
WalkthroughReplace PubsubClient with PubSubConnection; add reconnect/abort flow, health probes, per-client reconnect orchestration, and CancellationTokens; switch subscription storage to an LRU with optional subscription metrics and a background updater; extend ChainPubsubClient with reconnection APIs; update logging, tests, and workspace manifests. (50 words) Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant SubMux
participant ChainActor as ChainPubsubActor
participant PubSubConn as PubSubConnection
participant Abort as Abort Sender
rect rgb(240,248,255)
Note over Client,ChainActor: Subscribe path (LRU + register)
Client->>SubMux: subscribe(pubkey)
SubMux->>ChainActor: register_subscription(pubkey)
ChainActor->>PubSubConn: account_subscribe(pubkey)
PubSubConn-->>ChainActor: subscription_stream (updates)
end
rect rgb(255,240,245)
Note over PubSubConn,Abort: Connection error -> abort & reconnect
PubSubConn--xChainActor: connection failure
ChainActor->>Abort: send abort()
Abort->>SubMux: notify reconnection task
SubMux->>SubMux: reconnect_client_with_backoff()
SubMux->>ChainActor: try_reconnect()
ChainActor->>PubSubConn: reconnect probe (subscribe/unsubscribe)
PubSubConn-->>ChainActor: probe success
ChainActor->>SubMux: resubscribe restored subs
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes
Possibly related issues
Possibly related PRs
Suggested reviewers
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ 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: 4
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
magicblock-chainlink/src/chainlink/fetch_cloner.rs (1)
1027-1040: Fix the function name in the log message and remove duplicate error logging.Line 1032: The log message references "FetchCloner::clone_accounts" but the actual function is
fetch_and_clone_accounts_with_dedup.Lines 1031-1038: There's redundant error logging—
inspect_errlogs a detailed warning (including the pubkey), and then theerror!macro logs the same error again without the pubkey. This creates noise and the second log provides less information.Apply this diff to fix the function name and remove the redundant log:
if let Err(err) = receiver .await .inspect_err(|err| { - warn!("FetchCloner::clone_accounts - RecvError occurred while awaiting account {}: {err:?}. This indicates the account fetch sender was dropped without sending a value.", pubkey); + warn!("FetchCloner::fetch_and_clone_accounts_with_dedup - RecvError occurred while awaiting account {}: {err:?}. This indicates the account fetch sender was dropped without sending a value.", pubkey); }) { - // The sender was dropped, likely due to an error in the other request - error!( - "Failed to receive account from pending request: {err}" - ); + // Error already logged by inspect_err above }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
⛔ Files ignored due to path filters (2)
Cargo.lockis excluded by!**/*.locktest-integration/Cargo.lockis excluded by!**/*.lock
📒 Files selected for processing (21)
Cargo.toml(1 hunks)magicblock-aperture/src/requests/http/mod.rs(1 hunks)magicblock-aperture/src/requests/http/send_transaction.rs(1 hunks)magicblock-chainlink/Cargo.toml(2 hunks)magicblock-chainlink/src/chainlink/errors.rs(1 hunks)magicblock-chainlink/src/chainlink/fetch_cloner.rs(2 hunks)magicblock-chainlink/src/remote_account_provider/chain_pubsub_actor.rs(8 hunks)magicblock-chainlink/src/remote_account_provider/chain_pubsub_client.rs(11 hunks)magicblock-chainlink/src/remote_account_provider/config.rs(4 hunks)magicblock-chainlink/src/remote_account_provider/lru_cache.rs(2 hunks)magicblock-chainlink/src/remote_account_provider/mod.rs(24 hunks)magicblock-chainlink/src/submux/mod.rs(20 hunks)magicblock-chainlink/src/testing/chain_pubsub.rs(1 hunks)magicblock-metrics/src/metrics/mod.rs(1 hunks)test-integration/Cargo.toml(1 hunks)test-integration/test-chainlink/src/test_context.rs(1 hunks)test-integration/test-chainlink/tests/ix_exceed_capacity.rs(1 hunks)test-integration/test-chainlink/tests/ix_remote_account_provider.rs(1 hunks)test-integration/test-cloning/tests/07_subscription_limits.rs(1 hunks)test-integration/test-tools/Cargo.toml(1 hunks)test-integration/test-tools/src/integration_test_context.rs(2 hunks)
🧰 Additional context used
🧠 Learnings (3)
📚 Learning: 2025-10-21T14:00:54.642Z
Learnt from: bmuddha
Repo: magicblock-labs/magicblock-validator PR: 578
File: magicblock-aperture/src/requests/websocket/account_subscribe.rs:18-27
Timestamp: 2025-10-21T14:00:54.642Z
Learning: In magicblock-aperture account_subscribe handler (src/requests/websocket/account_subscribe.rs), the RpcAccountInfoConfig fields data_slice, commitment, and min_context_slot are currently ignored—only encoding is applied. This is tracked as technical debt in issue #579: https://github.com/magicblock-labs/magicblock-validator/issues/579
Applied to files:
magicblock-chainlink/src/remote_account_provider/lru_cache.rsmagicblock-aperture/src/requests/http/mod.rstest-integration/test-chainlink/src/test_context.rstest-integration/test-cloning/tests/07_subscription_limits.rsmagicblock-chainlink/src/remote_account_provider/config.rsmagicblock-chainlink/src/remote_account_provider/mod.rsmagicblock-chainlink/src/remote_account_provider/chain_pubsub_actor.rsmagicblock-chainlink/src/submux/mod.rsmagicblock-metrics/src/metrics/mod.rsmagicblock-chainlink/src/testing/chain_pubsub.rs
📚 Learning: 2025-10-14T09:56:14.047Z
Learnt from: taco-paco
Repo: magicblock-labs/magicblock-validator PR: 564
File: test-integration/programs/flexi-counter/src/processor/call_handler.rs:122-125
Timestamp: 2025-10-14T09:56:14.047Z
Learning: The file test-integration/programs/flexi-counter/src/processor/call_handler.rs contains a test smart contract used for integration testing, not production code.
Applied to files:
test-integration/test-chainlink/tests/ix_remote_account_provider.rstest-integration/test-cloning/tests/07_subscription_limits.rs
📚 Learning: 2025-10-26T16:53:29.820Z
Learnt from: thlorenz
Repo: magicblock-labs/magicblock-validator PR: 587
File: magicblock-chainlink/src/remote_account_provider/mod.rs:134-0
Timestamp: 2025-10-26T16:53:29.820Z
Learning: In magicblock-chainlink/src/remote_account_provider/mod.rs, the `Endpoint::separate_pubsub_url_and_api_key()` method uses `split_once("?api-key=")` because the api-key parameter is always the only query parameter right after `?`. No additional query parameter parsing is needed for this use case.
Applied to files:
magicblock-chainlink/src/remote_account_provider/chain_pubsub_actor.rs
🧬 Code graph analysis (12)
magicblock-chainlink/src/remote_account_provider/lru_cache.rs (1)
magicblock-chainlink/src/remote_account_provider/mod.rs (1)
new(262-317)
test-integration/test-chainlink/src/test_context.rs (2)
magicblock-chainlink/src/remote_account_provider/config.rs (2)
try_new_with_metrics(27-42)lifecycle_mode(51-53)magicblock-chainlink/src/remote_account_provider/mod.rs (3)
try_from_clients_and_mode(173-192)rpc_client(1016-1018)rpc_client(1028-1030)
magicblock-chainlink/src/remote_account_provider/chain_pubsub_client.rs (2)
magicblock-chainlink/src/remote_account_provider/chain_pubsub_actor.rs (6)
new(126-158)subscription_count(177-192)subscriptions(165-170)subscriptions(194-203)try_reconnect(454-492)new_from_url(116-124)magicblock-chainlink/src/submux/mod.rs (3)
new(147-158)subscription_count(620-636)subscriptions(641-643)
test-integration/test-chainlink/tests/ix_exceed_capacity.rs (1)
magicblock-chainlink/src/remote_account_provider/config.rs (2)
try_new_with_metrics(27-42)subscribed_accounts_lru_capacity(55-57)
test-integration/test-tools/src/integration_test_context.rs (1)
magicblock-chainlink/src/remote_account_provider/chain_pubsub_client.rs (1)
url(56-58)
test-integration/test-chainlink/tests/ix_remote_account_provider.rs (1)
magicblock-chainlink/src/remote_account_provider/config.rs (1)
try_new_with_metrics(27-42)
magicblock-chainlink/src/chainlink/fetch_cloner.rs (1)
magicblock-chainlink/src/remote_account_provider/config.rs (1)
try_new_with_metrics(27-42)
magicblock-chainlink/src/remote_account_provider/mod.rs (6)
magicblock-metrics/src/metrics/mod.rs (1)
set_monitored_accounts_count(320-322)magicblock-chainlink/src/remote_account_provider/chain_pubsub_actor.rs (1)
new(126-158)magicblock-chainlink/src/remote_account_provider/chain_pubsub_client.rs (3)
new(46-54)new(311-322)try_new_from_url(165-180)magicblock-chainlink/src/submux/mod.rs (1)
new(147-158)magicblock-chainlink/src/remote_account_provider/lru_cache.rs (4)
new(25-34)pubkeys(38-41)pubkeys(129-135)len(117-123)magicblock-chainlink/src/remote_account_provider/config.rs (2)
default(65-72)try_new_with_metrics(27-42)
magicblock-chainlink/src/remote_account_provider/chain_pubsub_actor.rs (4)
magicblock-chainlink/src/remote_account_provider/mod.rs (4)
new(262-317)default(115-121)unsubscribe(771-799)update(422-422)magicblock-chainlink/src/remote_account_provider/chain_pubsub_client.rs (16)
new(46-54)new(311-322)url(56-58)subscription_count(135-138)subscription_count(237-248)subscription_count(414-429)subscriptions(140-140)subscriptions(250-252)subscriptions(431-434)try_reconnect(147-147)try_reconnect(257-266)try_reconnect(439-442)unsubscribe(123-126)unsubscribe(219-235)unsubscribe(402-410)send(335-344)magicblock-chainlink/src/submux/mod.rs (4)
new(147-158)subscription_count(620-636)subscriptions(641-643)unsubscribe(587-595)magicblock-chainlink/src/testing/chain_pubsub.rs (1)
unsubscribe(45-57)
magicblock-chainlink/src/submux/mod.rs (2)
magicblock-chainlink/src/remote_account_provider/chain_pubsub_actor.rs (4)
new(126-158)subscription_count(177-192)subscriptions(165-170)subscriptions(194-203)magicblock-chainlink/src/remote_account_provider/chain_pubsub_client.rs (8)
new(46-54)new(311-322)subscription_count(135-138)subscription_count(237-248)subscription_count(414-429)subscriptions(140-140)subscriptions(250-252)subscriptions(431-434)
magicblock-metrics/src/metrics/mod.rs (1)
magicblock-aperture/src/state/subscriptions.rs (2)
count(335-337)count(370-372)
magicblock-chainlink/src/testing/chain_pubsub.rs (1)
magicblock-chainlink/src/remote_account_provider/chain_pubsub_actor.rs (1)
new_from_url(116-124)
🪛 GitHub Actions: Run CI - Format
test-integration/test-chainlink/tests/ix_remote_account_provider.rs
[error] 41-41: Rustfmt formatting check failed. Diff detected; run 'cargo +nightly fmt' (or 'cargo fmt') to fix formatting, then re-run the check.
⏰ 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). (3)
- GitHub Check: Build Project
- GitHub Check: run_make_ci_lint
- GitHub Check: run_make_ci_test
🔇 Additional comments (11)
magicblock-chainlink/src/chainlink/errors.rs (1)
21-21: LGTM! Error message improved for clarity.The addition of "record" makes the error message more specific and precise without any breaking changes to the error variant structure.
magicblock-chainlink/src/chainlink/fetch_cloner.rs (1)
1507-1512: LGTM!The test configuration correctly uses the new
try_new_with_metricsAPI with appropriate parameters (LRU capacity: 1000, lifecycle mode: Ephemeral, metrics disabled) and properly handles the Result withunwrap()in the test context.magicblock-aperture/src/requests/http/mod.rs (1)
115-115: The review comment is valid; maintain with minor refinement.The verification confirms the inconsistency exists:
- Line 115 uses
debug!for single account ensure failures- Line 137 uses
warn!for multiple accounts ensure failures- Both call the same
chainlink.ensure_accounts()method- Both have identical fallback behavior and error handling comments
The logging level mismatch between semantically similar operations is a legitimate code quality concern worth addressing. The review comment's suggestions are reasonable and actionable.
test-integration/test-tools/Cargo.toml (1)
14-15: Metrics HTTP deps look goodAdding
ureqandurlvia the workspace keeps the new metrics helper lean and consistent with the rest of the tooling.test-integration/Cargo.toml (1)
100-101: Workspace pin aligns with new helperThanks for pinning
ureqandurlhere—this lets the test tooling reuse the common versions cleanly.magicblock-aperture/src/requests/http/send_transaction.rs (1)
1-1: Import change is finePulling in the full log prelude keeps the new trace/debug statements compiling without extra edits elsewhere.
magicblock-chainlink/Cargo.toml (1)
7-17: Dependency additions check out
arc-swap,magicblock-metrics, andmagicblock-delegation-programline up with the cache/metrics work in this crate.Cargo.toml (1)
94-94: Good call on log featureDropping the release max-level gate matches the added trace instrumentation so it remains available in release profiles.
test-integration/test-tools/src/integration_test_context.rs (1)
1156-1203: Metric fetch helper looks solidParsing the RPC URL to derive the metrics endpoint and validating the Prometheus gauge gives the tests the observability they need.
magicblock-chainlink/src/remote_account_provider/lru_cache.rs (2)
117-135: Accessor additions make senseThe new helpers expose the cache state safely for metrics/reporting without breaking the locking strategy.
261-269: Test covers never-evicted setNice to see the invariant enforced so the clock sysvar always survives LRU churn.
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: 4
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (4)
magicblock-chainlink/src/remote_account_provider/chain_pubsub_actor.rs(8 hunks)magicblock-chainlink/src/testing/chain_pubsub.rs(2 hunks)test-integration/test-chainlink/tests/chain_pubsub_actor.rs(3 hunks)test-integration/test-chainlink/tests/chain_pubsub_client.rs(1 hunks)
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-10-21T14:00:54.642Z
Learnt from: bmuddha
Repo: magicblock-labs/magicblock-validator PR: 578
File: magicblock-aperture/src/requests/websocket/account_subscribe.rs:18-27
Timestamp: 2025-10-21T14:00:54.642Z
Learning: In magicblock-aperture account_subscribe handler (src/requests/websocket/account_subscribe.rs), the RpcAccountInfoConfig fields data_slice, commitment, and min_context_slot are currently ignored—only encoding is applied. This is tracked as technical debt in issue #579: https://github.com/magicblock-labs/magicblock-validator/issues/579
Applied to files:
magicblock-chainlink/src/remote_account_provider/chain_pubsub_actor.rs
📚 Learning: 2025-10-26T16:53:29.820Z
Learnt from: thlorenz
Repo: magicblock-labs/magicblock-validator PR: 587
File: magicblock-chainlink/src/remote_account_provider/mod.rs:134-0
Timestamp: 2025-10-26T16:53:29.820Z
Learning: In magicblock-chainlink/src/remote_account_provider/mod.rs, the `Endpoint::separate_pubsub_url_and_api_key()` method uses `split_once("?api-key=")` because the api-key parameter is always the only query parameter right after `?`. No additional query parameter parsing is needed for this use case.
Applied to files:
magicblock-chainlink/src/remote_account_provider/chain_pubsub_actor.rs
🧬 Code graph analysis (4)
test-integration/test-chainlink/tests/chain_pubsub_actor.rs (2)
magicblock-chainlink/src/testing/chain_pubsub.rs (4)
reconnect(59-68)setup_actor_and_client(14-29)subscribe(31-43)unsubscribe(45-57)test-integration/test-tools/src/integration_test_context.rs (1)
airdrop(610-635)
test-integration/test-chainlink/tests/chain_pubsub_client.rs (1)
magicblock-chainlink/src/remote_account_provider/chain_pubsub_client.rs (1)
try_new_from_url(165-180)
magicblock-chainlink/src/testing/chain_pubsub.rs (2)
magicblock-chainlink/src/remote_account_provider/chain_pubsub_actor.rs (1)
new_from_url(116-124)magicblock-chainlink/src/remote_account_provider/chain_pubsub_client.rs (1)
reconnect(81-111)
magicblock-chainlink/src/remote_account_provider/chain_pubsub_actor.rs (3)
magicblock-chainlink/src/remote_account_provider/mod.rs (4)
new(262-317)default(115-121)unsubscribe(771-799)update(422-422)magicblock-chainlink/src/remote_account_provider/chain_pubsub_client.rs (16)
new(46-54)new(311-322)url(56-58)subscription_count(135-138)subscription_count(237-248)subscription_count(414-429)subscriptions(140-140)subscriptions(250-252)subscriptions(431-434)try_reconnect(147-147)try_reconnect(257-266)try_reconnect(439-442)unsubscribe(123-126)unsubscribe(219-235)unsubscribe(402-410)send(335-344)magicblock-chainlink/src/submux/mod.rs (4)
new(147-158)subscription_count(620-636)subscriptions(641-643)unsubscribe(587-595)
⏰ 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). (2)
- GitHub Check: run_make_ci_test
- GitHub Check: Build Project
🔇 Additional comments (8)
test-integration/test-chainlink/tests/chain_pubsub_actor.rs (2)
93-100: LGTM: Correctly validates reconnection behavior.The test now properly validates that after reconnection, existing subscriptions are cleared and updates are not received until clients resubscribe. This aligns with the event-driven reconnection model described in the PR objectives.
154-167: LGTM: Comprehensive multi-account reconnection test.The test validates that after reconnection:
- All subscriptions are cleared (no updates for any account)
- Selective resubscription works correctly (only first 3 accounts)
- Previously unsubscribed accounts remain unsubscribed after reconnection
magicblock-chainlink/src/testing/chain_pubsub.rs (1)
59-68: LGTM: Clean API rename from recycle to reconnect.The function correctly sends the renamed
Reconnectmessage variant and handles the response appropriately.magicblock-chainlink/src/remote_account_provider/chain_pubsub_actor.rs (5)
115-158: LGTM: Constructor properly initializes connection management state.The constructor correctly:
- Adds abort_sender parameter for signaling connection issues
- Uses static atomic CLIENT_ID for unique instance identification
- Initializes PubSubConnection and new tracking fields (is_connected, client_id)
177-203: LGTM: Connectivity-aware subscription tracking.The methods correctly return zero/empty results when disconnected, representing that no active subscriptions exist from an external perspective even if the internal map hasn't been cleaned up yet. This design prevents callers from making incorrect assumptions about subscription state during connection issues.
280-307: Verify: Subscribe/unsubscribe are ignored when disconnected.When
is_connectedis false, both subscribe and unsubscribe requests are acknowledged but not processed. While this prevents operations on a dead connection, it means:
- Subscribe requests during disconnection are silently ignored (caller thinks subscription succeeded)
- Unsubscribe requests leave entries in the subscriptions map until reconnection cleanup
This behavior may be intentional to avoid errors during reconnection, but consider whether callers should be notified of the disconnected state rather than receiving an
Ok(())response.Does the higher-level code (RemoteAccountProvider, SubMux) handle retry logic when these operations succeed but don't actually modify subscription state? The silent acknowledgment could mask issues if callers expect immediate effect.
442-454: LGTM: Timeout prevents hanging on dead sockets during cleanup.The 2-second timeout for unsubscribe prevents the cleanup task from hanging indefinitely when the connection is dead. The subscription is removed from the map regardless of whether the unsubscribe succeeds or times out, ensuring proper cleanup.
497-534: LGTM: Robust abort signaling with duplicate prevention.The method correctly:
- Uses atomic swap to prevent duplicate aborts (line 504)
- Drains and cancels all subscriptions before signaling
- Uses
try_sendto avoid blocking, treating channel-full as expected during active reconnection (lines 528-529)The ordering ensures consistent state: subscriptions are cleaned up before signaling the connection issue, preventing races where new subscribe attempts could occur before cleanup completes.
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
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (1)
magicblock-chainlink/src/chainlink/fetch_cloner.rs(3 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
magicblock-chainlink/src/chainlink/fetch_cloner.rs (2)
magicblock-chainlink/src/remote_account_provider/lru_cache.rs (2)
pubkeys(38-41)pubkeys(129-135)magicblock-chainlink/src/remote_account_provider/config.rs (1)
try_new_with_metrics(27-42)
⏰ 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). (3)
- GitHub Check: Build Project
- GitHub Check: run_make_ci_test
- GitHub Check: run_make_ci_lint
🔇 Additional comments (2)
magicblock-chainlink/src/chainlink/fetch_cloner.rs (2)
1037-1044: Excellent improvement to error logging.The addition of pubkey context in the error message significantly improves debuggability. Using
inspect_errto log before propagating the error is idiomatic and helps trace which specific account fetch failed when multiple requests are pending.
1517-1522: LGTM!The test correctly adopts the new
try_new_with_metricsconstructor with appropriate parameters for the test context (capacity=1000, ephemeral lifecycle, metrics disabled).
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
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (1)
magicblock-chainlink/src/chainlink/mod.rs(3 hunks)
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-11-07T13:20:13.754Z
Learnt from: bmuddha
Repo: magicblock-labs/magicblock-validator PR: 589
File: magicblock-processor/src/scheduler/coordinator.rs:227-238
Timestamp: 2025-11-07T13:20:13.754Z
Learning: In magicblock-processor's ExecutionCoordinator (scheduler/coordinator.rs), the `account_contention` HashMap intentionally does not call `shrink_to_fit()`. Maintaining slack capacity is beneficial for performance by avoiding frequent reallocations during high transaction throughput. As long as empty entries are removed from the map (which `clear_account_contention` does), the capacity overhead is acceptable.
Applied to files:
magicblock-chainlink/src/chainlink/mod.rs
📚 Learning: 2025-10-21T14:00:54.642Z
Learnt from: bmuddha
Repo: magicblock-labs/magicblock-validator PR: 578
File: magicblock-aperture/src/requests/websocket/account_subscribe.rs:18-27
Timestamp: 2025-10-21T14:00:54.642Z
Learning: In magicblock-aperture account_subscribe handler (src/requests/websocket/account_subscribe.rs), the RpcAccountInfoConfig fields data_slice, commitment, and min_context_slot are currently ignored—only encoding is applied. This is tracked as technical debt in issue #579: https://github.com/magicblock-labs/magicblock-validator/issues/579
Applied to files:
magicblock-chainlink/src/chainlink/mod.rs
🧬 Code graph analysis (1)
magicblock-chainlink/src/chainlink/mod.rs (1)
magicblock-chainlink/src/remote_account_provider/mod.rs (2)
new(262-317)pubkeys_str(1076-1082)
🔇 Additional comments (4)
magicblock-chainlink/src/chainlink/mod.rs (4)
1-4: LGTM! Necessary imports for atomic counters.The addition of
AtomicU64andOrderingsupports the enhanced metrics tracking introduced in thereset_accounts_bankmethod.
143-147: LGTM! Clear categorization with atomic counters.The atomic counters provide excellent observability into the account removal process, tracking five distinct categories for detailed metrics.
149-175: Verify the TODO regarding log level adjustment.The removal logic is correct and well-structured with clear priority handling (blacklisted → delegated → DLP-owned → remaining). However, line 163 has a TODO comment suggesting the debug log should eventually be moved to trace level.
Consider whether the debug-level logging for each removed non-delegated, non-DLP-owned account (lines 164-167) might be too verbose in production. The TODO suggests moving it to trace level—confirm whether this adjustment should be made now or tracked separately.
324-339: LGTM! Enhanced observability for fetch operations.Elevating the log level from trace to debug and including the
mark_empty_if_not_foundparameter provides valuable context for debugging account fetch operations, aligning with the PR's observability improvements.
…ics and cancellations
* master: Fix scheduling of commits where accounts aren't delegated, or are delegated to another validator (#619)
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: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
magicblock-chainlink/src/remote_account_provider/mod.rs (1)
617-624: Don’t clobber in-flight fetch waitersOverwriting an existing
fetchingentry drops the previous waiters’ senders, so their receivers observeRecvErroreven though the original fetch is still running. Sharing the pending vector is required when two callers request the same pubkey concurrently.Apply this diff to merge with in-flight requests:
{ let mut fetching = self.fetching_accounts.lock().unwrap(); for &pubkey in pubkeys { let (sender, receiver) = oneshot::channel(); - fetching.insert(pubkey, (fetch_start_slot, vec![sender])); + if let Some((_slot, waiters)) = fetching.get_mut(&pubkey) { + waiters.push(sender); + } else { + fetching.insert(pubkey, (fetch_start_slot, vec![sender])); + } subscription_overrides.push((pubkey, receiver)); } }
♻️ Duplicate comments (2)
test-integration/test-cloning/tests/07_subscription_limits.rs (1)
71-73: Good: JoinSet failures are surfacedSwitch to iterating join_all results propagates panics/cancellations. Matches prior feedback.
magicblock-chainlink/src/remote_account_provider/mod.rs (1)
715-724: Reinsert the evicted key when unsubscribe failsWe now remove the new key on failure, but the evicted key never goes back into the LRU even though the pubsub unsubscribe didn’t happen. That leaves the cache claiming we aren’t watching the evicted account while the client still is.
Apply this diff to restore the prior state before returning:
if let Err(err) = self.pubsub_client.unsubscribe(evicted).await { warn!( "Failed to unsubscribe from pubsub for evicted account {evicted}: {err:?}"); // Rollback the LRU add since eviction failed self.lrucache_subscribed_accounts.remove(pubkey); + let _ = self.lrucache_subscribed_accounts.add(evicted); return Err(err); }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (2)
magicblock-chainlink/src/remote_account_provider/mod.rs(24 hunks)test-integration/test-cloning/tests/07_subscription_limits.rs(1 hunks)
🧰 Additional context used
🧠 Learnings (3)
📚 Learning: 2025-10-14T09:56:14.047Z
Learnt from: taco-paco
Repo: magicblock-labs/magicblock-validator PR: 564
File: test-integration/programs/flexi-counter/src/processor/call_handler.rs:122-125
Timestamp: 2025-10-14T09:56:14.047Z
Learning: The file test-integration/programs/flexi-counter/src/processor/call_handler.rs contains a test smart contract used for integration testing, not production code.
Applied to files:
test-integration/test-cloning/tests/07_subscription_limits.rs
📚 Learning: 2025-10-21T14:00:54.642Z
Learnt from: bmuddha
Repo: magicblock-labs/magicblock-validator PR: 578
File: magicblock-aperture/src/requests/websocket/account_subscribe.rs:18-27
Timestamp: 2025-10-21T14:00:54.642Z
Learning: In magicblock-aperture account_subscribe handler (src/requests/websocket/account_subscribe.rs), the RpcAccountInfoConfig fields data_slice, commitment, and min_context_slot are currently ignored—only encoding is applied. This is tracked as technical debt in issue #579: https://github.com/magicblock-labs/magicblock-validator/issues/579
Applied to files:
magicblock-chainlink/src/remote_account_provider/mod.rs
📚 Learning: 2025-10-26T16:53:29.820Z
Learnt from: thlorenz
Repo: magicblock-labs/magicblock-validator PR: 587
File: magicblock-chainlink/src/remote_account_provider/mod.rs:134-0
Timestamp: 2025-10-26T16:53:29.820Z
Learning: In magicblock-chainlink/src/remote_account_provider/mod.rs, the `Endpoint::separate_pubsub_url_and_api_key()` method uses `split_once("?api-key=")` because the api-key parameter is always the only query parameter right after `?`. No additional query parameter parsing is needed for this use case.
Applied to files:
magicblock-chainlink/src/remote_account_provider/mod.rs
🧬 Code graph analysis (1)
magicblock-chainlink/src/remote_account_provider/mod.rs (5)
magicblock-metrics/src/metrics/mod.rs (1)
set_monitored_accounts_count(320-322)magicblock-chainlink/src/remote_account_provider/chain_pubsub_client.rs (3)
new(46-54)new(311-322)try_new_from_url(165-180)magicblock-chainlink/src/submux/mod.rs (1)
new(147-158)magicblock-chainlink/src/remote_account_provider/lru_cache.rs (4)
new(25-34)pubkeys(38-41)pubkeys(129-135)len(117-123)magicblock-chainlink/src/remote_account_provider/config.rs (2)
default(65-72)try_new_with_metrics(27-42)
⏰ 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). (3)
- GitHub Check: run_make_ci_lint
- GitHub Check: Build Project
- GitHub Check: run_make_ci_test
🔇 Additional comments (2)
test-integration/test-cloning/tests/07_subscription_limits.rs (2)
16-17: No action required: metrics port constant matches configuration The hardcoded port 9000 in the test aligns withmetrics.port = 9000intest-integration/configs/cloning-conf.ephem.toml.
37-37: Ignore zero-lamport clamp—unnecessary
Rent::default()uses non-zerolamports_per_byte_yearandexemption_threshold, sominimum_balance(0)is guaranteed to return > 0—no clamp needed. citeturn3web0Likely an incorrect or invalid review comment.
| // TODO: need to delegate half those instead as part of airdropping | ||
| // that way we can test unsub | ||
| let rent_exempt_amount = Rent::default().minimum_balance(0); |
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.
Remove or reword stale TODO
The code already delegates half the accounts. Update the comment or drop it to avoid confusion.
- // TODO: need to delegate half those instead as part of airdropping
- // that way we can test unsub
+ // Delegate half the accounts; only the non-delegated half should be monitored.📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| // TODO: need to delegate half those instead as part of airdropping | |
| // that way we can test unsub | |
| let rent_exempt_amount = Rent::default().minimum_balance(0); | |
| // Delegate half the accounts; only the non-delegated half should be monitored. | |
| let rent_exempt_amount = Rent::default().minimum_balance(0); |
🤖 Prompt for AI Agents
In test-integration/test-cloning/tests/07_subscription_limits.rs around lines 35
to 37, the TODO comment claiming "need to delegate half those instead as part of
airdropping" is stale because the code already delegates half the accounts;
remove or reword that TODO to accurately reflect current behavior (e.g., delete
the comment or change it to note that delegation is already performed), leaving
the rent_exempt_amount line unchanged.
| if idx % 2 == 0 { | ||
| ctx.airdrop_chain_and_delegate( | ||
| &payer_chain, | ||
| &keypair, | ||
| rent_exempt_amount, | ||
| ) | ||
| .expect( | ||
| "failed to airdrop and delegate to on-chain account", | ||
| ); | ||
| } else { | ||
| ctx.airdrop_chain(&keypair.pubkey(), rent_exempt_amount) | ||
| .expect("failed to airdrop to on-chain account"); | ||
| } | ||
| }); |
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.
🧹 Nitpick | 🔵 Trivial
Include pubkey in task error messages for faster triage
Enrich the failure messages so we know which account failed and why.
- join_set.spawn(async move {
- if idx % 2 == 0 {
- ctx.airdrop_chain_and_delegate(
- &payer_chain,
- &keypair,
- rent_exempt_amount,
- )
- .expect(
- "failed to airdrop and delegate to on-chain account",
- );
- } else {
- ctx.airdrop_chain(&keypair.pubkey(), rent_exempt_amount)
- .expect("failed to airdrop to on-chain account");
- }
- });
+ join_set.spawn(async move {
+ let pk = keypair.pubkey();
+ if idx % 2 == 0 {
+ ctx.airdrop_chain_and_delegate(
+ &payer_chain,
+ &keypair,
+ rent_exempt_amount,
+ )
+ .unwrap_or_else(|e| panic!("failed to airdrop+delegate {pk}: {e}"));
+ } else {
+ ctx.airdrop_chain(&pk, rent_exempt_amount)
+ .unwrap_or_else(|e| panic!("failed to airdrop {pk}: {e}"));
+ }
+ });Committable suggestion skipped: line range outside the PR's diff.
| // Wait 1 second for metrics update | ||
| tokio::time::sleep(Duration::from_secs(5)).await; | ||
|
|
||
| let monitored_accounts_after = | ||
| ctx.get_monitored_accounts_count(PORT).unwrap(); | ||
| let diff = monitored_accounts_after - monitored_accounts_before; | ||
| debug!("Monitored accounts count total: {monitored_accounts_after}, diff: {diff}"); |
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.
🧹 Nitpick | 🔵 Trivial
Avoid fixed sleeps; poll metrics with timeout to reduce flakiness
Replace the hard-coded sleep with a short poll + deadline.
- // Wait 1 second for metrics update
- tokio::time::sleep(Duration::from_secs(5)).await;
-
- let monitored_accounts_after =
- ctx.get_monitored_accounts_count(PORT).unwrap();
+ // Poll until metrics reflect expected increase or timeout (30s)
+ let monitored_accounts_after = {
+ let deadline = tokio::time::Instant::now() + Duration::from_secs(30);
+ loop {
+ let v = ctx.get_monitored_accounts_count(PORT).unwrap();
+ if v - monitored_accounts_before >= EXTRA_MONITORED_ACCOUNTS
+ || tokio::time::Instant::now() >= deadline
+ {
+ break v;
+ }
+ tokio::time::sleep(Duration::from_millis(250)).await;
+ }
+ };📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| // Wait 1 second for metrics update | |
| tokio::time::sleep(Duration::from_secs(5)).await; | |
| let monitored_accounts_after = | |
| ctx.get_monitored_accounts_count(PORT).unwrap(); | |
| let diff = monitored_accounts_after - monitored_accounts_before; | |
| debug!("Monitored accounts count total: {monitored_accounts_after}, diff: {diff}"); | |
| // Poll until metrics reflect expected increase or timeout (30s) | |
| let monitored_accounts_after = { | |
| let deadline = tokio::time::Instant::now() + Duration::from_secs(30); | |
| loop { | |
| let v = ctx.get_monitored_accounts_count(PORT).unwrap(); | |
| if v - monitored_accounts_before >= EXTRA_MONITORED_ACCOUNTS | |
| || tokio::time::Instant::now() >= deadline | |
| { | |
| break v; | |
| } | |
| tokio::time::sleep(Duration::from_millis(250)).await; | |
| } | |
| }; | |
| let diff = monitored_accounts_after - monitored_accounts_before; | |
| debug!("Monitored accounts count total: {monitored_accounts_after}, diff: {diff}"); |
🤖 Prompt for AI Agents
In test-integration/test-cloning/tests/07_subscription_limits.rs around lines
111 to 117, replace the fixed tokio::time::sleep(Duration::from_secs(5)).await
with a polling loop that repeatedly calls ctx.get_monitored_accounts_count(PORT)
until the expected change is observed or a deadline is reached; implement a
short poll interval (e.g., 100–200ms) and a total timeout (e.g., 2–5s) using
tokio::time::sleep inside the loop or tokio::time::timeout/Instant for the
deadline, and fail the test (return Err or panic) if the timeout elapses without
the expected metric change to avoid flakiness.
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: 3
♻️ Duplicate comments (2)
test-integration/test-cloning/tests/07_subscription_limits.rs (1)
71-73: Propagate JoinError to detect task failures.The loop iterates over
join_all()results but ignores them with the_resultbinding. If a spawned task panics or is cancelled, theJoinErroris silently dropped, allowing the test to proceed with incomplete operations and produce misleading results. The comment "handled by join_all" is inaccurate—join_all()collects errors but does not propagate them.Apply this diff to fail the test immediately on any task failure:
- for _result in join_set.join_all().await { - // spawned task panicked or was cancelled - handled by join_all + for result in join_set.join_all().await { + result.expect("airdrop/delegate task failed"); }magicblock-chainlink/src/remote_account_provider/mod.rs (1)
715-725: Restore the evicted key in LRU when unsubscribe failsWhen
unsubscribe(evicted)errors we roll back the new pubkey, but the evicted key stays removed from the cache even though the pubsub client never dropped it. That leavesis_watching(evicted)false while the subscription is still live and can trigger duplicate subscribe attempts later—this was flagged previously.if let Err(err) = self.pubsub_client.unsubscribe(evicted).await { warn!( "Failed to unsubscribe from pubsub for evicted account {evicted}: {err:?}"); // Rollback the LRU add since eviction failed self.lrucache_subscribed_accounts.remove(pubkey); + self.lrucache_subscribed_accounts.add(evicted); return Err(err); }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (3)
magicblock-chainlink/src/chainlink/mod.rs(3 hunks)magicblock-chainlink/src/remote_account_provider/mod.rs(24 hunks)test-integration/test-cloning/tests/07_subscription_limits.rs(1 hunks)
🧰 Additional context used
🧠 Learnings (6)
📓 Common learnings
Learnt from: thlorenz
Repo: magicblock-labs/magicblock-validator PR: 621
File: magicblock-chainlink/src/remote_account_provider/chain_pubsub_actor.rs:457-495
Timestamp: 2025-11-07T14:20:31.425Z
Learning: In magicblock-chainlink/src/remote_account_provider/chain_pubsub_client.rs, the unsubscribe closure returned by PubSubConnection::account_subscribe(...) resolves to () (unit), not a Result. Downstream code should not attempt to inspect an unsubscribe result and can optionally wrap it in a timeout to guard against hangs.
📚 Learning: 2025-11-07T13:20:13.793Z
Learnt from: bmuddha
Repo: magicblock-labs/magicblock-validator PR: 589
File: magicblock-processor/src/scheduler/coordinator.rs:227-238
Timestamp: 2025-11-07T13:20:13.793Z
Learning: In magicblock-processor's ExecutionCoordinator (scheduler/coordinator.rs), the `account_contention` HashMap intentionally does not call `shrink_to_fit()`. Maintaining slack capacity is beneficial for performance by avoiding frequent reallocations during high transaction throughput. As long as empty entries are removed from the map (which `clear_account_contention` does), the capacity overhead is acceptable.
Applied to files:
magicblock-chainlink/src/chainlink/mod.rs
📚 Learning: 2025-10-21T14:00:54.642Z
Learnt from: bmuddha
Repo: magicblock-labs/magicblock-validator PR: 578
File: magicblock-aperture/src/requests/websocket/account_subscribe.rs:18-27
Timestamp: 2025-10-21T14:00:54.642Z
Learning: In magicblock-aperture account_subscribe handler (src/requests/websocket/account_subscribe.rs), the RpcAccountInfoConfig fields data_slice, commitment, and min_context_slot are currently ignored—only encoding is applied. This is tracked as technical debt in issue #579: https://github.com/magicblock-labs/magicblock-validator/issues/579
Applied to files:
magicblock-chainlink/src/chainlink/mod.rstest-integration/test-cloning/tests/07_subscription_limits.rsmagicblock-chainlink/src/remote_account_provider/mod.rs
📚 Learning: 2025-11-07T14:20:31.425Z
Learnt from: thlorenz
Repo: magicblock-labs/magicblock-validator PR: 621
File: magicblock-chainlink/src/remote_account_provider/chain_pubsub_actor.rs:457-495
Timestamp: 2025-11-07T14:20:31.425Z
Learning: In magicblock-chainlink/src/remote_account_provider/chain_pubsub_client.rs, the unsubscribe closure returned by PubSubConnection::account_subscribe(...) resolves to () (unit), not a Result. Downstream code should not attempt to inspect an unsubscribe result and can optionally wrap it in a timeout to guard against hangs.
Applied to files:
magicblock-chainlink/src/chainlink/mod.rstest-integration/test-cloning/tests/07_subscription_limits.rsmagicblock-chainlink/src/remote_account_provider/mod.rs
📚 Learning: 2025-10-14T09:56:14.047Z
Learnt from: taco-paco
Repo: magicblock-labs/magicblock-validator PR: 564
File: test-integration/programs/flexi-counter/src/processor/call_handler.rs:122-125
Timestamp: 2025-10-14T09:56:14.047Z
Learning: The file test-integration/programs/flexi-counter/src/processor/call_handler.rs contains a test smart contract used for integration testing, not production code.
Applied to files:
test-integration/test-cloning/tests/07_subscription_limits.rs
📚 Learning: 2025-10-26T16:53:29.820Z
Learnt from: thlorenz
Repo: magicblock-labs/magicblock-validator PR: 587
File: magicblock-chainlink/src/remote_account_provider/mod.rs:134-0
Timestamp: 2025-10-26T16:53:29.820Z
Learning: In magicblock-chainlink/src/remote_account_provider/mod.rs, the `Endpoint::separate_pubsub_url_and_api_key()` method uses `split_once("?api-key=")` because the api-key parameter is always the only query parameter right after `?`. No additional query parameter parsing is needed for this use case.
Applied to files:
magicblock-chainlink/src/remote_account_provider/mod.rs
🧬 Code graph analysis (2)
magicblock-chainlink/src/chainlink/mod.rs (1)
magicblock-chainlink/src/remote_account_provider/mod.rs (1)
pubkeys_str(1079-1085)
magicblock-chainlink/src/remote_account_provider/mod.rs (6)
magicblock-metrics/src/metrics/mod.rs (1)
set_monitored_accounts_count(320-322)magicblock-chainlink/src/remote_account_provider/chain_pubsub_actor.rs (1)
new(126-158)magicblock-chainlink/src/remote_account_provider/chain_pubsub_client.rs (3)
new(46-54)new(311-322)try_new_from_url(165-180)magicblock-chainlink/src/submux/mod.rs (1)
new(147-158)magicblock-chainlink/src/remote_account_provider/lru_cache.rs (4)
new(25-34)pubkeys(38-41)pubkeys(129-135)len(117-123)magicblock-chainlink/src/remote_account_provider/config.rs (2)
default(65-72)try_new_with_metrics(27-42)
⏰ 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: Build Project
🔇 Additional comments (4)
test-integration/test-cloning/tests/07_subscription_limits.rs (4)
1-17: LGTM! Clear setup and well-documented constants.The imports are appropriate for an integration test, and the constants are well-documented. The math is correct: 400 accounts with half delegated results in 200 monitored accounts.
19-44: LGTM! Appropriate test configuration.The test is correctly marked as ignored for manual execution, uses multi-threaded Tokio runtime for parallelism, and the payer funding (10 SOL) should be sufficient for the planned operations.
76-107: LGTM! Appropriate logging and account fetching.The batch processing logs progress clearly, and the account fetching verifies that accounts are accessible via the ephemeral RPC. The trace-level pubkey logging is appropriately verbose for debugging without cluttering normal test output.
114-123: LGTM! Clear verification logic.The final assertion correctly validates that the monitored accounts increased by exactly 200 (the non-delegated accounts), which is the core objective of this subscription limits test.
| collections::{HashMap, HashSet}, | ||
| num::NonZeroUsize, | ||
| sync::{ | ||
| atomic::{AtomicU64, Ordering}, | ||
| Arc, Mutex, | ||
| }, | ||
| time::Duration, | ||
| }; |
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.
Don't drop existing fetch waiters
fetching.insert replaces any in-flight entry, dropping the earlier waiters so their receivers resolve with RecvError even though the fetch eventually succeeds. Concurrent try_get_multi callers will start failing under load. Please append to the existing waiter list instead of clobbering it.
-use std::{
- collections::{HashMap, HashSet},
+use std::{
+ collections::{hash_map::Entry, HashMap, HashSet},
@@
- for &pubkey in pubkeys {
- let (sender, receiver) = oneshot::channel();
- fetching.insert(pubkey, (fetch_start_slot, vec![sender]));
- subscription_overrides.push((pubkey, receiver));
- }
+ for &pubkey in pubkeys {
+ let (sender, receiver) = oneshot::channel();
+ match fetching.entry(pubkey) {
+ Entry::Occupied(mut entry) => {
+ entry.get_mut().1.push(sender);
+ }
+ Entry::Vacant(entry) => {
+ entry.insert((fetch_start_slot, vec![sender]));
+ }
+ }
+ subscription_overrides.push((pubkey, receiver));
+ }Also applies to: 618-645
| // TODO: need to delegate half those instead as part of airdropping | ||
| // that way we can test unsub |
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.
Remove obsolete TODO comment.
The TODO suggests delegating half the accounts as part of airdropping, but this functionality is already implemented in lines 56-68 (even-indexed accounts are delegated via airdrop_chain_and_delegate, odd-indexed are not). The comment should be removed to avoid confusion.
Apply this diff:
- // TODO: need to delegate half those instead as part of airdropping
- // that way we can test unsub
let rent_exempt_amount = Rent::default().minimum_balance(0);📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| // TODO: need to delegate half those instead as part of airdropping | |
| // that way we can test unsub | |
| let rent_exempt_amount = Rent::default().minimum_balance(0); |
🤖 Prompt for AI Agents
In test-integration/test-cloning/tests/07_subscription_limits.rs around lines
35-36, remove the obsolete TODO comment "// TODO: need to delegate half those
instead as part of airdropping // that way we can test unsub" because the code
already delegates even-indexed accounts via airdrop_chain_and_delegate (lines
56-68); simply delete these two comment lines to avoid confusion.
| // Wait 1 second for metrics update | ||
| tokio::time::sleep(Duration::from_secs(5)).await; |
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.
Fix comment to match wait duration.
The comment states "Wait 1 second" but the code waits 5 seconds. Update the comment for consistency.
Apply this diff:
- // Wait 1 second for metrics update
+ // Wait 5 seconds for metrics update
tokio::time::sleep(Duration::from_secs(5)).await;📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| // Wait 1 second for metrics update | |
| tokio::time::sleep(Duration::from_secs(5)).await; | |
| // Wait 5 seconds for metrics update | |
| tokio::time::sleep(Duration::from_secs(5)).await; |
🤖 Prompt for AI Agents
In test-integration/test-cloning/tests/07_subscription_limits.rs around lines
111 to 112, the inline comment incorrectly says "Wait 1 second" while the code
sleeps for 5 seconds; update the comment to accurately reflect the wait duration
(e.g., change to "Wait 5 seconds for metrics update") so the comment matches the
implementation.
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
♻️ Duplicate comments (1)
magicblock-chainlink/src/chainlink/mod.rs (1)
175-181: Remove unnecessary fetch_sub operation.The
fetch_subat lines 178-181 is dead code—its result is unused and the mutation is never observed sinceinto_inner()is called on all atomics in the logging statement. Thenon_emptycalculation at lines 175-177 is already correct and sufficient for logging.Apply this diff to remove the unnecessary operation:
let non_empty = remaining .load(Ordering::Relaxed) .saturating_sub(remaining_empty.load(Ordering::Relaxed)); - remaining.fetch_sub( - remaining_empty.load(Ordering::Relaxed), - Ordering::Relaxed, - ); -
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (2)
magicblock-chainlink/src/chainlink/mod.rs(3 hunks)magicblock-processor/src/executor/processing.rs(2 hunks)
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: thlorenz
Repo: magicblock-labs/magicblock-validator PR: 621
File: magicblock-chainlink/src/remote_account_provider/chain_pubsub_actor.rs:457-495
Timestamp: 2025-11-07T14:20:31.425Z
Learning: In magicblock-chainlink/src/remote_account_provider/chain_pubsub_client.rs, the unsubscribe closure returned by PubSubConnection::account_subscribe(...) resolves to () (unit), not a Result. Downstream code should not attempt to inspect an unsubscribe result and can optionally wrap it in a timeout to guard against hangs.
📚 Learning: 2025-11-07T13:20:13.793Z
Learnt from: bmuddha
Repo: magicblock-labs/magicblock-validator PR: 589
File: magicblock-processor/src/scheduler/coordinator.rs:227-238
Timestamp: 2025-11-07T13:20:13.793Z
Learning: In magicblock-processor's ExecutionCoordinator (scheduler/coordinator.rs), the `account_contention` HashMap intentionally does not call `shrink_to_fit()`. Maintaining slack capacity is beneficial for performance by avoiding frequent reallocations during high transaction throughput. As long as empty entries are removed from the map (which `clear_account_contention` does), the capacity overhead is acceptable.
Applied to files:
magicblock-processor/src/executor/processing.rsmagicblock-chainlink/src/chainlink/mod.rs
📚 Learning: 2025-10-21T14:00:54.642Z
Learnt from: bmuddha
Repo: magicblock-labs/magicblock-validator PR: 578
File: magicblock-aperture/src/requests/websocket/account_subscribe.rs:18-27
Timestamp: 2025-10-21T14:00:54.642Z
Learning: In magicblock-aperture account_subscribe handler (src/requests/websocket/account_subscribe.rs), the RpcAccountInfoConfig fields data_slice, commitment, and min_context_slot are currently ignored—only encoding is applied. This is tracked as technical debt in issue #579: https://github.com/magicblock-labs/magicblock-validator/issues/579
Applied to files:
magicblock-processor/src/executor/processing.rsmagicblock-chainlink/src/chainlink/mod.rs
🧬 Code graph analysis (1)
magicblock-chainlink/src/chainlink/mod.rs (2)
magicblock-chainlink/src/chainlink/fetch_cloner.rs (1)
new(134-158)magicblock-chainlink/src/remote_account_provider/mod.rs (2)
new(262-317)pubkeys_str(1079-1085)
⏰ 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). (2)
- GitHub Check: run_make_ci_test
- GitHub Check: Build Project
🔇 Additional comments (6)
magicblock-chainlink/src/chainlink/mod.rs (4)
1-4: LGTM: Atomic imports added correctly.The imports are appropriate for the atomic counter operations introduced in
reset_accounts_bank.
143-147: LGTM: Atomic counters initialized correctly.The atomic counters provide clear categorization for account removal tracking and improve observability.
149-173: LGTM: Account removal logic is well-structured.The explicit branching for blacklisted, delegated, and DLP-owned accounts provides clear categorization. The atomic increments with Relaxed ordering are appropriate for these independent statistics counters.
183-194: LGTM: Logging calculation fixed correctly.The logging now correctly uses the pre-calculated
non_emptyvalue, addressing the previous review concern about incorrectfetch_subusage inline. The detailed breakdown provides excellent observability into account removal categories.magicblock-processor/src/executor/processing.rs (2)
10-10: LGTM: Import is necessary and correct.The
ReadableAccounttrait import is required for thelamports()method used in the filter condition at line 292.
287-294: Account closure handling is correctly delegated to chainlink.The processor intentionally skips persisting empty accounts (lamports == 0) because chainlink manages account closures independently through direct pubsub subscriptions to the chain. When an account closes, chainlink receives that closure event directly from the chain (see
listen_for_account_updatesinmagicblock-chainlink/src/remote_account_provider/mod.rs), not through the processor'saccounts_txchannel. This separation of concerns is documented in the code comment at line 289-291 and is the correct design.Likely an incorrect or invalid review comment.
| if log::log_enabled!(log::Level::Debug) { | ||
| let pubkeys_str = pubkeys | ||
| .iter() | ||
| .map(|p| p.to_string()) | ||
| .collect::<Vec<_>>() | ||
| .join(", "); | ||
| trace!("Fetching accounts: {pubkeys_str}"); | ||
| let mark_empty_str = mark_empty_if_not_found | ||
| .map(|keys| { | ||
| keys.iter() | ||
| .map(|p| p.to_string()) | ||
| .collect::<Vec<_>>() | ||
| .join(", ") | ||
| }) | ||
| .unwrap_or_default(); | ||
| trace!("Fetching accounts: {pubkeys_str}, mark_empty_if_not_found: {mark_empty_str}"); | ||
| } |
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.
Fix logging level inconsistency.
The code gates on log::Level::Debug (line 327) but then uses the trace!() macro (line 341). This is inconsistent—if Debug is enabled but Trace is not, the expensive string formatting will execute but produce no output.
Apply this diff to align the macro with the gate:
- if log::log_enabled!(log::Level::Debug) {
+ if log::log_enabled!(log::Level::Trace) {
let pubkeys_str = pubkeys
.iter()
.map(|p| p.to_string())Or, if Debug-level logging is intentional, use the debug!() macro instead:
let mark_empty_str = mark_empty_if_not_found
.map(|keys| {
keys.iter()
.map(|p| p.to_string())
.collect::<Vec<_>>()
.join(", ")
})
.unwrap_or_default();
- trace!("Fetching accounts: {pubkeys_str}, mark_empty_if_not_found: {mark_empty_str}");
+ debug!("Fetching accounts: {pubkeys_str}, mark_empty_if_not_found: {mark_empty_str}");
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| if log::log_enabled!(log::Level::Debug) { | |
| let pubkeys_str = pubkeys | |
| .iter() | |
| .map(|p| p.to_string()) | |
| .collect::<Vec<_>>() | |
| .join(", "); | |
| trace!("Fetching accounts: {pubkeys_str}"); | |
| let mark_empty_str = mark_empty_if_not_found | |
| .map(|keys| { | |
| keys.iter() | |
| .map(|p| p.to_string()) | |
| .collect::<Vec<_>>() | |
| .join(", ") | |
| }) | |
| .unwrap_or_default(); | |
| trace!("Fetching accounts: {pubkeys_str}, mark_empty_if_not_found: {mark_empty_str}"); | |
| } | |
| if log::log_enabled!(log::Level::Debug) { | |
| let pubkeys_str = pubkeys | |
| .iter() | |
| .map(|p| p.to_string()) | |
| .collect::<Vec<_>>() | |
| .join(", "); | |
| let mark_empty_str = mark_empty_if_not_found | |
| .map(|keys| { | |
| keys.iter() | |
| .map(|p| p.to_string()) | |
| .collect::<Vec<_>>() | |
| .join(", ") | |
| }) | |
| .unwrap_or_default(); | |
| debug!("Fetching accounts: {pubkeys_str}, mark_empty_if_not_found: {mark_empty_str}"); | |
| } |
🤖 Prompt for AI Agents
In magicblock-chainlink/src/chainlink/mod.rs around lines 327 to 342, the code
checks log::Level::Debug but then calls trace!(), causing expensive string
formatting to run when Debug is enabled but Trace is not; fix by making the gate
and macro consistent: either change the guard to log::Level::Trace (or use
log::log_enabled!(log::Level::Trace)) if you want trace-level logging, or
replace trace!() with debug!() if debug-level output was intended, ensuring the
enabled-level check matches the chosen logging macro.
Summary by CodeRabbit
New Features
Bug Fixes
Tests
Chores
Enhances subscription management and reliability by adding metrics, and robust reconnection logic with automatic resubscription.
Details
Subscription Management Improvements
Metrics and Monitoring
subscription_countmethod toChainPubsubClienttrait for tracking active subscriptions across all clientsRemoteAccountProviderConfigReconnection and Reliability
ReconnectableClienttraitTesting and Integration
07_subscription_limits.rsto test large-scale subscription scenarios (400 accounts)Code Quality
ReconnectableClienttrait for better abstractionureqandurlfor metrics fetching in integration tests