Skip to content

fix(alert): disable deployment alerts before intentional close#2845

Open
baktun14 wants to merge 3 commits intomainfrom
fix/deployment-alerts-on-close
Open

fix(alert): disable deployment alerts before intentional close#2845
baktun14 wants to merge 3 commits intomainfrom
fix/deployment-alerts-on-close

Conversation

@baktun14
Copy link
Copy Markdown
Contributor

@baktun14 baktun14 commented Mar 2, 2026

Why

When a user intentionally closes a deployment via managed wallet, the deployment-closed chain event fires and triggers an unwanted alert notification. This is annoying for users since they deliberately closed the deployment.

What

Disable deployment alerts before the close transaction is signed, so the chain event finds no enabled alerts to trigger.

  • Added disableDeploymentAlerts method to NotificationService that fetches current alerts and upserts them with enabled: false (best-effort, errors are caught and logged)
  • Added getDeploymentAlerts private helper to NotificationService
  • Hooked into ManagedSignerService.executeDecodedTxByUserWallet() to detect MsgCloseDeployment and disable alerts before signing — this covers both the direct close endpoint (DELETE /v1/deployments/{dseq}) and the generic transaction path (POST /v1/tx)
  • Alerts must be disabled before close because the notifications service validates deployment existence on-chain; after closing, the upsert would fail with "Deployment not found"
  • Added 6 unit tests for disableDeploymentAlerts covering: both alerts enabled, already disabled, suppressed by system, no alerts, error handling, partial disable

Summary by CodeRabbit

  • New Features

    • Automatically disable deployment alerts when a deployment is closed to prevent unnecessary notifications.
  • Updates

    • Notification service now exposes a public operation to disable deployment alerts for a given user/wallet/deployment; managed signing flow invokes it when closes are detected.
  • Tests

    • Added comprehensive tests covering multiple close events, skipped cases, partial disables, error handling, and retry/backoff.

When a user intentionally closes a deployment via managed wallet,
the chain event fires and triggers unwanted alert notifications.
This disables alerts before the close transaction so the chain
event finds no enabled alerts. Handles both the direct close
endpoint and generic transaction paths.
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 2, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 7b83fdf and b8815dc.

📒 Files selected for processing (1)
  • apps/api/src/billing/services/managed-signer/managed-signer.service.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/api/src/billing/services/managed-signer/managed-signer.service.ts

📝 Walkthrough

Walkthrough

ManagedSignerService now detects MsgCloseDeployment messages and invokes NotificationService.disableDeploymentAlerts(userId, walletAddress, dseq). NotificationService gains disableDeploymentAlerts(...) to fetch, conditionally disable, and upsert deployment alerts with retry and error logging. Tests added/updated across both services.

Changes

Cohort / File(s) Summary
Billing Service Integration
apps/api/src/billing/services/managed-signer/managed-signer.service.ts
Constructor now accepts NotificationService. Scans tx batches for MsgCloseDeployment messages and calls notificationService.disableDeploymentAlerts(userId, walletAddress, dseq) before existing lease handling.
Notification Service (impl & tests)
apps/api/src/notifications/services/notification/notification.service.ts, apps/api/src/notifications/services/notification/notification.service.spec.ts
Adds disableDeploymentAlerts({ userId, walletAddress, dseq }) which GETs current deployment alerts, conditionally disables deploymentBalance/deploymentClosed, and UPSERTs via API with backoff and error logging. Tests cover primary flow, partial disables, suppressed/already-disabled/no-alerts cases, error handling; note duplicate test block appears in diff.
Billing Service Tests
apps/api/src/billing/services/managed-signer/managed-signer.service.spec.ts
Test harness updated to inject a NotificationService mock. New tests verify disableDeploymentAlerts calls for single/multiple MsgCloseDeployment messages and absence of calls for non-close messages.
Manifest / Package
manifest_file, package.json
Manifest/package metadata changes included (no behavioral detail provided).

Sequence Diagram

sequenceDiagram
    participant MS as ManagedSignerService
    participant NS as NotificationService
    participant API as Notifications API

    MS->>MS: scan tx messages for MsgCloseDeployment
    activate MS
    MS->>NS: disableDeploymentAlerts(userId, walletAddress, dseq)
    deactivate MS

    activate NS
    NS->>API: GET /deployment-alerts?userId=...&wallet=...
    activate API
    API-->>NS: current alerts
    deactivate API

    NS->>NS: determine which alerts to disable
    alt alerts need update
        NS->>API: UPSERT /deployment-alerts (disable payload) with backoff
        activate API
        API-->>NS: success
        deactivate API
    else no update needed or suppressed
        NS->>NS: skip upsert
    end

    NS-->>MS: return void
    deactivate NS
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐰 I found a close and gave a hop,
I quieted alerts with a tiny plop,
A gentle fetch, a careful mend,
Deployments rest — the watch I end. ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ 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%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main change: disabling deployment alerts before closing a deployment intentionally.
Description check ✅ Passed The description comprehensively covers why the change is needed and what was implemented, matching the template requirements with detailed explanations of the solution.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ 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 fix/deployment-alerts-on-close

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

