Skip to content

Conversation

pujitm
Copy link
Member

@pujitm pujitm commented Oct 8, 2025

Summary by CodeRabbit

  • New Features
    • Added CPU power metrics, including total power and per-processor readings.
    • CPU power now appears in system info and system metrics.
    • Introduced a real-time subscription for CPU power updates.
    • Backwards compatible: existing CPU utilization data remains unchanged.

Copy link

claude bot commented Oct 8, 2025

Claude encountered an error —— View job


I'll analyze this and get back to you.

Copy link
Contributor

coderabbitai bot commented Oct 8, 2025

Walkthrough

Adds CPU power metrics to the API. Introduces CpuPower type in the schema, a CpuPowerService that reads RAPL counters to compute power, integrates CpuPower into InfoCpu, adds a new GraphQL subscription for systemMetricsCpuPower, wires modules and DI, updates metrics polling and PubSub channel, and adjusts related tests.

Changes

Cohort / File(s) Summary
GraphQL Schema
api/generated-schema.graphql
Adds CpuPower type; adds InfoCpu.power: CpuPower; adds Subscription.systemMetricsCpuPower: CpuPower!.
CPU Power Model & Service
api/src/unraid-api/graph/resolvers/info/cpu/cpu.model.ts, api/src/unraid-api/graph/resolvers/info/cpu/cpu-power.service.ts
Defines CpuPower model (totalPower, coresPower). Implements CpuPowerService.generateCpuPower() reading RAPL from /sys/class/powercap, computing per-package and total power with error handling.
CPU Module Wiring
api/src/unraid-api/graph/resolvers/info/cpu/cpu.module.ts, api/src/unraid-api/graph/resolvers/info/info.module.ts
Adds CpuModule exporting CpuService and CpuPowerService; InfoModule imports CpuModule and removes direct CpuService provider.
CpuService Integration & Tests
api/src/unraid-api/graph/resolvers/info/cpu/cpu.service.ts, api/src/unraid-api/graph/resolvers/info/cpu/cpu.service.spec.ts
Injects CpuPowerService and Logger into CpuService; generateCpu now includes power from CpuPowerService; tests mock CpuPowerService and expect power field.
Metrics Resolver & Module
api/src/unraid-api/graph/resolvers/metrics/metrics.module.ts, api/src/unraid-api/graph/resolvers/metrics/metrics.resolver.ts
MetricsModule now imports CpuModule; adds CpuPowerService to MetricsResolver; registers CPU_POWER polling (5s) and publishes systemMetricsCpuPower; adds subscription systemMetricsCpuPower.
Metrics Tests
api/src/unraid-api/graph/resolvers/metrics/metrics.resolver.spec.ts, api/src/unraid-api/graph/resolvers/metrics/metrics.resolver.integration.spec.ts
Test setup updated to include CpuPowerService; constructor updates; onModuleInit expectations include CPU_POWER topic.
Info Resolver Test
api/src/unraid-api/graph/resolvers/info/info.resolver.integration.spec.ts
Adds CpuPowerService to providers for integration testing.
PubSub Channel
packages/unraid-shared/src/pubsub/graphql.pubsub.ts
Adds GRAPHQL_PUBSUB_CHANNEL.CPU_POWER.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant App as MetricsResolver
  participant CPS as CpuPowerService
  participant Pub as PubSub
  participant Sub as Subscriber

  rect rgba(200,220,255,0.25)
    note over App: onModuleInit
    App->>Pub: register POLL CPU_POWER (5s)
    loop every 5s
      App->>CPS: generateCpuPower()
      CPS-->>App: CpuPower { totalPower, coresPower }
      App->>Pub: publish { systemMetricsCpuPower }
    end
  end

  rect rgba(220,255,220,0.25)
    Sub->>App: subscribe systemMetricsCpuPower
    App-->>Sub: async stream of CpuPower
  end
Loading
sequenceDiagram
  autonumber
  participant CPS as CpuPowerService
  participant FS as sysfs (/sys/class/powercap)
  participant Log as Logger

  CPS->>FS: list rapl:* domains
  alt none found
    CPS->>Log: warn "no domains"
    CPS-->>CPS: return { id }
  else domains found
    CPS->>FS: read energy_uj + max_energy_range_uj (t0)
    CPS-->>CPS: wait ~200ms
    CPS->>FS: read energy_uj (t1)
    CPS-->>CPS: compute deltas, wrap if needed
    CPS-->>CPS: aggregate coresPower[], totalPower
    CPS-->>CPS: return CpuPower
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Poem

