Skip to content

feat: add parityCheckStatus field to array query#1611

Merged
pujitm merged 11 commits intomainfrom
feat/parity-check-status
Aug 25, 2025
Merged

feat: add parityCheckStatus field to array query#1611
pujitm merged 11 commits intomainfrom
feat/parity-check-status

Conversation

@pujitm
Copy link
Member

@pujitm pujitm commented Aug 21, 2025

Responds with a ParityCheck:

type ParityCheck {
  """Date of the parity check"""
  date: DateTime

  """Duration of the parity check in seconds"""
  duration: Int

  """Speed of the parity check, in MB/s"""
  speed: String

  """Status of the parity check"""
  status: ParityCheckStatus!

  """Number of errors during the parity check"""
  errors: Int

  """Progress percentage of the parity check"""
  progress: Int

  """Whether corrections are being written to parity"""
  correcting: Boolean

  """Whether the parity check is paused"""
  paused: Boolean

  """Whether the parity check is running"""
  running: Boolean
}

enum ParityCheckStatus {
    NEVER_RUN = 'never_run',
    RUNNING = 'running',
    PAUSED = 'paused',
    COMPLETED = 'completed',
    CANCELLED = 'cancelled',
    FAILED = 'failed',
}

Summary by CodeRabbit

  • New Features

    • Exposes a structured parity-check status for arrays with detailed fields (status enum: NEVER_RUN, RUNNING, PAUSED, COMPLETED, CANCELLED, FAILED), date, duration, speed, progress, errors, and running/paused flags.
  • Tests

    • Adds comprehensive unit tests covering all parity-check states, numeric edge cases, speed/date/duration/progress calculations, and real-world scenarios.
  • Refactor

    • Safer numeric/date parsing and a new numeric-conversion helper; minor formatting/cleanup in shared utilities.

Responds with one of:
```ts
export enum ParityCheckStatus {
    NEVER_RUN = 'never_run',
    RUNNING = 'running',
    PAUSED = 'paused',
    COMPLETED = 'completed',
    CANCELLED = 'cancelled',
    FAILED = 'failed',
}
```
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Aug 21, 2025

Walkthrough

Adds a structured ParityCheck model and ParityCheckStatus enum, wires runtime parity status computation into array data, extends Var state fields, registers the enum with GraphQL, replaces string-based status handling in parity services, adds toNumberAlways helper, and includes comprehensive parity-status unit tests.

Changes

Cohort / File(s) Summary of changes
GraphQL schema
api/generated-schema.graphql
Replaced prior parity-check representation with a new type ParityCheck, added scalar DateTime, and added enum ParityCheckStatus { NEVER_RUN, RUNNING, PAUSED, COMPLETED, CANCELLED, FAILED }. Added parityCheckStatus: ParityCheck! on UnraidArray.
Array data integration
api/src/core/modules/array/get-array-data.ts
Injected parityCheckStatus into returned UnraidArray by calling getParityCheckStatus(emhttp.var).
Parity status implementation
api/src/core/modules/array/parity-check-status.ts, api/src/core/modules/array/parity-check-status.test.ts
New module exporting ParityCheckStatus enum and getParityCheckStatus(varData) that computes status, speed, date, duration, and progress from Var fields. Added comprehensive unit tests covering status permutations and numeric coercion/edge cases.
Var state types
api/src/core/types/states/var.ts
Added parity/resync-related fields to Var: mdResync, mdResyncDt, mdResyncPos, mdResyncSize, sbSynced, sbSynced2, sbSyncErrs, sbSyncExit (with documentation).
GraphQL parity layer
api/src/unraid-api/graph/resolvers/array/parity.model.ts, api/src/unraid-api/graph/resolvers/array/parity.service.ts, api/src/unraid-api/graph/resolvers/array/array.model.ts, api/src/unraid-api/graph/resolvers/array/array.service.spec.ts
Registered ParityCheckStatus with GraphQL; updated ParityCheck.status to use the enum; parity.service.ts maps numeric status codes to enum via statusCodeToStatusEnum; test mocks updated to include structured parityCheckStatus.
Shared util
packages/unraid-shared/src/util/data.ts
Added toNumberAlways(value, defaultValue = 0): number helper; minor formatting adjustments to existing utilities.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor Client
  participant GraphQL
  participant ArrayService
  participant StateStore as Store
  participant ParityModule as getParityCheckStatus

  rect rgba(230,245,255,0.6)
    Client->>GraphQL: Query UnraidArray { parityCheckStatus }
    GraphQL->>ArrayService: getArray()
    ArrayService->>StateStore: getters.emhttp().var
    StateStore-->>ArrayService: Var
    ArrayService->>ParityModule: getParityCheckStatus(Var)
    ParityModule-->>ArrayService: ParityCheck { status, progress, date, duration, speed }
    ArrayService-->>GraphQL: UnraidArray { ..., parityCheckStatus }
    GraphQL-->>Client: Response
  end

  note right of ParityModule: Decision precedence (high-level): RUNNING/PAUSED → NEVER_RUN → CANCELLED(-4) → FAILED(!=0) → COMPLETED(sbSynced2>0) → NEVER_RUN
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • elibosley
  • mdatelle
  • zackspear

Poem

I nibble logs and parse the night,
RUNNING, PAUSED — I keep them right.
NEVER_RUN whispers, CANCELLED hops,
FAILED beeps, COMPLETED stops.
A rabbit cheers: parity gleams bright 🥕

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/parity-check-status

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@claude
Copy link

