Skip to content

Test to check vercel CI#94

Closed
Im-Madhur-Gupta wants to merge 7 commits intomainfrom
jake/monitoring
Closed

Test to check vercel CI#94
Im-Madhur-Gupta wants to merge 7 commits intomainfrom
jake/monitoring

Conversation

@Im-Madhur-Gupta
Copy link
Copy Markdown
Collaborator

Motivation:

Explain here the context, and why you're making that change. What is the problem you're trying to solve.

Modifications:

Describe the modifications you've done.

Result:

After your change, what will change.

@vercel
Copy link
Copy Markdown

vercel bot commented Apr 2, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
monode Ready Ready Preview, Comment Apr 2, 2026 10:23am

Request Review

@Im-Madhur-Gupta Im-Madhur-Gupta changed the title Test Test to check vercel CI Apr 2, 2026
@socket-security
Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Addednpm/​@​types/​ws@​8.18.11001007480100
Addednpm/​@​types/​node@​20.19.131001008195100
Addednpm/​tsx@​4.20.51001008185100
Addednpm/​typescript@​5.9.2100100909990
Addednpm/​@​slack/​web-api@​7.10.09910010093100
Addednpm/​dotenv@​16.6.19910010096100

View full report

@greptile-apps
Copy link
Copy Markdown

greptile-apps bot commented Apr 2, 2026

Greptile Summary

This PR introduces a new monitoring package — a standalone TypeScript service that connects to the backend via WebSocket, watches for incoming execution events, and fires Slack alerts when silence exceeds a configurable threshold. It also adds native-tls support to the Rust backend's tokio-tungstenite dependency.

Key changes:

  • New monitoring/src/main.ts: WebSocketMonitor class with health-check loop, exponential-backoff reconnect, configurable connection-lifetime refresh, and Slack alerting (fatal / recovery / online / offline notifications)
  • New monitoring/ scaffolding: package.json, tsconfig.json, biome.json, pnpm-lock.yaml, pnpm-workspace.yaml, .env.example
  • backend/Cargo.toml: adds native-tls feature to tokio-tungstenite

Issues found:

  • Race condition in sendFatalAlert: lastNotification is only written after the async Slack API call completes. Because checkHealth fires every 2 seconds without await, multiple concurrent invocations can all pass the cooldown guard before any of them finish, resulting in duplicate Slack messages on the very first alert.
  • Commented-out subscribe message: The WebSocket subscription block is commented out with a note that it "must be sent within 10 seconds." If the server requires a subscription to push events, the monitor will never receive messages and will immediately enter a permanent fatal-alert loop.
  • .env.example inaccuracies: The comment says COOLDOWN_MS defaults to 5 minutes, but the code sets 300_000 * 3 = 900_000 ms (15 minutes). The CONNECTION_MAX_LIFETIME_MIN variable is also undocumented.
  • sendOnlineAlert sends empty blocks array: Unlike all other alert methods, the online alert passes blocks: [], resulting in an unformatted plain-text Slack message.

Confidence Score: 3/5

Not safe to merge as-is — the commented-out subscribe message may cause the monitor to be permanently in false-alert mode, and the race condition in sendFatalAlert can spam Slack on first trigger.

Two P1 issues are present: (1) the subscribe message is commented out, which may prevent events from ever being received and cause constant false alerts that spam the Slack channel, and (2) the async race condition in sendFatalAlert allows duplicate concurrent Slack messages. Both need to be resolved before this service runs in production.

monitoring/src/main.ts requires the most attention — specifically the commented-out subscribe block and the sendFatalAlert race condition.

Important Files Changed

Filename Overview
monitoring/src/main.ts New WebSocket monitoring service with Slack alerting — has a race condition in sendFatalAlert (lastNotification set after async Slack call allows duplicate alerts) and a commented-out subscribe message that may prevent events from ever being received.
monitoring/.env.example COOLDOWN_MS default is documented as 5 minutes but the code defaults to 15 minutes; CONNECTION_MAX_LIFETIME_MIN env var is missing from this file.
monitoring/package.json Adds new monitoring package with @slack/web-api, ws, dotenv dependencies and biome/tsx dev tooling — looks correct.
backend/Cargo.toml Adds native-tls feature to tokio-tungstenite dependency for TLS WebSocket support.

Sequence Diagram

sequenceDiagram
    participant M as WebSocketMonitor
    participant WS as Backend WebSocket
    participant HI as setInterval (2s)
    participant SL as Slack API

    M->>WS: new WebSocket(backendUrl)
    WS-->>M: open event
    M->>M: scheduleConnectionRefresh()
    Note over M: (subscribe message commented out)

    loop Every 2 seconds
        HI->>M: checkHealth()
        alt silenceDuration > SILENCE_THRESHOLD
            M->>M: inFatalState = true
            M->>M: sendFatalAlert() [no await]
            M->>SL: chat.postMessage (fatal alert)
            SL-->>M: ok
            M->>M: lastNotification = now
        else silenceDuration <= threshold & was in fatal state
            M->>M: inFatalState = false
            M->>M: sendRecoveryAlert() [no await]
            M->>SL: chat.postMessage (recovery)
        end
    end

    WS-->>M: message event
    M->>M: lastMessageTime = Date.now()

    WS-->>M: close event
    M->>M: scheduleReconnect() (exp. backoff)
    M->>WS: new WebSocket(backendUrl)

    M->>M: shutdown(SIGINT/SIGTERM)
    M->>SL: chat.postMessage (offline alert)
    M->>M: process.exit(0)