A watt-wise warren, ears alert and keen,
I sniff the RAPL trails where numbers preen.
Packages hum, little cores all purr—
I tally their warmth with a whiskered whirr.
New channels hop, subscriptions bloom—
CPU power now banishes the gloom.
Thump-thump! Metrics glow, vrooms-vrooms!

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title clearly and concisely describes the primary change: adding a CPU power query and subscription, matching the pull request’s main modifications to the schema and resolvers.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/cpu-power

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

@@ -1,11 +1,19 @@
import { Injectable } from '@nestjs/common';
import { Injectable, Logger } from '@nestjs/common';
import { constants as fsConstants } from 'node:fs';

Check notice

Code scanning / CodeQL

Unused variable, import, function or class Note

Unused import fsConstants.

Copilot Autofix

AI 10 days ago

To fix this detected error, simply remove the unused import statement import { constants as fsConstants } from 'node:fs'; (line 2 in the code). No usages of fsConstants are present in the file snippet, so deleting the line will have no effect except for improving readability and potentially reducing unnecessary module resolution overhead. No other imports or edits need to be made. This change should be performed in the file api/src/unraid-api/graph/resolvers/info/cpu/cpu.service.ts, specifically removing line 2.

Suggested changeset 1
api/src/unraid-api/graph/resolvers/info/cpu/cpu.service.ts

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/api/src/unraid-api/graph/resolvers/info/cpu/cpu.service.ts b/api/src/unraid-api/graph/resolvers/info/cpu/cpu.service.ts
--- a/api/src/unraid-api/graph/resolvers/info/cpu/cpu.service.ts
+++ b/api/src/unraid-api/graph/resolvers/info/cpu/cpu.service.ts
@@ -1,5 +1,4 @@
 import { Injectable, Logger } from '@nestjs/common';
-import { constants as fsConstants } from 'node:fs';
 import { access, readdir, readFile } from 'node:fs/promises';
 import { basename, join } from 'node:path';
 
EOF
@@ -1,5 +1,4 @@
import { Injectable, Logger } from '@nestjs/common';
import { constants as fsConstants } from 'node:fs';
import { access, readdir, readFile } from 'node:fs/promises';
import { basename, join } from 'node:path';

Copilot is powered by AI and may make mistakes. Always verify output.
import { Injectable } from '@nestjs/common';
import { Injectable, Logger } from '@nestjs/common';
import { constants as fsConstants } from 'node:fs';
import { access, readdir, readFile } from 'node:fs/promises';

Check notice

Code scanning / CodeQL

Unused variable, import, function or class Note

Unused imports access, readFile, readdir.

Copilot Autofix

AI 10 days ago

To fix the unused imports issue, remove { access, readdir, readFile } from the import statement on line 3. Since none of these methods are used anywhere in the code block shown, remove the import line entirely for clarity unless additional symbols are added to the import in the future. No changes to method implementations or other imports are necessary. This change is made in api/src/unraid-api/graph/resolvers/info/cpu/cpu.service.ts, specifically on line 3.


Suggested changeset 1
api/src/unraid-api/graph/resolvers/info/cpu/cpu.service.ts

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/api/src/unraid-api/graph/resolvers/info/cpu/cpu.service.ts b/api/src/unraid-api/graph/resolvers/info/cpu/cpu.service.ts
--- a/api/src/unraid-api/graph/resolvers/info/cpu/cpu.service.ts
+++ b/api/src/unraid-api/graph/resolvers/info/cpu/cpu.service.ts
@@ -1,6 +1,6 @@
 import { Injectable, Logger } from '@nestjs/common';
 import { constants as fsConstants } from 'node:fs';
-import { access, readdir, readFile } from 'node:fs/promises';
+
 import { basename, join } from 'node:path';
 
 import { cpu, cpuFlags, currentLoad } from 'systeminformation';
EOF
@@ -1,6 +1,6 @@
import { Injectable, Logger } from '@nestjs/common';
import { constants as fsConstants } from 'node:fs';
import { access, readdir, readFile } from 'node:fs/promises';

import { basename, join } from 'node:path';

import { cpu, cpuFlags, currentLoad } from 'systeminformation';
Copilot is powered by AI and may make mistakes. Always verify output.
import { Injectable, Logger } from '@nestjs/common';
import { constants as fsConstants } from 'node:fs';
import { access, readdir, readFile } from 'node:fs/promises';
import { basename, join } from 'node:path';