claude bot commented Aug 21, 2025

Claude finished @pujitm's task —— View job


Code Review - Analyzing Diff Only

  • Read changed files and identify diff lines only
  • Analyze diff for critical bugs, security issues, breaking changes, data loss risks
  • Provide feedback focusing on high-priority issues only

Analysis Results

Reviewing only the modified lines in the recent commits, I found one potential critical bug:

⚠️ Line 46 in parity.service.ts: Redundant toNumberAlways call

: toNumberAlways(statusCode, 0) === 0  // statusCode is already a number

This line applies toNumberAlways to statusCode which is already guaranteed to be a number from the function signature. While not breaking, this is redundant logic that could be simplified to just statusCode === 0.

✅ Other changes look good:

  • Progress calculation fix (lines 67-70 parity-check-status.ts) properly clamps values 0-100 and handles division by zero
  • Date/duration validation (lines 27-31 parity.service.ts) properly handles invalid dates and NaN durations
  • Type narrowing with RelevantVarData improves type safety
  • Error handling with fallback status code 422 is appropriate

✅ No critical issues found - no security vulnerabilities, data loss risks, or breaking changes identified in the diff.

@pujitm pujitm requested a review from elibosley August 21, 2025 18:37
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: 0

🧹 Nitpick comments (8)
packages/unraid-shared/src/util/data.ts (2)

19-27: Minor: make opts optional and destructure defaults to avoid creating a new object each call

This keeps behavior identical while avoiding allocating { noEmpty: true } on every call and makes the signature a bit friendlier.

-export function csvStringToArray(
-  csvString?: string | null,
-  opts: { noEmpty?: boolean } = { noEmpty: true }
-): string[] {
-  if (!csvString) return [];
-  const result = csvString.split(",").map((item) => item.trim());
-  if (opts.noEmpty) {
-    return result.filter((item) => item !== "");
-  }
-  return result;
-}
+export function csvStringToArray(
+  csvString?: string | null,
+  opts?: { noEmpty?: boolean }
+): string[] {
+  if (!csvString) return [];
+  const { noEmpty = true } = opts ?? {};
+  const result = csvString.split(",").map((item) => item.trim());
+  if (noEmpty) {
+    return result.filter((item) => item !== "");
+  }
+  return result;
+}

53-63: Harden numeric coercion against Infinity while keeping NaN fallback semantics

Consider treating non-finite numbers the same as NaN. This is a safe enhancement for defensive parsing and does not affect typical Var inputs.

 export function toNumberAlways(value: unknown, defaultValue = 0): number {
   const num = Number(value);
-  return Number.isNaN(num) ? defaultValue : num;
+  return Number.isFinite(num) ? num : defaultValue;
 }

If desired, we can add a short note to the JSDoc clarifying that empty strings and null coerce to 0 (by design).

api/src/unraid-api/graph/resolvers/array/parity.model.ts (1)

1-7: Enum registration looks good; verify there's no import-order coupling

Registering ParityCheckStatus here is fine, but UnraidArray in array.model.ts consumes the enum too. Today this file is imported by ParityService, so registration will happen before schema generation, but that coupling is implicit. Consider centralizing enum registrations in a small GraphQL-layer enums module that’s imported unconditionally by the GraphQL module to avoid order pitfalls.

api/src/unraid-api/graph/resolvers/array/parity.service.ts (1)

97-100: Add a guard and GraphQL-friendly error if emhttp.var is absent

Aligns with prior guidance to surface read errors as GraphQLError at the service level and avoids possible runtime undefined access in edge environments.

-    async getParityCheckStatus(): Promise<ParityCheckStatus> {
-        const { getters } = await import('@app/store/index.js');
-        return getParityCheckStatus(getters.emhttp().var);
-    }
+    async getParityCheckStatus(): Promise<ParityCheckStatus> {
+        const { getters } = await import('@app/store/index.js');
+        const emhttp = getters.emhttp?.();
+        if (!emhttp?.var) {
+            throw new GraphQLError('emhttp.var not available');
+        }
+        return getParityCheckStatus(emhttp.var);
+    }
api/src/core/modules/array/parity-check-status.ts (1)

19-21: Coerce mdResyncPos for robustness and consistency.

You already normalize mdResyncDt and sbSyncExit via toNumberAlways. mdResyncPos can also arrive as a string depending on source; coercing it avoids subtle truthiness/coercion pitfalls and keeps logic uniform.

Apply this diff:

 export function getParityCheckStatus(varData: Var): ParityCheckStatus {
-    const { mdResyncPos, mdResyncDt, sbSyncExit, sbSynced, sbSynced2 } = varData;
+    const { mdResyncPos, mdResyncDt, sbSyncExit, sbSynced, sbSynced2 } = varData;
     const mdResyncDtNumber = toNumberAlways(mdResyncDt, 0);
     const sbSyncExitNumber = toNumberAlways(sbSyncExit, 0);
+    const mdResyncPosNumber = toNumberAlways(mdResyncPos as any, 0);
 
-    if (mdResyncPos > 0) {
+    if (mdResyncPosNumber > 0) {
         return mdResyncDtNumber > 0 ? ParityCheckStatus.RUNNING : ParityCheckStatus.PAUSED;
     }
api/src/core/types/states/var.ts (1)

71-76: Docstring for mdResync is misleading; it suggests a running-state indicator.

Running/paused detection is implemented via mdResyncPos and mdResyncDt. mdResync typically represents total size of the operation.

Apply this doc-only tweak:

-    /**
-     * Serves a dual purpose depending on context:
-     * - Total size of the operation (in sectors/blocks)
-     * - Running state indicator (0 = paused, >0 = running)
-     */
+    /**
+     * Total size of the resync/parity operation (in sectors/blocks).
+     * Use mdResyncPos (> 0) and mdResyncDt (> 0) to determine running/paused state.
+     */
api/src/core/modules/array/parity-check-status.test.ts (2)

422-431: Test name doesn’t match the assertion (Infinity case).

Title says “PAUSED” but the expectation is RUNNING (and the comment explains why).

Apply this rename:

-        it('should return PAUSED when mdResyncDt is Infinity string', () => {
+        it('should return RUNNING when mdResyncDt is Infinity string', () => {

46-86: Optional: add a case for string mdResyncPos to lock in robustness if we coerce it.

This guards against regressions if mdResyncPos arrives as a string from emhttp.var.

Add:

+        it('should handle string mdResyncPos by treating as RUNNING when > 0', () => {
+            const varData = createMockVarData({
+                mdResyncPos: '100' as any,
+                mdResyncDt: '1',
+            });
+            expect(getParityCheckStatus(varData)).toBe(ParityCheckStatus.RUNNING);
+        });

Note: This will pass if the mdResyncPos coercion suggested in parity-check-status.ts is applied or if ingestion already coerces it.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between fd895ca and b37935b.

📒 Files selected for processing (10)
  • api/generated-schema.graphql (2 hunks)
  • api/src/core/modules/array/get-array-data.ts (2 hunks)
  • api/src/core/modules/array/parity-check-status.test.ts (1 hunks)
  • api/src/core/modules/array/parity-check-status.ts (1 hunks)
  • api/src/core/types/states/var.ts (2 hunks)
  • api/src/unraid-api/graph/resolvers/array/array.model.ts (2 hunks)
  • api/src/unraid-api/graph/resolvers/array/array.service.spec.ts (2 hunks)
  • api/src/unraid-api/graph/resolvers/array/parity.model.ts (1 hunks)
  • api/src/unraid-api/graph/resolvers/array/parity.service.ts (2 hunks)
  • packages/unraid-shared/src/util/data.ts (2 hunks)
🧰 Additional context used
📓 Path-based instructions (7)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

TypeScript source files must use import specifiers with .js extensions for ESM compatibility

Files:

  • api/src/core/modules/array/parity-check-status.ts
  • api/src/core/modules/array/parity-check-status.test.ts
  • packages/unraid-shared/src/util/data.ts
  • api/src/unraid-api/graph/resolvers/array/parity.service.ts
  • api/src/unraid-api/graph/resolvers/array/parity.model.ts
  • api/src/unraid-api/graph/resolvers/array/array.model.ts
  • api/src/unraid-api/graph/resolvers/array/array.service.spec.ts
  • api/src/core/types/states/var.ts
  • api/src/core/modules/array/get-array-data.ts
**/*.{ts,tsx,js,jsx,vue}

📄 CodeRabbit inference engine (CLAUDE.md)

Avoid unnecessary or obvious comments; only add comments when needed for clarity

Files:

  • api/src/core/modules/array/parity-check-status.ts
  • api/src/core/modules/array/parity-check-status.test.ts
  • packages/unraid-shared/src/util/data.ts
  • api/src/unraid-api/graph/resolvers/array/parity.service.ts
  • api/src/unraid-api/graph/resolvers/array/parity.model.ts
  • api/src/unraid-api/graph/resolvers/array/array.model.ts
  • api/src/unraid-api/graph/resolvers/array/array.service.spec.ts
  • api/src/core/types/states/var.ts
  • api/src/core/modules/array/get-array-data.ts
api/**/*.{test,spec}.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Prefer not to mock simple dependencies in API tests

Files:

  • api/src/core/modules/array/parity-check-status.test.ts
  • api/src/unraid-api/graph/resolvers/array/array.service.spec.ts
**/*.{test,spec}.{js,ts,jsx,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{test,spec}.{js,ts,jsx,tsx}: General testing: use .rejects.toThrow() without arguments when asserting thrown errors
General testing: focus on behavior, not exact error message wording
General testing: avoid brittle tests tied to non-essential details (exact messages, log formats)
General testing: use mocks as nouns (objects), not verbs (behavioral overuse)

Files:

  • api/src/core/modules/array/parity-check-status.test.ts
  • api/src/unraid-api/graph/resolvers/array/array.service.spec.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/core/modules/array/parity-check-status.test.ts
  • api/src/unraid-api/graph/resolvers/array/array.service.spec.ts
{**/*.test.ts,**/__test__/{components,store}/**/*.ts}

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

{**/*.test.ts,**/__test__/{components,store}/**/*.ts}: Use .rejects.toThrow() without arguments when asserting that async functions throw; avoid checking exact error message strings unless the message format is explicitly under test
Focus tests on observable behavior and outcomes, not implementation details such as exact error messages
Use await nextTick() for DOM update assertions and flushPromises() for complex async chains; always await async operations before asserting
Place module mock declarations (vi.mock) at the top level of the test file to avoid hoisting issues
Use factory functions in vi.mock calls to define mocks and avoid hoisting pitfalls
Use vi.spyOn() to specify return values or behavior of methods under test
Reset/clear mocks between tests using vi.clearAllMocks() (and vi.resetAllMocks() when appropriate) to ensure isolation
Do not rely on Nuxt auto-imports in tests; import required Vue utilities explicitly in test files
Remember that vi.mock calls are hoisted; avoid mixing mock declarations and module mocks incorrectly

Files:

  • api/src/core/modules/array/parity-check-status.test.ts
api/src/unraid-api/**

📄 CodeRabbit inference engine (CLAUDE.md)

Place new API source files in api/src/unraid-api/ rather than legacy locations

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

Files:

  • api/src/unraid-api/graph/resolvers/array/parity.service.ts
  • api/src/unraid-api/graph/resolvers/array/parity.model.ts
  • api/src/unraid-api/graph/resolvers/array/array.model.ts
  • api/src/unraid-api/graph/resolvers/array/array.service.spec.ts
🧠 Learnings (2)
📚 Learning: 2024-11-06T20:59:25.809Z
Learnt from: mdatelle
PR: unraid/api#942
File: api/src/unraid-api/graph/resolvers/auth/auth.resolver.ts:111-113
Timestamp: 2024-11-06T20:59:25.809Z
Learning: In the Unraid API project, error handling for mutations is handled at the service level rather than in the GraphQL resolvers. Specifically, in `api/src/unraid-api/graph/resolvers/auth/auth.resolver.ts`, methods like `removeRoleFromApiKey` rely on service-level error handling.

Applied to files:

  • api/src/unraid-api/graph/resolvers/array/parity.service.ts
📚 Learning: 2024-11-05T14:49:07.308Z
Learnt from: elibosley
PR: unraid/api#942
File: api/src/unraid-api/auth/api-key.service.ts:62-70
Timestamp: 2024-11-05T14:49:07.308Z
Learning: In `api/src/unraid-api/auth/api-key.service.ts`, when handling read errors in the `findById` method, throw a `GraphQLError` instead of an `InternalServerErrorException`.

Applied to files:

  • api/src/unraid-api/graph/resolvers/array/parity.service.ts
🔇 Additional comments (11)
packages/unraid-shared/src/util/data.ts (1)

44-51: LGTM: readability improvements without behavior change

The getNestedValue formatting cleanup retains the original semantics and reads better.

api/src/unraid-api/graph/resolvers/array/array.service.spec.ts (2)

9-9: LGTM: correct ESM import path

Using the .js extension follows our ESM guideline for TS source.


86-86: Good: mock includes parityCheckStatus to satisfy non-null GraphQL field

This keeps the test data aligned with the updated schema and model.

api/src/unraid-api/graph/resolvers/array/array.model.ts (2)

8-9: LGTM: ESM import path for enum

Importing ParityCheckStatus with a .js specifier complies with our TS/ESM rule.


147-149: LGTM: new parityCheckStatus field on UnraidArray

Non-null GraphQL enum is appropriate here. Ensure get-array-data always resolves a value (the core helper’s default to NEVER_RUN should cover this).

api/src/core/modules/array/get-array-data.ts (2)

4-4: ESM import looks correct.

Good use of .js extension per our ESM guideline for TS sources.


65-66: Surface parityCheckStatus on UnraidArray — LGTM.

Field is computed from emhttp.var and returned with the rest of the array payload. Preconditions already ensure var is loaded, so this won’t throw at runtime.

api/generated-schema.graphql (2)

159-161: Schema surface addition matches PR intent.

Adding parityCheckStatus: ParityCheckStatus! to UnraidArray aligns with the objectives. Non-null is appropriate given we always compute a value.

Please confirm that all code paths resolving UnraidArray (queries and subscriptions) populate parityCheckStatus to avoid non-null violations. The tests mention mocks updated in array.service.spec.ts; ensure all mocks include this field.


183-190: ParityCheckStatus enum registration — double-check enum wiring.

The GraphQL enum uses UPPER_CASE values while the TS enum uses lower-case string values (e.g., 'never_run'). This is fine as long as registerEnumType(ParityCheckStatus, { name: 'ParityCheckStatus' }) is used so GraphQL values map to the TS enum string values.

If not already present, ensure api/src/unraid-api/graph/resolvers/array/parity.model.ts registers the enum and that resolvers return ParityCheckStatus members (not raw strings).

api/src/core/modules/array/parity-check-status.ts (1)

23-39: Clarify fallback semantics (NEVER_RUN) when a prior start timestamp exists but no completion/exit codes.

Current fallback returns NEVER_RUN even if sbSynced > 0, sbSynced2 === 0, and sbSyncExitNumber === 0 (i.e., “started sometime in the past, not running now, and no exit code”). That state may not literally mean “never run.”

  • Is this state representable with real emhttp.var data, and if so, should it be exposed as NEVER_RUN or is PAUSED/FAILED more accurate?
  • If NEVER_RUN is the intended UX, consider documenting this explicitly in the function’s JSDoc and enum description to avoid confusion.

I can adjust logic and tests if product semantics dictate a different outcome.

api/src/core/types/states/var.ts (1)

89-91: mdResyncPos is already normalized at the ingestion boundary; no changes needed

A review of api/src/store/state-parsers/var.ts confirms that the raw iniFile.mdResyncPos (string) is passed through toNumber when building the Var object (see line 237). Since Var.mdResyncPos is thus always a number by the time it reaches core logic (e.g. getParityCheckStatus), downstream comparisons like > 0 are safe.
– No additional coercion needed in the loader.
– Core functions and tests already assume a numeric mdResyncPos, and all pass.

Copy link
Member

@elibosley elibosley left a comment

Choose a reason for hiding this comment

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

One comment / piece of feedback that seems like we should adjust the behavior of this.

@pujitm pujitm requested a review from elibosley August 21, 2025 21:08
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: 4

🧹 Nitpick comments (5)
api/src/core/modules/array/parity-check-status.ts (3)

15-20: Guard speed calculation against negatives and non-finite values

Handle negative/infinite inputs defensively and keep speed non-negative.

 function calculateParitySpeed(deltaTime: number, deltaBlocks: number) {
-    if (deltaTime === 0 || deltaBlocks === 0) return 0;
+    if (deltaTime <= 0 || deltaBlocks <= 0) return 0;
     const deltaBytes = deltaBlocks * 1024;
-    const speedMBps = deltaBytes / deltaTime / 1024 / 1024;
-    return Math.round(speedMBps);
+    const speedMBps = deltaBytes / deltaTime / 1024 / 1024;
+    if (!Number.isFinite(speedMBps) || speedMBps < 0) return 0;
+    return Math.round(speedMBps);
 }

43-58: Minor tidy-up: compute status once and reuse it; improves readability

Compute status once before building the object.

-export function getParityCheckStatus(varData: Var): ParityCheck {
+export function getParityCheckStatus(varData: Var): ParityCheck {
     const { sbSynced, sbSynced2, mdResyncDt, mdResyncDb, mdResyncPos, mdResyncSize } = varData;
     const deltaTime = toNumberAlways(mdResyncDt, 0);
     const deltaBlocks = toNumberAlways(mdResyncDb, 0);
 
     // seconds since epoch (unix timestamp)
     const now = sbSynced2 > 0 ? sbSynced2 : Date.now() / 1000;
+    const status = getStatusFromVarData(varData);
     return {
-        status: getStatusFromVarData(varData),
+        status,
         speed: String(calculateParitySpeed(deltaTime, deltaBlocks)),
         // percentage as integer, clamped to [0, 100]
         progress:
             mdResyncSize > 0
                 ? Math.round(
                       Math.min(100, Math.max(0, (mdResyncPos / mdResyncSize) * 100))
                   )
                 : 0,
-        date: sbSynced > 0 ? new Date(sbSynced * 1000) : undefined,
-        duration: Math.round(now - sbSynced),
+        date: sbSynced > 0 ? new Date(sbSynced * 1000) : undefined,
+        duration: sbSynced > 0 ? Math.round(now - sbSynced) : undefined,
     };
 }

3-5: Layering: core module imports a GraphQL model type — consider decoupling

Even though it’s a type-only import, core depending on @app/unraid-api/graph/... ties layers together and risks circular references in refactors. Prefer returning a core-level plain TypeScript type (e.g., ParityCheckSnapshot) and mapping it to the GraphQL model at the API layer.

If you’d like, I can draft a minimal core type and an adapter in unraid-api to keep boundaries clean.

api/src/core/modules/array/parity-check-status.test.ts (2)

424-433: Fix test title to match the expectation (Infinity -> RUNNING)

The description says “PAUSED” but the assertion is RUNNING.

-it('should return PAUSED when mdResyncDt is Infinity string', () => {
+it('should return RUNNING when mdResyncDt is Infinity string', () => {

1-681: Optional: add assertions for progress rounding/clamping and undefined date/duration for NEVER_RUN

Given the schema uses Int for progress and date/duration are nullable, it’s worth asserting these behaviors explicitly.

Proposed additions:

it('returns integer progress clamped to [0,100]', () => {
  const varData = createMockVarData({
    mdResyncPos: 150,
    mdResyncSize: 100, // 150%
    mdResyncDt: '10',
  });
  const { progress } = getParityCheckStatus(varData);
  expect(Number.isInteger(progress)).toBe(true);
  expect(progress).toBe(100);
});

it('leaves date and duration undefined when NEVER_RUN', () => {
  const varData = createMockVarData({
    sbSynced: 0,
    sbSynced2: 0,
    mdResyncPos: 0,
    mdResyncDt: '0',
  });
  const { status, date, duration } = getParityCheckStatus(varData);
  expect(status).toBe(ParityCheckStatus.NEVER_RUN);
  expect(date).toBeUndefined();
  expect(duration).toBeUndefined();
});

I can open a follow-up PR to add these tests after the producer changes land.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between b37935b and aad9abd.

📒 Files selected for processing (6)
  • api/src/core/modules/array/parity-check-status.test.ts (1 hunks)
  • api/src/core/modules/array/parity-check-status.ts (1 hunks)
  • api/src/unraid-api/graph/resolvers/array/array.model.ts (2 hunks)
  • api/src/unraid-api/graph/resolvers/array/array.service.spec.ts (2 hunks)
  • api/src/unraid-api/graph/resolvers/array/parity.model.ts (2 hunks)
  • api/src/unraid-api/graph/resolvers/array/parity.service.ts (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • api/src/unraid-api/graph/resolvers/array/array.model.ts
🧰 Additional context used
📓 Path-based instructions (7)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

TypeScript source files must use import specifiers with .js extensions for ESM compatibility

Files:

  • api/src/unraid-api/graph/resolvers/array/array.service.spec.ts
  • api/src/core/modules/array/parity-check-status.test.ts
  • api/src/core/modules/array/parity-check-status.ts
  • api/src/unraid-api/graph/resolvers/array/parity.service.ts
  • api/src/unraid-api/graph/resolvers/array/parity.model.ts
api/src/unraid-api/**

📄 CodeRabbit inference engine (CLAUDE.md)

Place new API source files in api/src/unraid-api/ rather than legacy locations

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

Files:

  • api/src/unraid-api/graph/resolvers/array/array.service.spec.ts
  • api/src/unraid-api/graph/resolvers/array/parity.service.ts
  • api/src/unraid-api/graph/resolvers/array/parity.model.ts
api/**/*.{test,spec}.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Prefer not to mock simple dependencies in API tests

Files:

  • api/src/unraid-api/graph/resolvers/array/array.service.spec.ts
  • api/src/core/modules/array/parity-check-status.test.ts
**/*.{test,spec}.{js,ts,jsx,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{test,spec}.{js,ts,jsx,tsx}: General testing: use .rejects.toThrow() without arguments when asserting thrown errors
General testing: focus on behavior, not exact error message wording
General testing: avoid brittle tests tied to non-essential details (exact messages, log formats)
General testing: use mocks as nouns (objects), not verbs (behavioral overuse)

Files:

  • api/src/unraid-api/graph/resolvers/array/array.service.spec.ts
  • api/src/core/modules/array/parity-check-status.test.ts
**/*.{ts,tsx,js,jsx,vue}

📄 CodeRabbit inference engine (CLAUDE.md)

Avoid unnecessary or obvious comments; only add comments when needed for clarity

Files:

  • api/src/unraid-api/graph/resolvers/array/array.service.spec.ts
  • api/src/core/modules/array/parity-check-status.test.ts
  • api/src/core/modules/array/parity-check-status.ts
  • api/src/unraid-api/graph/resolvers/array/parity.service.ts
  • api/src/unraid-api/graph/resolvers/array/parity.model.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/array/array.service.spec.ts
  • api/src/core/modules/array/parity-check-status.test.ts
{**/*.test.ts,**/__test__/{components,store}/**/*.ts}

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

{**/*.test.ts,**/__test__/{components,store}/**/*.ts}: Use .rejects.toThrow() without arguments when asserting that async functions throw; avoid checking exact error message strings unless the message format is explicitly under test
Focus tests on observable behavior and outcomes, not implementation details such as exact error messages
Use await nextTick() for DOM update assertions and flushPromises() for complex async chains; always await async operations before asserting
Place module mock declarations (vi.mock) at the top level of the test file to avoid hoisting issues
Use factory functions in vi.mock calls to define mocks and avoid hoisting pitfalls
Use vi.spyOn() to specify return values or behavior of methods under test
Reset/clear mocks between tests using vi.clearAllMocks() (and vi.resetAllMocks() when appropriate) to ensure isolation
Do not rely on Nuxt auto-imports in tests; import required Vue utilities explicitly in test files
Remember that vi.mock calls are hoisted; avoid mixing mock declarations and module mocks incorrectly

Files:

  • api/src/core/modules/array/parity-check-status.test.ts
🧬 Code graph analysis (1)
api/src/unraid-api/graph/resolvers/array/parity.service.ts (1)
packages/unraid-shared/src/util/data.ts (1)
  • toNumberAlways (60-63)
🔇 Additional comments (5)
api/src/unraid-api/graph/resolvers/array/parity.service.ts (2)

4-4: LGTM on ESM import specifier

Uses .js extension per repo guidelines; import path aligns with shared util placement.


7-7: Enum import is correct

Importing the enum from core keeps history mapping consistent with live status computation.

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

86-92: LGTM: parityCheckStatus shape matches the new GraphQL/enum contract

Test data mirrors the new enum and field schema. Keeping date undefined is appropriate for NEVER_RUN.

api/src/unraid-api/graph/resolvers/array/parity.model.ts (2)

1-7: Enum registration looks good

registerEnumType called once with a stable name. Make sure this module isn’t imported multiple times in a hot-reload context during tests to avoid “type already exists” noise, but with Vitest + Nest this is typically fine.

If you’ve seen duplicate-type warnings previously, we can centralize enum registrations in a single bootstrap file.


20-21: Ensure ParityCheck.progress is an integer per GraphQL Int

• In api/src/unraid-api/graph/resolvers/array/parity-check-status.ts, confirm that getParityCheckStatus now:
– Rounds the raw percentage to the nearest whole number
– Clamps the result between 0 and 100
– Returns a JavaScript number without fractional part for the progress field

• The GraphQL model in api/src/unraid-api/graph/resolvers/array/parity.model.ts should still declare @Field(() => Int) for progress. No change to the schema is needed.

• Add or update a unit test in your array resolvers (e.g. in parity-check-status.spec.ts) to verify:
– An input that would yield a fractional progress (e.g. 12.7) returns 13
– Negative or >100 inputs are clamped to 0 and 100 respectively

• Manually exercise the GraphQL sandbox (e.g. run a query like
{ array { status { progress } } }) and confirm the returned progress value is an integer.

Please verify these changes and ensure that all existing clients relying on the Int type continue to work as expected.

@elibosley elibosley linked an issue Aug 22, 2025 that may be closed by this pull request
@github-actions
Copy link
Contributor

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/PR1611/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/array/parity.service.ts (1)

65-87: Disallow “start” when a parity check is paused

The resolver currently only treats mdResync ≠ 0 as “running”, but a paused check has mdResync == 0 and mdResyncPos > 0 — so “start” remains allowed while paused.

• File: api/src/unraid-api/graph/resolvers/array/parity.service.ts
Lines: ~65–87

• Change the running flag to include paused checks:

-       const running = getters.emhttp().var.mdResync !== 0;
+       // Treat both actively running and paused parity checks as “busy”
+       const { mdResync, mdResyncPos } = getters.emhttp().var;
+       const running = mdResync !== 0 || mdResyncPos > 0;
@@
-       if (running) {
+       if (running) {
            // Remove 'start' when any check is in progress or paused
            allowedStates = allowedStates.filter((state) => state !== 'start');
        }

This ensures that “start” is only offered when no check—paused or running—is present.

🧹 Nitpick comments (6)
api/src/unraid-api/graph/resolvers/array/parity.service.ts (2)

43-49: Simplify and harden statusCodeToStatusEnum (avoid re-coercion and NaN→COMPLETED)

  • statusCode is already numeric; reapplying toNumberAlways can convert NaN to 0 and mislabel as COMPLETED.
  • Use direct equality checks.

Apply this diff:

-    statusCodeToStatusEnum(statusCode: number): ParityCheckStatus {
-        return statusCode === -4
-            ? ParityCheckStatus.CANCELLED
-            : toNumberAlways(statusCode, 0) === 0
-              ? ParityCheckStatus.COMPLETED
-              : ParityCheckStatus.FAILED;
-    }
+    statusCodeToStatusEnum(statusCode: number): ParityCheckStatus {
+        if (statusCode === -4) return ParityCheckStatus.CANCELLED;
+        if (statusCode === 0) return ParityCheckStatus.COMPLETED;
+        return ParityCheckStatus.FAILED;
+    }

19-21: Prefer GraphQLError for user-facing resolver failures

For consistency with the rest of this resolver and cleaner client errors, wrap the “history file not found” case in GraphQLError.

Apply this diff:

-        const history = await readFile(historyFilePath).catch(() => {
-            throw new Error(`Parity history file not found: ${historyFilePath}`);
-        });
+        const history = await readFile(historyFilePath).catch(() => {
+            throw new GraphQLError(`Parity history file not found: ${historyFilePath}`);
+        });
api/src/core/modules/array/parity-check-status.ts (1)

15-20: Consider clamping negative speeds to 0 MB/s

If mdResyncDt becomes negative due to bad input, speed can be negative, which is confusing. Optional: clamp to 0 to reflect “no transfer”.

Apply this diff:

-function calculateParitySpeed(deltaTime: number, deltaBlocks: number) {
-    if (deltaTime === 0 || deltaBlocks === 0) return 0;
+function calculateParitySpeed(deltaTime: number, deltaBlocks: number) {
+    if (deltaTime <= 0 || deltaBlocks <= 0) return 0;
     const deltaBytes = deltaBlocks * 1024;
     const speedMBps = deltaBytes / deltaTime / 1024 / 1024;
     return Math.round(speedMBps);
 }
api/src/core/modules/array/parity-check-status.test.ts (3)

424-433: Fix misleading test name (expects RUNNING, title says PAUSED)

The assertion expects RUNNING for mdResyncDt = 'Infinity' (correct), but the test title says PAUSED. Rename for clarity.

Apply this diff:

-        it('should return PAUSED when mdResyncDt is Infinity string', () => {
+        it('should return RUNNING when mdResyncDt is "Infinity" string', () => {

6-46: Reduce maintenance burden of Var-heavy test fixtures

You only need a subset of Var for getParityCheckStatus. Consider deriving the param type and mocking only those fields to keep tests future-proof.

Example change:

-const createMockVarData = (overrides: Partial<Var> = {}): Var =>
-    ({
-        mdResyncPos: 0,
-        mdResyncDt: '0',
-        mdResyncDb: '0',
-        mdResyncSize: 100000,
-        sbSyncExit: '0',
-        sbSynced: 0,
-        sbSynced2: 0,
-        // many unrelated defaults...
-        ...overrides,
-    }) as Var;
+type Input = Parameters<typeof getParityCheckStatus>[0];
+const createMockVarData = (overrides: Partial<Input> = {}): Input => ({
+    mdResyncPos: 0,
+    mdResyncDt: '0',
+    mdResyncDb: '0',
+    mdResyncSize: 100000,
+    sbSyncExit: '0',
+    sbSynced: 0,
+    sbSynced2: 0,
+    ...overrides,
+});

681-799: Speed tests are thorough; consider aligning with any “no negative speed” decision

If you adopt clamping in calculateParitySpeed, update the negative-deltaTime test to expect '0'. Otherwise, the current expectation of '-1' is fine and demonstrates the behavior explicitly.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between aad9abd and 3839bb2.

📒 Files selected for processing (4)
  • api/generated-schema.graphql (2 hunks)
  • api/src/core/modules/array/parity-check-status.test.ts (1 hunks)
  • api/src/core/modules/array/parity-check-status.ts (1 hunks)
  • api/src/unraid-api/graph/resolvers/array/parity.service.ts (2 hunks)
🧰 Additional context used
📓 Path-based instructions (7)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

TypeScript source files must use import specifiers with .js extensions for ESM compatibility

Files:

  • api/src/core/modules/array/parity-check-status.test.ts
  • api/src/unraid-api/graph/resolvers/array/parity.service.ts
  • api/src/core/modules/array/parity-check-status.ts
api/**/*.{test,spec}.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Prefer not to mock simple dependencies in API tests

Files:

  • api/src/core/modules/array/parity-check-status.test.ts
**/*.{test,spec}.{js,ts,jsx,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{test,spec}.{js,ts,jsx,tsx}: General testing: use .rejects.toThrow() without arguments when asserting thrown errors
General testing: focus on behavior, not exact error message wording
General testing: avoid brittle tests tied to non-essential details (exact messages, log formats)
General testing: use mocks as nouns (objects), not verbs (behavioral overuse)

Files:

  • api/src/core/modules/array/parity-check-status.test.ts
**/*.{ts,tsx,js,jsx,vue}

📄 CodeRabbit inference engine (CLAUDE.md)

Avoid unnecessary or obvious comments; only add comments when needed for clarity

Files:

  • api/src/core/modules/array/parity-check-status.test.ts
  • api/src/unraid-api/graph/resolvers/array/parity.service.ts
  • api/src/core/modules/array/parity-check-status.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/core/modules/array/parity-check-status.test.ts
{**/*.test.ts,**/__test__/{components,store}/**/*.ts}

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

{**/*.test.ts,**/__test__/{components,store}/**/*.ts}: Use .rejects.toThrow() without arguments when asserting that async functions throw; avoid checking exact error message strings unless the message format is explicitly under test
Focus tests on observable behavior and outcomes, not implementation details such as exact error messages
Use await nextTick() for DOM update assertions and flushPromises() for complex async chains; always await async operations before asserting
Place module mock declarations (vi.mock) at the top level of the test file to avoid hoisting issues
Use factory functions in vi.mock calls to define mocks and avoid hoisting pitfalls
Use vi.spyOn() to specify return values or behavior of methods under test
Reset/clear mocks between tests using vi.clearAllMocks() (and vi.resetAllMocks() when appropriate) to ensure isolation
Do not rely on Nuxt auto-imports in tests; import required Vue utilities explicitly in test files
Remember that vi.mock calls are hoisted; avoid mixing mock declarations and module mocks incorrectly

Files:

  • api/src/core/modules/array/parity-check-status.test.ts
api/src/unraid-api/**

📄 CodeRabbit inference engine (CLAUDE.md)

Place new API source files in api/src/unraid-api/ rather than legacy locations

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

Files:

  • api/src/unraid-api/graph/resolvers/array/parity.service.ts
🧬 Code graph analysis (3)
api/src/core/modules/array/parity-check-status.test.ts (2)
api/src/core/types/states/var.ts (1)
  • Var (12-242)
api/src/core/modules/array/parity-check-status.ts (1)
  • getParityCheckStatus (54-72)
api/src/unraid-api/graph/resolvers/array/parity.service.ts (1)
packages/unraid-shared/src/util/data.ts (1)
  • toNumberAlways (60-63)
api/src/core/modules/array/parity-check-status.ts (2)
api/src/core/types/states/var.ts (1)
  • Var (12-242)
packages/unraid-shared/src/util/data.ts (1)
  • toNumberAlways (60-63)
🔇 Additional comments (7)
api/src/unraid-api/graph/resolvers/array/parity.service.ts (1)

4-4: Good ESM hygiene on TS imports

The .js extensions ensure ESM compatibility per repo guidelines. No action needed.

Also applies to: 7-7

api/generated-schema.graphql (3)

17-44: ParityCheck type expansion aligns with runtime model

Fields and nullability look consistent with the resolver surface (nullable date/duration/speed/errors, non-null enum status). LGTM.


202-204: New array.parityCheckStatus field

Contract addition looks good and non-null return ensures clients always get a shape. Make sure the resolver always returns an object, even on “never run” (date/duration may be null). No change requested.


51-58: Confirmed enum registration
I’ve verified that ParityCheckStatus is registered with Nest’s registerEnumType in api/src/unraid-api/graph/resolvers/array/parity.model.ts at line 5. The GraphQL enum members (NEVER_RUN…FAILED) correctly match the TypeScript enum keys. LGTM.

• Registration located at: api/src/unraid-api/graph/resolvers/array/parity.model.ts:5

api/src/core/modules/array/parity-check-status.ts (3)

6-13: Good enum shape for GraphQL mapping

String-valued TS enum with uppercase keys will map cleanly to GraphQL enum names. Nice.


33-52: Status precedence and parsing look solid

Active/paused checks take precedence; NEVER_RUN guards sbSynced == 0; cancelled overrides failed; completed comes after failures. This matches expected behavior and tests. Nice work.


59-71: Derived fields are sensible and null-safe

  • date/duration only set when sbSynced > 0
  • progress clamped 0–100
  • speed derived from deltas

All align with schema nullability and avoid serialization pitfalls.

@pujitm pujitm merged commit c508366 into main Aug 25, 2025
16 checks passed
@pujitm pujitm deleted the feat/parity-check-status branch August 25, 2025 17:22
elibosley pushed a commit that referenced this pull request Aug 27, 2025
🤖 I have created a release *beep* *boop*
---


## [4.16.0](v4.15.1...v4.16.0)
(2025-08-27)


### Features

* add `parityCheckStatus` field to `array` query
([#1611](#1611))
([c508366](c508366))
* generated UI API key management + OAuth-like API Key Flows
([#1609](#1609))
([674323f](674323f))


### Bug Fixes

* **connect:** clear `wanport` upon disabling remote access
([#1624](#1624))
([9df6a3f](9df6a3f))
* **connect:** valid LAN FQDN while remote access is enabled
([#1625](#1625))
([aa58888](aa58888))
* correctly parse periods in share names from ini file
([#1629](#1629))
([7d67a40](7d67a40))
* **rc.unraid-api:** remove profile sourcing
([#1622](#1622))
([6947b5d](6947b5d))
* remove unused api key calls
([#1628](#1628))
([9cd0d6a](9cd0d6a))
* retry VMs init for up to 2 min
([#1612](#1612))
([b2e7801](b2e7801))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
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.

Query "parityCheck"

2 participants