Skip to content

feat: preempt_v2#429

Open
NamelessOIer wants to merge 2 commits intomasterfrom
dev/preempt_v2
Open

feat: preempt_v2#429
NamelessOIer wants to merge 2 commits intomasterfrom
dev/preempt_v2

Conversation

@NamelessOIer
Copy link
Copy Markdown
Collaborator

@NamelessOIer NamelessOIer commented Apr 27, 2026

Summary by CodeRabbit

  • New Features
    • Added QoS preemption support: specify which jobs may be preempted and choose preemption mode (OFF/CANCEL).
    • CLI: add/modify QoS commands accept preemption parameters; empty preempt value clears the list.
    • Output & help: QoS displays and help text now show Preempt and PreemptMode fields.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 27, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 45b59b21-6504-48b2-a7f8-fbccc467880f

📥 Commits

Reviewing files that changed from the base of the PR and between fbabee3 and f7dd64d.

📒 Files selected for processing (6)
  • internal/cacctmgr/cacctmgr.go
  • internal/cacctmgr/cmd.go
  • internal/cacctmgr/help.go
  • internal/cacctmgr/output.go
  • internal/util/string.go
  • protos/PublicDefs.proto
✅ Files skipped from review due to trivial changes (1)
  • internal/cacctmgr/cmd.go
🚧 Files skipped from review as they are similar to previous changes (2)
  • protos/PublicDefs.proto
  • internal/cacctmgr/output.go

📝 Walkthrough

Walkthrough

Adds QoS preemption: new protobuf enums/fields, CLI flags for preempt and preemptmode, parsing that accepts empty comma lists to clear preempt entries, output formatting for preempt fields, and a utility to parse comma-separated lists allowing empty input.

Changes

Cohort / File(s) Summary
Schema & Protocol
protos/PublicDefs.proto
Added PreemptType and PreemptMode enums; extended ModifyField with Preempt and ModifyPreemptMode; added repeated string preempt and PreemptMode preempt_mode to QosInfo.
Command Handling & Logic
internal/cacctmgr/cacctmgr.go, internal/cacctmgr/cmd.go
ModifyQos special-cases ModifyField_Preempt to parse comma-separated NewValue into ValueList (allowing empty to clear); added parsePreemptMode and wiring for preempt / preemptmode flags in CLI handlers.
Output & Help Text
internal/cacctmgr/output.go, internal/cacctmgr/help.go
Added Preempt and PreemptMode columns and format keys; implemented formatPreemptMode; updated CLI help to document Preempt and PreemptMode usage and examples.
Utilities
internal/util/string.go
Added ParseStringParamListAllowEmpty(parameters, splitStr) to treat empty/whitespace input as nil and otherwise parse using existing splitting logic.

Sequence Diagram(s)

(omitted)

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • huerni
  • Nativu5

Poem

🐇 In burrows of code I softly creep,
I split the lists so none will weep,
Empty strings now clear the way,
OFF or CANCEL — choose your sway,
Hooray for QoS, a rabbit's leap!

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 15.38% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'feat: preempt_v2' is vague and uses a non-descriptive version identifier ('v2') that doesn't convey meaningful information about what preemption feature is being added or modified. Consider updating the title to be more descriptive, such as 'feat: add preemption QoS attributes and configuration' or 'feat: implement preempt and preemptmode QoS fields' to clarify the actual changes.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch dev/preempt_v2

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (3)
internal/cacctmgr/output.go (1)

911-927: formatPreemptMode default returning "OFF" can hide unknown values.

Falling back to a real, valid mode name for unknown enum values silently masks any future additions to PreemptMode (or values from a newer backend). A surfaced sentinel is safer for diagnostics:

🔍 Suggested fallback
 	default:
-		return "OFF"
+		return fmt.Sprintf("UNKNOWN(%d)", int32(m))
 	}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/cacctmgr/output.go` around lines 911 - 927, formatPreemptMode
currently returns "OFF" for unknown protos.PreemptMode values which can silently
hide mismatches; change it to return a clear sentinel string containing the
unknown numeric value (e.g., "UNKNOWN_PREEMPT_MODE(<numeric>)" or
"UNKNOWN:<numeric>") so diagnostics show unexpected enum values; update
formatPreemptMode to detect the default case and format the sentinel using the
numeric value of m (from protos.PreemptMode) instead of returning "OFF".
internal/cacctmgr/cmd.go (2)

1235-1245: Avoid parsing the preempt list twice.

Here you call ParseStringParamListAllowEmpty purely for validation, then pass the raw value string into NewValue; ModifyQos in cacctmgr.go parses it again. The validation round-trip is harmless but redundant — and the two parses must stay in agreement forever. Either:

  • drop the local parse and rely on ModifyQos to surface the error (it already does, with a similar message), or
  • thread the parsed slice through ModifyParam (e.g., add a ValueList []string field) so the wire path is single-source.
♻️ Lightest cleanup (option 1)
 		case "preempt":
-			// Validate the list format early. ModifyQos will split NewValue
-			// again so the backend receives the actual list. Empty value
-			// means "clear the preempt set" and is accepted.
-			if _, err := util.ParseStringParamListAllowEmpty(value, ","); err != nil {
-				return util.NewCraneErr(util.ErrorCmdArg, fmt.Sprintf("invalid preempt list %q: %v\n", value, err))
-			}
+			// Empty value means "clear the preempt set" and is accepted;
+			// ModifyQos validates and splits the list before sending.
 			params = append(params, ModifyParam{
 				ModifyField: protos.ModifyField_Preempt,
 				NewValue:    value,
 			})
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/cacctmgr/cmd.go` around lines 1235 - 1245, Remove the redundant
local parse: drop the call to util.ParseStringParamListAllowEmpty in the
"preempt" case and stop validating twice; simply append ModifyParam with
ModifyField: protos.ModifyField_Preempt and NewValue: value (leave
ModifyParam.NewValue as the raw string) and let ModifyQos in cacctmgr.go perform
parsing/validation. Update any comment to note that ModifyQos is the single
source of truth for parsing the preempt list and remove that unused
import/variable if it becomes unused.

