BUG: getActiveDownloads makes redundant concurrent HTTP requests to SABnzbd queue endpoint #36

Closed
opened 2026-05-22 19:11:10 +01:00 by Gandalf · 1 comment
Owner

Problem Location

  • File: server/clients/SABnzbdClient.js
  • Lines: 45-52 (within getActiveDownloads) and lines 93-100 (within getClientStatus)

Issue Details

In SABnzbdClient.js, the getActiveDownloads() method initiates concurrent requests using Promise.all:

      // Get both queue and history to provide complete picture
      const [queueResponse, historyResponse, clientStatus] = await Promise.all([
        this.makeRequest({ mode: 'queue' }),
        this.makeRequest({ mode: 'history', limit: 10 }),
        this.getClientStatus()
      ]);

However, looking at the implementation of getClientStatus():

  async getClientStatus() {
    try {
      const response = await this.makeRequest({ mode: 'queue' });
      const queueData = response.data.queue;
      ...

We see that getClientStatus() internally makes the exact same this.makeRequest({ mode: 'queue' }) request.
As a result, calling getActiveDownloads() triggers two concurrent and identical requests to the SABnzbd /api?mode=queue endpoint during every polling cycle. This redundant HTTP overhead wastes SABnzbd instance CPU/memory resource, network bandwidth, and application memory, especially when polling frequently.

Proposed Fix

Avoid calling this.getClientStatus() concurrently in getActiveDownloads() when we already have the queue response. Instead, extract the client status directly from the fetched queueResponse data.

Specifically, in getActiveDownloads(), query queue and history in parallel, and then construct the clientStatus info directly from queueData.queue. This eliminates the redundant API request entirely.

### Problem Location - **File**: `server/clients/SABnzbdClient.js` - **Lines**: 45-52 (within `getActiveDownloads`) and lines 93-100 (within `getClientStatus`) ### Issue Details In `SABnzbdClient.js`, the `getActiveDownloads()` method initiates concurrent requests using `Promise.all`: ```javascript // Get both queue and history to provide complete picture const [queueResponse, historyResponse, clientStatus] = await Promise.all([ this.makeRequest({ mode: 'queue' }), this.makeRequest({ mode: 'history', limit: 10 }), this.getClientStatus() ]); ``` However, looking at the implementation of `getClientStatus()`: ```javascript async getClientStatus() { try { const response = await this.makeRequest({ mode: 'queue' }); const queueData = response.data.queue; ... ``` We see that `getClientStatus()` internally makes the exact same `this.makeRequest({ mode: 'queue' })` request. As a result, calling `getActiveDownloads()` triggers two concurrent and identical requests to the SABnzbd `/api?mode=queue` endpoint during every polling cycle. This redundant HTTP overhead wastes SABnzbd instance CPU/memory resource, network bandwidth, and application memory, especially when polling frequently. ### Proposed Fix Avoid calling `this.getClientStatus()` concurrently in `getActiveDownloads()` when we already have the queue response. Instead, extract the client status directly from the fetched `queueResponse` data. Specifically, in `getActiveDownloads()`, query queue and history in parallel, and then construct the clientStatus info directly from `queueData.queue`. This eliminates the redundant API request entirely.
Gandalf added the Kind/Bug label 2026-05-22 19:16:27 +01:00
Author
Owner

Resolved via commit 12c44a6 (removed redundant getClientStatus call).

Resolved via commit 12c44a6 (removed redundant getClientStatus call).
Gandalf added the Area/Download Clients label 2026-05-28 11:53:52 +01:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Gandalf/sofarr#36