Check notice

Code scanning / CodeQL

Unused variable, import, function or class Note

Unused imports basename, join.

Copilot Autofix

AI 10 days ago

To fix the problem, simply remove basename and join from the import statement on line 4:
Replace import { basename, join } from 'node:path'; with nothing, or remove only the unused named imports.
No changes to surrounding code are required, as neither basename nor join are used in this file.

Specifically, in api/src/unraid-api/graph/resolvers/info/cpu/cpu.service.ts, delete line 4 entirely.

Suggested changeset 1
api/src/unraid-api/graph/resolvers/info/cpu/cpu.service.ts

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/api/src/unraid-api/graph/resolvers/info/cpu/cpu.service.ts b/api/src/unraid-api/graph/resolvers/info/cpu/cpu.service.ts
--- a/api/src/unraid-api/graph/resolvers/info/cpu/cpu.service.ts
+++ b/api/src/unraid-api/graph/resolvers/info/cpu/cpu.service.ts
@@ -1,8 +1,8 @@
 import { Injectable, Logger } from '@nestjs/common';
 import { constants as fsConstants } from 'node:fs';
 import { access, readdir, readFile } from 'node:fs/promises';
-import { basename, join } from 'node:path';
 
+
 import { cpu, cpuFlags, currentLoad } from 'systeminformation';
 
 import { CpuPowerService } from '@app/unraid-api/graph/resolvers/info/cpu/cpu-power.service.js';
EOF
@@ -1,8 +1,8 @@
import { Injectable, Logger } from '@nestjs/common';
import { constants as fsConstants } from 'node:fs';
import { access, readdir, readFile } from 'node:fs/promises';
import { basename, join } from 'node:path';


import { cpu, cpuFlags, currentLoad } from 'systeminformation';

import { CpuPowerService } from '@app/unraid-api/graph/resolvers/info/cpu/cpu-power.service.js';
Copilot is powered by AI and may make mistakes. Always verify output.
@@ -1,13 +1,15 @@
import { Module } from '@nestjs/common';

import { CpuPowerService } from '@app/unraid-api/graph/resolvers/info/cpu/cpu-power.service.js';

Check notice

Code scanning / CodeQL

Unused variable, import, function or class Note

Unused import CpuPowerService.

Copilot Autofix

AI 10 days ago

To fix the unused import error for CpuPowerService, simply remove the import statement on line 3. This will improve code clarity and potentially decrease bundle size as unused code will not be included. No additional changes to functionality are needed. All other code and imports should be kept as is to preserve existing functionality.

Suggested changeset 1
api/src/unraid-api/graph/resolvers/metrics/metrics.module.ts

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/api/src/unraid-api/graph/resolvers/metrics/metrics.module.ts b/api/src/unraid-api/graph/resolvers/metrics/metrics.module.ts
--- a/api/src/unraid-api/graph/resolvers/metrics/metrics.module.ts
+++ b/api/src/unraid-api/graph/resolvers/metrics/metrics.module.ts
@@ -1,6 +1,5 @@
 import { Module } from '@nestjs/common';
 
-import { CpuPowerService } from '@app/unraid-api/graph/resolvers/info/cpu/cpu-power.service.js';
 import { CpuModule } from '@app/unraid-api/graph/resolvers/info/cpu/cpu.module.js';
 import { CpuService } from '@app/unraid-api/graph/resolvers/info/cpu/cpu.service.js';
 import { MemoryService } from '@app/unraid-api/graph/resolvers/info/memory/memory.service.js';
EOF
@@ -1,6 +1,5 @@
import { Module } from '@nestjs/common';

import { CpuPowerService } from '@app/unraid-api/graph/resolvers/info/cpu/cpu-power.service.js';
import { CpuModule } from '@app/unraid-api/graph/resolvers/info/cpu/cpu.module.js';
import { CpuService } from '@app/unraid-api/graph/resolvers/info/cpu/cpu.service.js';
import { MemoryService } from '@app/unraid-api/graph/resolvers/info/memory/memory.service.js';
Copilot is powered by AI and may make mistakes. Always verify output.
Copy link

codecov bot commented Oct 8, 2025

Codecov Report

❌ Patch coverage is 33.12500% with 107 lines in your changes missing coverage. Please review.
✅ Project coverage is 53.28%. Comparing base (754966d) to head (14c0f90).

Files with missing lines Patch % Lines
...-api/graph/resolvers/info/cpu/cpu-power.service.ts 20.17% 91 Missing ⚠️
...id-api/graph/resolvers/metrics/metrics.resolver.ts 47.36% 10 Missing ⚠️
...c/unraid-api/graph/resolvers/info/cpu/cpu.model.ts 45.45% 6 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1745      +/-   ##
==========================================
- Coverage   53.35%   53.28%   -0.08%     
==========================================
  Files         860      862       +2     
  Lines       48278    48430     +152     
  Branches     4929     4941      +12     
==========================================
+ Hits        25759    25804      +45     
- Misses      22450    22557     +107     
  Partials       69       69              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Contributor

github-actions bot commented Oct 8, 2025

This plugin has been deployed to Cloudflare R2 and is available for testing.
Download it at this URL:

https://preview.dl.unraid.net/unraid-api/tag/PR1745/dynamix.unraid.net.plg

Copy link
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: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
api/src/unraid-api/graph/resolvers/info/cpu/cpu.service.ts (1)

23-33: Guard against NaN for stepping; consider latency impact of power fetch.

  • Number(stepping) can yield NaN (GraphQL Int cannot represent NaN). Guard it.
  • generateCpuPower() performs a ~200ms sampling; this adds latency to the InfoCpu query. Consider caching, lazy resolution via a separate field resolver, or background sampling.
-            power: await this.cpuPowerService.generateCpuPower(),
-            stepping: Number(stepping),
+            power: await this.cpuPowerService.generateCpuPower(),
+            stepping: stepping != null && `${stepping}` !== '' ? Number(stepping) : undefined,
♻️ Duplicate comments (1)
api/src/unraid-api/graph/resolvers/info/cpu/cpu.service.ts (1)

2-4: Remove unused imports (CodeQL findings).

fsConstants, access, readdir, readFile, basename, join are unused in this file.

-import { constants as fsConstants } from 'node:fs';
-import { access, readdir, readFile } from 'node:fs/promises';
-import { basename, join } from 'node:path';
🧹 Nitpick comments (7)
api/src/unraid-api/graph/resolvers/info/info.module.ts (1)

5-5: Remove unused CpuService import.

CpuService is no longer used directly in InfoModule since it's now provided by CpuModule (line 18).

Apply this diff to remove the unused import:

-import { CpuService } from '@app/unraid-api/graph/resolvers/info/cpu/cpu.service.js';
api/src/unraid-api/graph/resolvers/metrics/metrics.module.ts (1)

3-5: Remove unused imports.

CpuPowerService and CpuService are imported but not directly used in MetricsModule. Both services are now provided by CpuModule (line 11), making these direct imports unnecessary.

Apply this diff to remove the unused imports:

-import { CpuPowerService } from '@app/unraid-api/graph/resolvers/info/cpu/cpu-power.service.js';
 import { CpuModule } from '@app/unraid-api/graph/resolvers/info/cpu/cpu.module.js';
-import { CpuService } from '@app/unraid-api/graph/resolvers/info/cpu/cpu.service.js';
api/src/unraid-api/graph/resolvers/info/cpu/cpu.model.ts (1)

51-61: Clarify naming vs. semantics (packages/sockets vs. cores).

The field name coresPower suggests per-core values, but RAPL reads package/socket power. Either rename the field or update the description to avoid confusion.

Apply this minimal-description fix:

-        description: 'CPU power in watts for each physical processor',
+        description: 'CPU power in watts for each CPU package/socket (physical processor)',
api/src/unraid-api/graph/resolvers/info/cpu/cpu-power.service.ts (4)

4-4: Use node:path for ESM consistency.

Prefer Node built-in ESM specifier.

-import { basename, join } from 'path';
+import { basename, join } from 'node:path';

46-48: Make sampling window a constant/configurable.

Hardcoded 200ms can be a knob for accuracy vs. latency; extract to a const.

-            // ~200ms delay to measure energy delta
-            await new Promise((resolve) => setTimeout(resolve, 200));
+            // Sampling window to measure energy delta
+            const measureWindowMs = 200;
+            await new Promise((resolve) => setTimeout(resolve, measureWindowMs));

71-78: Handle RAPL energy counter wrap-around.

energy_uj can wrap; adjust diff using max_energy_range_uj when negative.

-                const diffEnergy = now - prevE; // microjoules
+                let diffEnergy = now - prevE; // microjoules
+                if (diffEnergy < 0) {
+                    try {
+                        const maxFile = join(domainPath, 'max_energy_range_uj');
+                        await access(maxFile, fsConstants.R_OK);
+                        const maxStr = await readFile(maxFile, 'utf8');
+                        const maxRange = Number.parseInt(maxStr.trim(), 10);
+                        if (Number.isFinite(maxRange) && maxRange > 0) {
+                            diffEnergy = (now + maxRange) - prevE;
+                        }
+                    } catch {
+                        // if wrap-around can't be determined, skip this sample
+                        continue;
+                    }
+                }
                 const diffTimeNs = Number(tNow - prevT); // nanoseconds
                 if (!(diffTimeNs > 0)) continue;

132-134: Log unexpected errors for observability.

Capture and log the error; return safe default.

-        } catch {
-            return { id };
-        }
+        } catch (e) {
+            this.logger.debug(`generateCpuPower failed: ${String(e)}`);
+            return { id };
+        }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 754966d and 14c0f90.

📒 Files selected for processing (13)
  • api/generated-schema.graphql (3 hunks)
  • api/src/unraid-api/graph/resolvers/info/cpu/cpu-power.service.ts (1 hunks)
  • api/src/unraid-api/graph/resolvers/info/cpu/cpu.model.ts (2 hunks)
  • api/src/unraid-api/graph/resolvers/info/cpu/cpu.module.ts (1 hunks)
  • api/src/unraid-api/graph/resolvers/info/cpu/cpu.service.spec.ts (3 hunks)
  • api/src/unraid-api/graph/resolvers/info/cpu/cpu.service.ts (2 hunks)
  • api/src/unraid-api/graph/resolvers/info/info.module.ts (2 hunks)
  • api/src/unraid-api/graph/resolvers/info/info.resolver.integration.spec.ts (2 hunks)
  • api/src/unraid-api/graph/resolvers/metrics/metrics.module.ts (1 hunks)
  • api/src/unraid-api/graph/resolvers/metrics/metrics.resolver.integration.spec.ts (2 hunks)
  • api/src/unraid-api/graph/resolvers/metrics/metrics.resolver.spec.ts (3 hunks)
  • api/src/unraid-api/graph/resolvers/metrics/metrics.resolver.ts (4 hunks)
  • packages/unraid-shared/src/pubsub/graphql.pubsub.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (6)
api/src/unraid-api/**

📄 CodeRabbit inference engine (.cursor/rules/api-rules.mdc)

Prefer adding new files to the Nest repo at api/src/unraid-api/ instead of legacy code

Files:

  • api/src/unraid-api/graph/resolvers/info/info.resolver.integration.spec.ts
  • api/src/unraid-api/graph/resolvers/metrics/metrics.module.ts
  • api/src/unraid-api/graph/resolvers/info/cpu/cpu.model.ts
  • api/src/unraid-api/graph/resolvers/info/cpu/cpu.module.ts
  • api/src/unraid-api/graph/resolvers/metrics/metrics.resolver.integration.spec.ts
  • api/src/unraid-api/graph/resolvers/info/cpu/cpu-power.service.ts
  • api/src/unraid-api/graph/resolvers/info/info.module.ts
  • api/src/unraid-api/graph/resolvers/metrics/metrics.resolver.spec.ts
  • api/src/unraid-api/graph/resolvers/info/cpu/cpu.service.ts
  • api/src/unraid-api/graph/resolvers/info/cpu/cpu.service.spec.ts
  • api/src/unraid-api/graph/resolvers/metrics/metrics.resolver.ts
api/**/*.{test,spec}.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/api-rules.mdc)

api/**/*.{test,spec}.{js,jsx,ts,tsx}: Use Vitest for tests in the api; do not use Jest
Prefer not to mock simple dependencies in tests
For error testing, use .rejects.toThrow() without arguments; avoid asserting exact error messages unless the message format is the subject under test

Files:

  • api/src/unraid-api/graph/resolvers/info/info.resolver.integration.spec.ts
  • api/src/unraid-api/graph/resolvers/metrics/metrics.resolver.integration.spec.ts
  • api/src/unraid-api/graph/resolvers/metrics/metrics.resolver.spec.ts
  • api/src/unraid-api/graph/resolvers/info/cpu/cpu.service.spec.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx}: Use TypeScript import specifiers with .js extensions for ESM compatibility
Never use the any type; prefer precise typing
Avoid type casting; model proper types from the start

Files:

  • api/src/unraid-api/graph/resolvers/info/info.resolver.integration.spec.ts
  • packages/unraid-shared/src/pubsub/graphql.pubsub.ts
  • api/src/unraid-api/graph/resolvers/metrics/metrics.module.ts
  • api/src/unraid-api/graph/resolvers/info/cpu/cpu.model.ts
  • api/src/unraid-api/graph/resolvers/info/cpu/cpu.module.ts
  • api/src/unraid-api/graph/resolvers/metrics/metrics.resolver.integration.spec.ts
  • api/src/unraid-api/graph/resolvers/info/cpu/cpu-power.service.ts
  • api/src/unraid-api/graph/resolvers/info/info.module.ts
  • api/src/unraid-api/graph/resolvers/metrics/metrics.resolver.spec.ts
  • api/src/unraid-api/graph/resolvers/info/cpu/cpu.service.ts
  • api/src/unraid-api/graph/resolvers/info/cpu/cpu.service.spec.ts
  • api/src/unraid-api/graph/resolvers/metrics/metrics.resolver.ts
api/**/*.{test,spec}.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

api/**/*.{test,spec}.{ts,tsx}: API test suite is Vitest; do not use Jest
Prefer not to mock simple dependencies in API tests

Files:

  • api/src/unraid-api/graph/resolvers/info/info.resolver.integration.spec.ts
  • api/src/unraid-api/graph/resolvers/metrics/metrics.resolver.integration.spec.ts
  • api/src/unraid-api/graph/resolvers/metrics/metrics.resolver.spec.ts
  • api/src/unraid-api/graph/resolvers/info/cpu/cpu.service.spec.ts
{api,web}/**/*.{test,spec}.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

{api,web}/**/*.{test,spec}.{ts,tsx}: For error tests, use .rejects.toThrow() without arguments; avoid asserting exact error messages unless that format is the subject
Focus tests on behavior, not implementation details
Avoid brittle tests tied to exact error or log wording
Use mocks as nouns, not verbs
Always await async operations before making assertions
Place all mock declarations at the top level; use factory functions for module mocks; clear mocks between tests

Files:

  • api/src/unraid-api/graph/resolvers/info/info.resolver.integration.spec.ts
  • api/src/unraid-api/graph/resolvers/metrics/metrics.resolver.integration.spec.ts
  • api/src/unraid-api/graph/resolvers/metrics/metrics.resolver.spec.ts
  • api/src/unraid-api/graph/resolvers/info/cpu/cpu.service.spec.ts
api/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

cache-manager v7 TTL values must be in milliseconds (e.g., 600000 for 10 minutes)

Files:

  • api/src/unraid-api/graph/resolvers/info/info.resolver.integration.spec.ts
  • api/src/unraid-api/graph/resolvers/metrics/metrics.module.ts
  • api/src/unraid-api/graph/resolvers/info/cpu/cpu.model.ts
  • api/src/unraid-api/graph/resolvers/info/cpu/cpu.module.ts
  • api/src/unraid-api/graph/resolvers/metrics/metrics.resolver.integration.spec.ts
  • api/src/unraid-api/graph/resolvers/info/cpu/cpu-power.service.ts
  • api/src/unraid-api/graph/resolvers/info/info.module.ts
  • api/src/unraid-api/graph/resolvers/metrics/metrics.resolver.spec.ts
  • api/src/unraid-api/graph/resolvers/info/cpu/cpu.service.ts
  • api/src/unraid-api/graph/resolvers/info/cpu/cpu.service.spec.ts
  • api/src/unraid-api/graph/resolvers/metrics/metrics.resolver.ts
🧠 Learnings (2)
📚 Learning: 2025-08-09T01:03:29.676Z
Learnt from: elibosley
PR: unraid/api#1575
File: packages/unraid-shared/src/services/socket-config.service.spec.ts:10-13
Timestamp: 2025-08-09T01:03:29.676Z
Learning: Vitest is used for all testing across all repositories in the unraid organization, not Jest. Always use `vi` for mocking utilities, not `jest`.

Applied to files:

  • api/src/unraid-api/graph/resolvers/info/info.resolver.integration.spec.ts
  • api/src/unraid-api/graph/resolvers/info/cpu/cpu.service.spec.ts
📚 Learning: 2025-09-12T01:36:59.838Z
Learnt from: CR
PR: unraid/api#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-12T01:36:59.838Z
Learning: Applies to api/**/*.{test,spec}.{ts,tsx} : API test suite is Vitest; do not use Jest

Applied to files:

  • api/src/unraid-api/graph/resolvers/metrics/metrics.resolver.spec.ts
🧬 Code graph analysis (6)
api/src/unraid-api/graph/resolvers/metrics/metrics.module.ts (3)
api/src/unraid-api/graph/resolvers/info/cpu/cpu.module.ts (1)
  • Module (6-10)
api/src/unraid-api/graph/resolvers/resolvers.module.ts (1)
  • Module (37-76)
api/src/unraid-api/graph/services/services.module.ts (1)
  • Module (8-13)
api/src/unraid-api/graph/resolvers/info/cpu/cpu.model.ts (2)
api/src/unraid-api/graph/resolvers/info/info.model.ts (1)
  • ObjectType (13-44)
api/src/unraid-api/cli/generated/graphql.ts (1)
  • Node (1371-1373)
api/src/unraid-api/graph/resolvers/info/cpu/cpu.module.ts (2)
api/src/unraid-api/graph/resolvers/info/info.module.ts (1)
  • Module (17-37)
api/src/unraid-api/graph/resolvers/metrics/metrics.module.ts (1)
  • Module (10-15)
api/src/unraid-api/graph/resolvers/info/cpu/cpu-power.service.ts (1)
api/src/unraid-api/graph/resolvers/info/cpu/cpu.service.ts (1)
  • Injectable (11-54)
api/src/unraid-api/graph/resolvers/info/cpu/cpu.service.ts (1)
api/src/unraid-api/graph/resolvers/info/cpu/cpu-power.service.ts (1)
  • Injectable (8-136)
api/src/unraid-api/graph/resolvers/metrics/metrics.resolver.ts (2)
api/src/unraid-api/cli/generated/graphql.ts (1)
  • Subscription (2046-2058)
web/composables/gql/graphql.ts (1)
  • Subscription (2032-2044)
🪛 GitHub Check: CodeQL
api/src/unraid-api/graph/resolvers/metrics/metrics.module.ts

[notice] 3-3: Unused variable, import, function or class
Unused import CpuPowerService.

api/src/unraid-api/graph/resolvers/info/cpu/cpu.service.ts

[notice] 2-2: Unused variable, import, function or class
Unused import fsConstants.


[notice] 3-3: Unused variable, import, function or class
Unused imports access, readFile, readdir.


[notice] 4-4: Unused variable, import, function or class
Unused imports basename, join.

🔇 Additional comments (7)
packages/unraid-shared/src/pubsub/graphql.pubsub.ts (1)

8-8: LGTM!

The CPU_POWER channel addition is consistent with existing patterns and properly supports the new CPU power metrics feature.

api/src/unraid-api/graph/resolvers/info/cpu/cpu.service.spec.ts (1)

3-3: LGTM!

The test properly mocks the CpuPowerService dependency and updates expectations to include the new power field. The mock implementation is appropriately simple for unit testing.

Also applies to: 92-99, 130-130

api/src/unraid-api/graph/resolvers/metrics/metrics.resolver.integration.spec.ts (1)

8-8: LGTM!

The integration test correctly includes CpuPowerService in the DI container, enabling proper integration testing of CPU power metrics.

Also applies to: 26-26

api/src/unraid-api/graph/resolvers/metrics/metrics.resolver.spec.ts (1)

6-6: LGTM!

The test correctly accommodates the new CpuPowerService dependency and updates the topic registration expectation from 2 to 3 to account for the new CPU_POWER topic.

Also applies to: 22-22, 168-168, 176-176

api/src/unraid-api/graph/resolvers/info/cpu/cpu.module.ts (1)

1-10: LGTM!

The CpuModule is well-structured and follows NestJS conventions. The module properly encapsulates CPU-related services and exports them for use by other modules.

api/src/unraid-api/graph/resolvers/info/info.resolver.integration.spec.ts (1)

9-9: LGTM!

The integration test correctly includes CpuPowerService in the DI container, ensuring the new CPU power functionality is properly tested.

Also applies to: 32-32

api/src/unraid-api/graph/resolvers/metrics/metrics.resolver.ts (1)

91-101: Approve CPU power subscription wiring

PUBSUB_CHANNEL.CPU_POWER is defined in the shared GRAPHQL_PUBSUB_CHANNEL enum.

Comment on lines +1404 to +1413
type CpuPower implements Node {
id: PrefixedID!

"""CPU power in watts"""
totalPower: Float

"""CPU power in watts for each physical processor"""
coresPower: [Float!]
}

Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Regenerate client GraphQL types to include CpuPower and systemMetricsCpuPower.

Schema adds CpuPower and systemMetricsCpuPower, but client types in snippets don’t include them. Regenerate CLI/web GraphQL typings to avoid runtime/type errors.

Run to verify and locate missing/updated references:

Also applies to: 1459-1461, 2658-2658


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Searching for systemMetricsCpuPower in repo..."
rg -n "systemMetricsCpuPower" -g "!**/node_modules/**" -C2 || true

echo
echo "Checking generated Subscription types in known clients..."
rg -nP "(?s)export\s+type\s+Subscription\s*=\s*{[^}]*}" api/src/unraid-api/cli/generated/graphql.ts -C2 || true
rg -nP "(?s)export\s+type\s+Subscription\s*=\s*{[^}]*}" web/composables/gql/graphql.ts -C2 || true

Length of output: 254


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Locating all graphql.ts files..."
fd graphql.ts

echo
echo "Searching for systemMetricsCpuPower in TS files..."
rg -n "systemMetricsCpuPower" -t ts -C2 || true

echo
echo "Searching for CpuPower in TS files..."
rg -n "CpuPower" -t ts -C2 || true

echo
echo "Searching for Subscription type definitions in TS files..."
rg -nP "export\s+type\s+Subscription\s*=\s*{" -t ts -C2 || true

Length of output: 17850


Regenerate GraphQL client typings for CLI, plugin, and web: Subscription type in generated outputs (api/src/unraid-api/cli/generated/graphql.ts, packages/unraid-api-plugin-connect/src/graphql/generated/client/graphql.ts, web/composables/gql/graphql.ts, web/src/composables/gql/graphql.ts) is missing the new systemMetricsCpuPower and CpuPower fields. Rerun your GraphQL code generation to include them.

🤖 Prompt for AI Agents
In api/generated-schema.graphql around lines 1404 to 1413 the new CpuPower type
and related fields (systemMetricsCpuPower and CpuPower) were added but the
generated GraphQL client typings for CLI, plugin, and web were not updated;
rerun the project's GraphQL code generation (the repo's graphql-codegen /
generate scripts) for the following targets:
api/src/unraid-api/cli/generated/graphql.ts,
packages/unraid-api-plugin-connect/src/graphql/generated/client/graphql.ts,
web/composables/gql/graphql.ts, and web/src/composables/gql/graphql.ts so the
subscription types include systemMetricsCpuPower and CpuPower, then commit the
regenerated files.

Comment on lines +37 to +45
// Register CPU power polling with 1 second interval
this.subscriptionTracker.registerTopic(
PUBSUB_CHANNEL.CPU_POWER,
async () => {
const payload = await this.cpuPowerService.generateCpuPower();
pubsub.publish(PUBSUB_CHANNEL.CPU_POWER, { systemMetricsCpuPower: payload });
},
5000
);
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Fix interval comment to match 5000ms.

Comment says 1s; code uses 5000ms.

-        // Register CPU power polling with 1 second interval
+        // Register CPU power polling with 5 second interval
📝 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.

Suggested change
// Register CPU power polling with 1 second interval
this.subscriptionTracker.registerTopic(
PUBSUB_CHANNEL.CPU_POWER,
async () => {
const payload = await this.cpuPowerService.generateCpuPower();
pubsub.publish(PUBSUB_CHANNEL.CPU_POWER, { systemMetricsCpuPower: payload });
},
5000
);
// Register CPU power polling with 5 second interval
this.subscriptionTracker.registerTopic(
PUBSUB_CHANNEL.CPU_POWER,
async () => {
const payload = await this.cpuPowerService.generateCpuPower();
pubsub.publish(PUBSUB_CHANNEL.CPU_POWER, { systemMetricsCpuPower: payload });
},
5000
);
🤖 Prompt for AI Agents
In api/src/unraid-api/graph/resolvers/metrics/metrics.resolver.ts around lines
37 to 45, the inline comment incorrectly states a 1 second interval while the
subscriptionTracker is configured with 5000ms; update the comment to accurately
reflect the 5000ms (5 seconds) interval so code and comment match.

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.

1 participant