131-141: Consider more defensive error handling in parsePreemptMode for clarity and maintainability.

Proto declares 4 PreemptMode values (OFF, CANCEL, REQUEUE, SUSPEND), but this parser only accepts OFF and CANCEL—the TODO comment correctly acknowledges this is intentional until the scheduler supports the others. Two minor points:

  1. Error message maintenance: The error lists "valid values are OFF, CANCEL" as a hard-coded string. If the backend ever gains support for REQUEUE/SUSPEND ahead of the frontend, this message will become stale. Either keep it in sync manually or consider sourcing the allowed set from a shared constant.

  2. Error return value: On the error path, the function returns PREEMPT_MODE_OFF (a valid enum value) alongside the error. While both current call sites correctly check err and ignore the enum, returning the zero value on error is a safer defensive pattern—returning a meaningful value alongside an error can mislead callers who skip error checks.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/cacctmgr/cmd.go` around lines 131 - 141, Update parsePreemptMode to
be more defensive: when returning an error, return the enum zero/unspecified
value instead of PREEMPT_MODE_OFF (use protos.PreemptMode(0) or the generated
UNSPECIFIED value) and build the error message from a single source of truth
(e.g., a local constant or slice of allowed strings defined near
parsePreemptMode) rather than a hard-coded literal; keep the switch accepting
only "OFF" and "CANCEL" for now but derive the "valid values" text from that
constant so it stays in sync with the accepted cases in parsePreemptMode.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@internal/cacctmgr/help.go`:
- Around line 197-198: The help claims "Self-reference is rejected" for the
Preempt field but neither executeAddQosCommand nor executeModifyQosCommand
enforce it (ParseStringParamListAllowEmpty only checks emptiness); add a
validation step in both executeAddQosCommand and executeModifyQosCommand that
iterates the parsed Preempt list and returns an error if any entry equals the
QoS name being added/modified (use the local qos name variable used in those
functions), or alternatively update the help text to remove the self-reference
claim if backend does not enforce it; ensure the error message clearly
references the Preempt field and the offending name.

In `@protos/PublicDefs.proto`:
- Around line 915-919: The PreemptType enum is unused and should be removed or
documented: locate the enum declaration named PreemptType and either delete it
from PublicDefs.proto (then regenerate protos/code via protoc and remove any
stray references) or replace it with a clear comment explaining it is
intentionally reserved for the backend/C++ if that is required; also verify
related types (e.g., QosInfo which uses PreemptMode) remain correct and update
any proto consumers after regeneration.

---

Nitpick comments:
In `@internal/cacctmgr/cmd.go`:
- Around line 1235-1245: Remove the redundant local parse: drop the call to
util.ParseStringParamListAllowEmpty in the "preempt" case and stop validating
twice; simply append ModifyParam with ModifyField: protos.ModifyField_Preempt
and NewValue: value (leave ModifyParam.NewValue as the raw string) and let
ModifyQos in cacctmgr.go perform parsing/validation. Update any comment to note
that ModifyQos is the single source of truth for parsing the preempt list and
remove that unused import/variable if it becomes unused.
- Around line 131-141: Update parsePreemptMode to be more defensive: when
returning an error, return the enum zero/unspecified value instead of
PREEMPT_MODE_OFF (use protos.PreemptMode(0) or the generated UNSPECIFIED value)
and build the error message from a single source of truth (e.g., a local
constant or slice of allowed strings defined near parsePreemptMode) rather than
a hard-coded literal; keep the switch accepting only "OFF" and "CANCEL" for now
but derive the "valid values" text from that constant so it stays in sync with
the accepted cases in parsePreemptMode.

In `@internal/cacctmgr/output.go`:
- Around line 911-927: formatPreemptMode currently returns "OFF" for unknown
protos.PreemptMode values which can silently hide mismatches; change it to
return a clear sentinel string containing the unknown numeric value (e.g.,
"UNKNOWN_PREEMPT_MODE(<numeric>)" or "UNKNOWN:<numeric>") so diagnostics show
unexpected enum values; update formatPreemptMode to detect the default case and
format the sentinel using the numeric value of m (from protos.PreemptMode)
instead of returning "OFF".
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 26a6d1be-c255-42a1-8d6e-ecbd1629e8d8