Copy link
Copy Markdown
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 `@apps/api/src/billing/services/managed-signer/managed-signer.service.ts`:
- Around line 117-127: The code currently uses messages.find to get only the
first MsgCloseDeployment (closeDeploymentMessage) so other close messages in the
same transaction are ignored; change this to iterate over all matching messages
(e.g., use messages.filter or a for loop over messages.filter(m =>
m.typeUrl.endsWith(".MsgCloseDeployment"))), and for each matching message where
userWallet.userId exists call this.notificationService.disableDeploymentAlerts
with the same payload (userId: userWallet.userId, walletAddress:
userWallet.address!, dseq: message.value.id!.dseq.toString()) so every
MsgCloseDeployment in the transaction is processed.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between c95e8dd and ef90d5c.

📒 Files selected for processing (3)
  • apps/api/src/billing/services/managed-signer/managed-signer.service.ts
  • apps/api/src/notifications/services/notification/notification.service.spec.ts
  • apps/api/src/notifications/services/notification/notification.service.ts

@codecov
Copy link
Copy Markdown

codecov bot commented Mar 2, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 53.46%. Comparing base (c95e8dd) to head (b8815dc).
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2845      +/-   ##
==========================================
- Coverage   54.25%   53.46%   -0.80%     
==========================================
  Files        1020      985      -35     
  Lines       23635    22831     -804     
  Branches     5789     5701      -88     
==========================================
- Hits        12824    12206     -618     
+ Misses       9423     9246     -177     
+ Partials     1388     1379       -9     
Flag Coverage Δ *Carryforward flag
api 77.08% <100.00%> (+0.09%) ⬆️
deploy-web 36.84% <ø> (ø) Carriedforward from 7b83fdf
log-collector ?
notifications 85.56% <ø> (ø) Carriedforward from 7b83fdf
provider-console 81.48% <ø> (ø) Carriedforward from 7b83fdf
provider-proxy 85.93% <ø> (ø) Carriedforward from 7b83fdf
tx-signer ?

*This pull request uses carry forward flags. Click here to find out more.

Files with missing lines Coverage Δ
.../services/managed-signer/managed-signer.service.ts 100.00% <100.00%> (ø)
...ions/services/notification/notification.service.ts 100.00% <100.00%> (ø)

... and 35 files with indirect coverage changes

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Process all MsgCloseDeployment messages in a transaction batch
instead of only the first one. Adds tests for single, multiple,
and absent close deployment messages in ManagedSignerService.
Copy link
Copy Markdown
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 `@apps/api/src/billing/services/managed-signer/managed-signer.service.ts`:
- Around line 117-129: The closeDeploymentMessages handling can throw when
message.value.id or dseq is missing and may call disableDeploymentAlerts
multiple times for the same dseq; update the block that builds
closeDeploymentMessages to first filter messages to those with a present id and
dseq (e.g. message.value?.id?.dseq != null), map to a normalized dseq string
(message.value.id.dseq.toString()), deduplicate that list (e.g. Set) and then
call this.notificationService.disableDeploymentAlerts once per unique dseq using
userWallet.userId and userWallet.address; reference the closeDeploymentMessages
variable, the notificationService.disableDeploymentAlerts call, and userWallet
fields to locate and change the code.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between ef90d5c and 7b83fdf.

📒 Files selected for processing (2)
  • apps/api/src/billing/services/managed-signer/managed-signer.service.spec.ts
  • apps/api/src/billing/services/managed-signer/managed-signer.service.ts

Comment on lines +127 to +131
await this.notificationService.disableDeploymentAlerts({
userId: userWallet.userId,
walletAddress: userWallet.address!,
dseq
});
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

question: does it make sense to keep this logic on notification service? for example, when it receives a block or event (not sure how it does it) then it can check whether there is a MsgCloseDeployment message for that dseq and if so, it means user intentionally closed it and it can skip notification.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This may be a cleaner approach indeed. Some logic to identify the event source would be needed here. Here's what the trigger event looks like:

[
  {
    "type": "akash.deployment.v1.EventDeploymentClosed",
    "attributes": [
      {
        "key": "id",
        "value": "{\"owner\":\"akash1sjds2vaquyax6zf88jhl9kt4enp3tqdn4r9erv\",\"dseq\":\"2330094\"}"
      },
      {
        "key": "msg_index",
        "value": "0"
      }
    ]
  }
]

@stalniy
Copy link
Copy Markdown
Contributor

stalniy commented Mar 3, 2026

I think from awareness standpoint, it's good to receive this notification even if it was initiated by user. Because he receives confirmation that he won't be billed for that deployment anymore. Also from audit trail standpoint it may be useful, since blockchain is abstracted from managed wallet user.

So, probably it makes sense to make it configurable via "notify on explicit close" checkbox, which can be disabled by default

Copy link
Copy Markdown
Contributor

@ygrishajev ygrishajev left a comment

Choose a reason for hiding this comment

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

Although I understand the purpose of this PR I'd like to throw in some concern:
We currently do not support SASS like product organization. Meaning if any user wants to use akash as an organization they are forced to share credentials and use the same account. This said I as a user may want to receive notifications if other users close deployments intentionally.

Comment on lines +127 to +131
await this.notificationService.disableDeploymentAlerts({
userId: userWallet.userId,
walletAddress: userWallet.address!,
dseq
});
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This may be a cleaner approach indeed. Some logic to identify the event source would be needed here. Here's what the trigger event looks like:

[
  {
    "type": "akash.deployment.v1.EventDeploymentClosed",
    "attributes": [
      {
        "key": "id",
        "value": "{\"owner\":\"akash1sjds2vaquyax6zf88jhl9kt4enp3tqdn4r9erv\",\"dseq\":\"2330094\"}"
      },
      {
        "key": "msg_index",
        "value": "0"
      }
    ]
  }
]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants