Skip to content

Activation task deduplication and SharedActivationCoordinator enhancements#274

Open
smk762 wants to merge 3 commits intodevfrom
deduplicate-activation
Open

Activation task deduplication and SharedActivationCoordinator enhancements#274
smk762 wants to merge 3 commits intodevfrom
deduplicate-activation

Conversation

@smk762
Copy link
Copy Markdown
Contributor

@smk762 smk762 commented Oct 30, 2025

closes #273

Summary

  • Ensures a single activation per AssetId across the SDK by routing all public activation calls through SharedActivationCoordinator and making ActivationManager idempotent at init.
  • Prevents balance/pubkeys from triggering overlapping coin-init while activation is pending by joining the in-flight activation.
  • Hardens event streaming to avoid WASM closure re-entrancy and post-dispose callbacks.

Key changes

  • AssetManager
    • Route activation via coordinator to guarantee dedup and convergence of callers.
    • Multi-asset activation aggregates coordinator streams.
  • ActivationManager
    • Idempotent init: register-or-join. New callers join the existing activation instead of spawning a duplicate backend task.
    • Emits a short "joining" progress and concludes with success/error accordingly.
  • BalanceManager
    • When activateIfNeeded=false but activation is pending, await coordinator activation to avoid racing wallet-account creation and pubkeys.
  • KdfEventStreamingService
    • Dispatch events via microtasks and guard against post-dispose to prevent closure invoked recursively or after being dropped errors.
  • Bootstrap DI
    • Inject SharedActivationCoordinator into AssetManager to make it the single entry path.

Rationale (maps to #273 goals)

  • Idempotency/dedup: Single activation per AssetId and shared result across call sites.
  • Race prevention: Balance/pubkeys join pending activation, avoiding overlapping coin-init.
  • WASM stability: Microtask dispatch + dispose guards reduce re-entrancy and after-dispose calls.

Files touched

  • packages/komodo_defi_sdk/lib/src/assets/asset_manager.dart
  • packages/komodo_defi_sdk/lib/src/activation/activation_manager.dart
  • packages/komodo_defi_sdk/lib/src/balances/balance_manager.dart
  • packages/komodo_defi_framework/lib/src/streaming/event_streaming_service.dart
  • packages/komodo_defi_sdk/lib/src/bootstrap.dart

Behavior notes

  • Coordinator Future path waits for coin availability before success; stream path exposes raw progress and closes on completion (unchanged semantics).
  • Direct ActivationManager usage remains internal; public APIs now converge via coordinator.

Testing plan

  • Concurrency: Two parallel activations for same asset → one backend task; both callers complete.
  • Activation + balance race: Balance joins activation; no uniqueness/storage errors.
  • Wallet switch during activation: Futures complete with cancellation; no post-dispose callbacks.
  • Stream subscribers + future joiners: Both complete; stream cleans up.
  • Protocol matrix: UTXO, ETH/ERC-20, BEP-20, Tendermint(+tokens) behave consistently.
  • Negative cases: Node/RPC errors do not create duplicate tasks on retries.

Follow-ups (tracked separately)

Acceptance criteria

  • One activation task per asset across concurrent callers.
  • No IndexedDB/storage uniqueness violations during activation + balance races.
  • No re-entrancy/after-dispose WASM closure errors under stress.
  • Activation responses parse reliably across protocols.

@smk762 smk762 requested a review from CharlVS October 30, 2025 14:56
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Oct 30, 2025

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch deduplicate-activation

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
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +224 to +240
Stream<ActivationProgress> activateAssets(List<Asset> assets) {
final coordinator = _activationCoordinator?.call();
if (coordinator == null) {
return _activationManager().activateAssets(assets);
}

final controller = StreamController<ActivationProgress>.broadcast();

scheduleMicrotask(() {
for (final asset in assets) {
coordinator
.activateAssetStream(asset)
.listen(controller.add, onError: controller.addError);
}
});

return controller.stream;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Close multi-asset activation stream after forwarding child streams

The new coordinator-backed activateAssets path builds a broadcast controller but never closes it when the underlying per‑asset streams finish. Consumers waiting on the returned stream to complete (e.g. await manager.activateAssets([...]).last or using await for expecting the loop to end) will now hang indefinitely and keep subscriptions alive, whereas the previous ActivationManager.activateAssets stream finished once all activations completed. Consider closing the controller once all child streams emit a terminal event.

Useful? React with 👍 / 👎.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Oct 30, 2025

Visit the preview URL for this PR (updated for commit 631cf0e):

https://komodo-playground--pr274-deduplicate-activati-7rj38wzj.web.app

(expires Fri, 07 Nov 2025 11:33:18 GMT)

🔥 via Firebase Hosting GitHub Action 🌎

Sign: 2bfedd77fdea45b25ba7c784416e81f177aa5c47

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