📥 Commits

Reviewing files that changed from the base of the PR and between 429cf0b and fbabee3.

📒 Files selected for processing (6)
  • internal/cacctmgr/cacctmgr.go
  • internal/cacctmgr/cmd.go
  • internal/cacctmgr/help.go
  • internal/cacctmgr/output.go
  • internal/util/string.go
  • protos/PublicDefs.proto

Comment thread internal/cacctmgr/help.go
Comment on lines +197 to +198
Preempt=<qos1,qos2,...> Comma-separated QoS names this QoS may preempt. Self-reference is rejected.
PreemptMode=<mode> Preemption handling (OFF, CANCEL). Default OFF. REQUEUE/SUSPEND are reserved for future versions.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Search for any frontend self-reference check tied to the preempt list.
rg -nP '(?i)\bpreempt\b.*\b(self|same.?name|name\s*==)' -C3

Repository: PKUHPC/CraneSched-FrontEnd

Length of output: 777


🏁 Script executed:

fd -t f '\.go$' | xargs rg -l 'executeAddQosCommand|executeModifyQosCommand'

Repository: PKUHPC/CraneSched-FrontEnd

Length of output: 95


🏁 Script executed:

rg -n 'func.*executeAddQosCommand|func.*executeModifyQosCommand' -A 30

Repository: PKUHPC/CraneSched-FrontEnd

Length of output: 3932


🏁 Script executed:

rg -n 'Preempt' internal/cacctmgr/ --type go -B 2 -A 2

Repository: PKUHPC/CraneSched-FrontEnd

Length of output: 9335


🏁 Script executed:

rg -n 'ParseStringParamList' internal/cacctmgr/ -B 2 -A 2

Repository: PKUHPC/CraneSched-FrontEnd

Length of output: 7245


🏁 Script executed:

fd -t f -name '*.go' | xargs rg -l 'func ParseStringParamList'

Repository: PKUHPC/CraneSched-FrontEnd

Length of output: 343


🏁 Script executed:

cat -n internal/util/string.go | head -100

Repository: PKUHPC/CraneSched-FrontEnd

Length of output: 3805


🏁 Script executed:

rg -n 'func ParseStringParamList' internal/util/string.go -A 20

Repository: PKUHPC/CraneSched-FrontEnd

Length of output: 1349


Frontend does not validate self-reference rejection for Preempt field, but help advertises it.

The help text at line 197 claims Self-reference is rejected., but neither executeAddQosCommand nor executeModifyQosCommand compare the supplied preempt names against the QoS name being added/modified. ParseStringParamListAllowEmpty only validates that values are non-empty; it performs no self-reference checking. If the backend enforces this constraint, the help is misleading about the validation boundary. If the backend does not enforce it, the help is simply incorrect.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/cacctmgr/help.go` around lines 197 - 198, The help claims
"Self-reference is rejected" for the Preempt field but neither
executeAddQosCommand nor executeModifyQosCommand enforce it
(ParseStringParamListAllowEmpty only checks emptiness); add a validation step in
both executeAddQosCommand and executeModifyQosCommand that iterates the parsed
Preempt list and returns an error if any entry equals the QoS name being
added/modified (use the local qos name variable used in those functions), or
alternatively update the help text to remove the self-reference claim if backend
does not enforce it; ensure the error message clearly references the Preempt
field and the offending name.

Comment thread protos/PublicDefs.proto
Comment on lines +915 to +919
enum PreemptType {
PREEMPT_NONE = 0;
PREEMPT_QOS = 1;
PREEMPT_PARTITION = 2;
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check for any usage of PreemptType across the repo (this PR is FrontEnd-only,
# but the proto is shared, so the enum may be referenced via the generated Go bindings).
rg -nP '\bPreemptType\b' --type=go --type=proto -C2

Repository: PKUHPC/CraneSched-FrontEnd

Length of output: 100


🏁 Script executed:

#!/bin/bash
# Search for PreemptType across the repo without using unsupported file types
rg -i '\bPreemptType\b' -C2

Repository: PKUHPC/CraneSched-FrontEnd

Length of output: 251


Remove PreemptType enum or clarify its intended use.

PreemptType is defined here (lines 915–919) but is not referenced by any message field in this proto file. Notably, QosInfo uses PreemptMode instead. A search of the codebase confirms this enum has no usage in the FrontEnd repository. If this enum is intended for the C++ backend or shared infrastructure, document that; otherwise, remove it to avoid dead code.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@protos/PublicDefs.proto` around lines 915 - 919, The PreemptType enum is
unused and should be removed or documented: locate the enum declaration named
PreemptType and either delete it from PublicDefs.proto (then regenerate
protos/code via protoc and remove any stray references) or replace it with a
clear comment explaining it is intentionally reserved for the backend/C++ if
that is required; also verify related types (e.g., QosInfo which uses
PreemptMode) remain correct and update any proto consumers after regeneration.

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