Loading

Reviews (1): Last reviewed commit: "reset last msg time on reconnect" | Re-trigger Greptile

Comment on lines +223 to +235
private async sendFatalAlert(silenceDuration: number) {
const now = Date.now()

// Check cooldown
if (
this.lastNotification > 0 &&
now - this.lastNotification < COOLDOWN_MS
) {
console.log(
`Skipping alert (cooldown: ${((now - this.lastNotification) / 1000).toFixed(0)}s / ${(COOLDOWN_MS / 1000).toFixed(0)}s)`,
)
return
}
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 Race condition allows duplicate Slack alerts

sendFatalAlert is an async function but is called without await from checkHealth (which runs every 2 seconds via setInterval). The cooldown guard only prevents duplicate alerts after this.lastNotification has been set — but lastNotification is only updated after the Slack API call completes (line 310). During the initial alert window when lastNotification === 0, the condition this.lastNotification > 0 && ... is false, so every health-check tick (every 2 s) that fires before the first Slack response will pass the guard and dispatch a separate Slack message.

To fix this, set this.lastNotification = now before the await call so subsequent concurrent invocations see it immediately:

Suggested change
private async sendFatalAlert(silenceDuration: number) {
const now = Date.now()
// Check cooldown
if (
this.lastNotification > 0 &&
now - this.lastNotification < COOLDOWN_MS
) {
console.log(
`Skipping alert (cooldown: ${((now - this.lastNotification) / 1000).toFixed(0)}s / ${(COOLDOWN_MS / 1000).toFixed(0)}s)`,
)
return
}
private async sendFatalAlert(silenceDuration: number) {
const now = Date.now()
// Check cooldown
if (
this.lastNotification > 0 &&
now - this.lastNotification < COOLDOWN_MS
) {
console.log(
`Skipping alert (cooldown: ${((now - this.lastNotification) / 1000).toFixed(0)}s / ${(COOLDOWN_MS / 1000).toFixed(0)}s)`,
)
return
}
// Lock immediately to prevent concurrent calls from bypassing the cooldown
this.lastNotification = now

Comment on lines +84 to +92
// Send subscribe message (must be sent within 10 seconds)
//const subscribeMessage = {
//type: 'subscribe',
//event_filters: [
//{'event_name': 'BlockStart'}
//]
//}
//this.ws?.send(JSON.stringify(subscribeMessage))
//console.log('Sent subscribe message')
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 Commented-out subscribe message may cause constant false alerts

The subscribe message that registers this client to receive events is entirely commented out. The inline comment itself says "must be sent within 10 seconds," which suggests the server requires it. If the WebSocket server only sends events to subscribed clients, this monitor will never receive any messages and will immediately and permanently report a "FATAL STATE: No messages" alert after the 10-second SILENCE_THRESHOLD_MS.

If the subscription is intentionally disabled (e.g., the server pushes events to all connections automatically), the dead code block should be removed to avoid confusion. If it is still needed, it should be re-enabled before this service goes live.

Comment on lines +9 to +10
# SILENCE_THRESHOLD_MS=10000 # Default: 10 seconds
# COOLDOWN_MS=300000 # Default: 5 minutes
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 COOLDOWN_MS default documented incorrectly + missing CONNECTION_MAX_LIFETIME_MIN

Two documentation gaps in the env example:

  1. The comment says the default for COOLDOWN_MS is 5 minutes (300000 ms), but the source code sets it to 300_000 * 3 = 900_000 ms (15 minutes). Operators relying on this file to understand defaults will be misled.

  2. The CONNECTION_MAX_LIFETIME_MIN variable (used on line 14 of main.ts, defaulting to 5 minutes) is not listed here at all. It should be documented so it can be tuned.

Suggested addition:

Suggested change
# SILENCE_THRESHOLD_MS=10000 # Default: 10 seconds
# COOLDOWN_MS=300000 # Default: 5 minutes
# Optional: Override default thresholds
# SILENCE_THRESHOLD_MS=10000 # Default: 10 seconds
# COOLDOWN_MS=900000 # Default: 15 minutes
# CONNECTION_MAX_LIFETIME_MIN=5 # Default: 5 minutes

Comment on lines +379 to +386
try {
await this.slackClient.chat.postMessage({
channel: this.config.slackChannel,
text: '🟢 *Monode Monitor Service Online*',
blocks: [],
})

console.log('Slack online alert sent')
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 sendOnlineAlert sends an empty blocks array

Every other alert method (sendOfflineAlert, sendFatalAlert) fills the blocks array with properly formatted sections. sendOnlineAlert passes blocks: [], which means Slack will only display the plain-text text field with no rich formatting. This is inconsistent with the other alerts. Consider either populating the blocks or removing the blocks key entirely to rely solely on the text field.

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