mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-24 05:06:28 +00:00
feat: add scheduler workload admission contracts (#3602)
This commit is contained in:
@@ -242,4 +242,19 @@ mod tests {
|
|||||||
assert_eq!(pipe.state(), BackpressureState::Normal);
|
assert_eq!(pipe.state(), BackpressureState::Normal);
|
||||||
assert_eq!(pipe.meta().buffer_capacity, 1024);
|
assert_eq!(pipe.meta().buffer_capacity, 1024);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_backpressure_pipe_meta_is_read_only() {
|
||||||
|
let manager = BackpressureManager::new(2048, 80, 50);
|
||||||
|
let pipe = manager.create_pipe();
|
||||||
|
let first = pipe.meta();
|
||||||
|
let second = pipe.meta();
|
||||||
|
|
||||||
|
assert_eq!(first.buffer_capacity, 2048);
|
||||||
|
assert_eq!(first.state, BackpressureState::Normal);
|
||||||
|
assert_eq!(second.buffer_capacity, first.buffer_capacity);
|
||||||
|
assert_eq!(second.state, first.state);
|
||||||
|
assert!(second.age >= first.age);
|
||||||
|
assert_eq!(manager.state(), BackpressureState::Normal);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -125,6 +125,7 @@ mod backpressure;
|
|||||||
mod scheduler;
|
mod scheduler;
|
||||||
|
|
||||||
pub mod workers;
|
pub mod workers;
|
||||||
|
pub mod workload;
|
||||||
|
|
||||||
// Public module exports with feature gates
|
// Public module exports with feature gates
|
||||||
#[cfg(feature = "timeout")]
|
#[cfg(feature = "timeout")]
|
||||||
@@ -149,6 +150,10 @@ pub use config::{ConcurrencyConfig, ConcurrencyFeatures};
|
|||||||
// Manager
|
// Manager
|
||||||
mod manager;
|
mod manager;
|
||||||
pub use manager::{ConcurrencyManager, GetObjectQueueSnapshot};
|
pub use manager::{ConcurrencyManager, GetObjectQueueSnapshot};
|
||||||
|
pub use workload::{
|
||||||
|
AdmissionState, WorkloadAdmissionRegistrySnapshot, WorkloadAdmissionSnapshot, WorkloadAdmissionSnapshotProvider,
|
||||||
|
WorkloadClass,
|
||||||
|
};
|
||||||
|
|
||||||
// Prelude for convenient imports
|
// Prelude for convenient imports
|
||||||
pub mod prelude {
|
pub mod prelude {
|
||||||
@@ -169,5 +174,5 @@ pub mod prelude {
|
|||||||
#[cfg(feature = "scheduler")]
|
#[cfg(feature = "scheduler")]
|
||||||
pub use crate::scheduler::{IoStrategy, SchedulerManager, SchedulerPolicy};
|
pub use crate::scheduler::{IoStrategy, SchedulerManager, SchedulerPolicy};
|
||||||
|
|
||||||
pub use crate::{ConcurrencyConfig, ConcurrencyFeatures, ConcurrencyManager};
|
pub use crate::{AdmissionState, ConcurrencyConfig, ConcurrencyFeatures, ConcurrencyManager, WorkloadAdmissionSnapshot};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -281,6 +281,24 @@ mod tests {
|
|||||||
assert!(snapshot.is_congested(70.0));
|
assert!(snapshot.is_congested(70.0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_queue_snapshot_clamps_over_available_permits() {
|
||||||
|
let snapshot = GetObjectQueueSnapshot::from_available_permits(64, 96);
|
||||||
|
assert_eq!(snapshot.permits_in_use, 0);
|
||||||
|
assert_eq!(snapshot.permits_available(), 64);
|
||||||
|
assert_eq!(snapshot.utilization_percent(), 0.0);
|
||||||
|
assert!(!snapshot.is_congested(0.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_queue_snapshot_handles_zero_total_permits() {
|
||||||
|
let snapshot = GetObjectQueueSnapshot::from_available_permits(0, 0);
|
||||||
|
assert_eq!(snapshot.permits_in_use, 0);
|
||||||
|
assert_eq!(snapshot.permits_available(), 0);
|
||||||
|
assert_eq!(snapshot.utilization_percent(), 0.0);
|
||||||
|
assert!(!snapshot.is_congested(0.0));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_manager_creation() {
|
fn test_manager_creation() {
|
||||||
let manager = ConcurrencyManager::with_defaults();
|
let manager = ConcurrencyManager::with_defaults();
|
||||||
|
|||||||
@@ -239,6 +239,26 @@ mod tests {
|
|||||||
assert_eq!(core.low_priority_size_threshold, policy.low_priority_threshold);
|
assert_eq!(core.low_priority_size_threshold, policy.low_priority_threshold);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_scheduler_default_thresholds_remain_stable() {
|
||||||
|
let policy = SchedulerPolicy::default();
|
||||||
|
assert_eq!(policy.base_buffer_size, 64 * 1024);
|
||||||
|
assert_eq!(policy.max_buffer_size, 4 * 1024 * 1024);
|
||||||
|
assert_eq!(policy.high_priority_threshold, 1024 * 1024);
|
||||||
|
assert_eq!(policy.low_priority_threshold, 10 * 1024 * 1024);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_scheduler_priority_boundaries_remain_stable() {
|
||||||
|
let policy = SchedulerPolicy::default();
|
||||||
|
let manager = SchedulerManager::from_policy(policy);
|
||||||
|
|
||||||
|
assert_eq!(manager.get_priority(1_048_575), IoPriority::High);
|
||||||
|
assert_eq!(manager.get_priority(1_048_576), IoPriority::Normal);
|
||||||
|
assert_eq!(manager.get_priority(10_485_760), IoPriority::Normal);
|
||||||
|
assert_eq!(manager.get_priority(10_485_761), IoPriority::Low);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_scheduler_manager() {
|
fn test_scheduler_manager() {
|
||||||
let manager = SchedulerManager::new(1024, 4096, 512, 2048);
|
let manager = SchedulerManager::new(1024, 4096, 512, 2048);
|
||||||
|
|||||||
@@ -0,0 +1,209 @@
|
|||||||
|
// Copyright 2024 RustFS Team
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
//! Runtime workload admission contract types.
|
||||||
|
|
||||||
|
/// Stable workload classes used by future runtime admission snapshots.
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
|
pub enum WorkloadClass {
|
||||||
|
/// Foreground read requests.
|
||||||
|
ForegroundRead,
|
||||||
|
/// Foreground write requests.
|
||||||
|
ForegroundWrite,
|
||||||
|
/// Metadata and namespace operations.
|
||||||
|
Metadata,
|
||||||
|
/// Background scanner work.
|
||||||
|
Scanner,
|
||||||
|
/// Repair and heal work.
|
||||||
|
Repair,
|
||||||
|
/// Replication work.
|
||||||
|
Replication,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WorkloadClass {
|
||||||
|
/// Required workload classes covered by the runtime admission contract.
|
||||||
|
pub const REQUIRED: [Self; 6] = [
|
||||||
|
Self::ForegroundRead,
|
||||||
|
Self::ForegroundWrite,
|
||||||
|
Self::Metadata,
|
||||||
|
Self::Scanner,
|
||||||
|
Self::Repair,
|
||||||
|
Self::Replication,
|
||||||
|
];
|
||||||
|
|
||||||
|
/// Return a stable label for logs, metrics, and snapshots.
|
||||||
|
pub const fn as_str(self) -> &'static str {
|
||||||
|
match self {
|
||||||
|
Self::ForegroundRead => "foreground_read",
|
||||||
|
Self::ForegroundWrite => "foreground_write",
|
||||||
|
Self::Metadata => "metadata",
|
||||||
|
Self::Scanner => "scanner",
|
||||||
|
Self::Repair => "repair",
|
||||||
|
Self::Replication => "replication",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for WorkloadClass {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
f.write_str(self.as_str())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Read-only admission state for a workload class.
|
||||||
|
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
|
pub enum AdmissionState {
|
||||||
|
/// Admission is open for this workload class.
|
||||||
|
Open,
|
||||||
|
/// Admission is currently throttled.
|
||||||
|
Throttled,
|
||||||
|
/// Admission is saturated or queue-limited.
|
||||||
|
Saturated,
|
||||||
|
/// Admission is disabled by configuration or capability.
|
||||||
|
Disabled,
|
||||||
|
/// Admission state is not currently known.
|
||||||
|
#[default]
|
||||||
|
Unknown,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AdmissionState {
|
||||||
|
/// Return whether the state allows admission without throttling.
|
||||||
|
pub const fn is_open(self) -> bool {
|
||||||
|
matches!(self, Self::Open)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Read-only admission snapshot for one workload class.
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
|
pub struct WorkloadAdmissionSnapshot {
|
||||||
|
/// Workload class described by this snapshot.
|
||||||
|
pub class: WorkloadClass,
|
||||||
|
/// Current admission state.
|
||||||
|
pub state: AdmissionState,
|
||||||
|
/// Active work count when the owner exposes it.
|
||||||
|
pub active: Option<usize>,
|
||||||
|
/// Queued work count when the owner exposes it.
|
||||||
|
pub queued: Option<usize>,
|
||||||
|
/// Admission limit when the owner exposes it.
|
||||||
|
pub limit: Option<usize>,
|
||||||
|
/// Optional state reason for disabled, throttled, saturated, or unknown states.
|
||||||
|
pub reason: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WorkloadAdmissionSnapshot {
|
||||||
|
/// Create a snapshot for a workload class and admission state.
|
||||||
|
pub const fn new(class: WorkloadClass, state: AdmissionState) -> Self {
|
||||||
|
Self {
|
||||||
|
class,
|
||||||
|
state,
|
||||||
|
active: None,
|
||||||
|
queued: None,
|
||||||
|
limit: None,
|
||||||
|
reason: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Add optional active, queued, and limit counters.
|
||||||
|
pub const fn with_counts(mut self, active: Option<usize>, queued: Option<usize>, limit: Option<usize>) -> Self {
|
||||||
|
self.active = active;
|
||||||
|
self.queued = queued;
|
||||||
|
self.limit = limit;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Add a human-readable reason.
|
||||||
|
pub fn with_reason(mut self, reason: impl Into<String>) -> Self {
|
||||||
|
self.reason = Some(reason.into());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Read-only admission registry snapshot.
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Default)]
|
||||||
|
pub struct WorkloadAdmissionRegistrySnapshot {
|
||||||
|
entries: Vec<WorkloadAdmissionSnapshot>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WorkloadAdmissionRegistrySnapshot {
|
||||||
|
/// Create a registry snapshot from per-class entries.
|
||||||
|
pub fn new(entries: Vec<WorkloadAdmissionSnapshot>) -> Self {
|
||||||
|
Self { entries }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Borrow all entries in snapshot order.
|
||||||
|
pub fn entries(&self) -> &[WorkloadAdmissionSnapshot] {
|
||||||
|
&self.entries
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Find the admission snapshot for a workload class.
|
||||||
|
pub fn get(&self, class: WorkloadClass) -> Option<&WorkloadAdmissionSnapshot> {
|
||||||
|
self.entries.iter().find(|entry| entry.class == class)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Provider boundary for future read-only workload admission snapshots.
|
||||||
|
pub trait WorkloadAdmissionSnapshotProvider {
|
||||||
|
/// Return the current workload admission registry snapshot.
|
||||||
|
fn workload_admission_snapshot(&self) -> WorkloadAdmissionRegistrySnapshot;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn workload_contract_covers_required_classes() {
|
||||||
|
let labels: Vec<_> = WorkloadClass::REQUIRED.iter().map(|class| class.as_str()).collect();
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
labels,
|
||||||
|
vec![
|
||||||
|
"foreground_read",
|
||||||
|
"foreground_write",
|
||||||
|
"metadata",
|
||||||
|
"scanner",
|
||||||
|
"repair",
|
||||||
|
"replication"
|
||||||
|
]
|
||||||
|
);
|
||||||
|
assert_eq!(WorkloadClass::Repair.to_string(), "repair");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn admission_snapshot_preserves_unknown_and_counted_states() {
|
||||||
|
let unknown = WorkloadAdmissionSnapshot::new(WorkloadClass::Scanner, AdmissionState::Unknown);
|
||||||
|
let open = WorkloadAdmissionSnapshot::new(WorkloadClass::ForegroundRead, AdmissionState::Open).with_counts(
|
||||||
|
Some(3),
|
||||||
|
Some(1),
|
||||||
|
Some(8),
|
||||||
|
);
|
||||||
|
let registry = WorkloadAdmissionRegistrySnapshot::new(vec![unknown.clone(), open.clone()]);
|
||||||
|
|
||||||
|
assert_eq!(registry.entries(), &[unknown, open]);
|
||||||
|
assert_eq!(
|
||||||
|
registry.get(WorkloadClass::Scanner).map(|snapshot| snapshot.state),
|
||||||
|
Some(AdmissionState::Unknown)
|
||||||
|
);
|
||||||
|
assert!(matches!(
|
||||||
|
registry.get(WorkloadClass::ForegroundRead).map(|snapshot| snapshot.state),
|
||||||
|
Some(state) if state.is_open()
|
||||||
|
));
|
||||||
|
assert_eq!(
|
||||||
|
registry
|
||||||
|
.get(WorkloadClass::ForegroundRead)
|
||||||
|
.and_then(|snapshot| snapshot.limit),
|
||||||
|
Some(8)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -104,6 +104,10 @@ Required `rustfs-storage-api` public re-exports:
|
|||||||
- `pub use object::{VersionMarker, WalkOptions, WalkVersionsSortOrder};`
|
- `pub use object::{VersionMarker, WalkOptions, WalkVersionsSortOrder};`
|
||||||
- `pub use topology::{DiskCapabilities, TopologyCapabilities, TopologyDisk, TopologyLabels, TopologyPool, TopologySet, TopologySnapshot, TopologySnapshotProvider};`
|
- `pub use topology::{DiskCapabilities, TopologyCapabilities, TopologyDisk, TopologyLabels, TopologyPool, TopologySet, TopologySnapshot, TopologySnapshotProvider};`
|
||||||
|
|
||||||
|
Required `rustfs-concurrency` public workload admission contract re-exports:
|
||||||
|
|
||||||
|
- `pub use workload::{AdmissionState, WorkloadAdmissionRegistrySnapshot, WorkloadAdmissionSnapshot, WorkloadAdmissionSnapshotProvider, WorkloadClass};`
|
||||||
|
|
||||||
ECStore must keep compile-time coverage for `StorageAdminApi`, `HealOperations`,
|
ECStore must keep compile-time coverage for `StorageAdminApi`, `HealOperations`,
|
||||||
and the separate `NamespaceLocking` operation group.
|
and the separate `NamespaceLocking` operation group.
|
||||||
|
|
||||||
|
|||||||
@@ -5,19 +5,19 @@ Status values: `[ ]` not started, `[~]` in progress, `[x]` complete, `[!]` block
|
|||||||
## Current Context
|
## Current Context
|
||||||
|
|
||||||
- Issue: [`rustfs/backlog#660`](https://github.com/rustfs/backlog/issues/660)
|
- Issue: [`rustfs/backlog#660`](https://github.com/rustfs/backlog/issues/660)
|
||||||
- Branch: `overtrue/arch-observability-topology-contracts`
|
- Branch: `overtrue/arch-scheduler-workload-contracts`
|
||||||
- Baseline: stacked on `origin/overtrue/arch-test-harness-compat-aliases`
|
- Baseline: stacked on `origin/overtrue/arch-test-harness-compat-aliases`
|
||||||
after `rustfs/rustfs#3600`
|
after `rustfs/rustfs#3601`
|
||||||
(`ae6a5befcf60f2f2ebce9799ba93649032234273`).
|
(`dc099f415670d94c0f79a7f9015653a08cdf458f`).
|
||||||
- PR type for this branch: `contract`
|
- PR type for this branch: `test-only` plus `contract`
|
||||||
- Runtime behavior changes: none.
|
- Runtime behavior changes: none.
|
||||||
- Rust code changes: add observability and topology capability DTO/trait
|
- Rust code changes: add scheduler preservation tests and workload admission
|
||||||
contracts to `rustfs-storage-api`.
|
contract types to `rustfs-concurrency`.
|
||||||
- CI/script changes: extend migration re-export guard coverage for the new
|
- CI/script changes: extend migration re-export guard coverage for workload
|
||||||
contract exports.
|
admission contract exports.
|
||||||
- Docs changes: add
|
- Docs changes: add
|
||||||
[`runtime-capability-contracts.md`](runtime-capability-contracts.md) and
|
[`workload-admission-contracts.md`](workload-admission-contracts.md) and
|
||||||
record the combined PR-08/API-013 plus PR-09/API-014 contract slice.
|
record the combined PR-05/TEST-SCH-001 plus PR-07/R-015 slice.
|
||||||
|
|
||||||
## Phase 0 Tasks
|
## Phase 0 Tasks
|
||||||
|
|
||||||
@@ -119,6 +119,31 @@ Status values: `[ ]` not started, `[~]` in progress, `[x]` complete, `[!]` block
|
|||||||
plus supported, unsupported, unknown, and disabled capability states;
|
plus supported, unsupported, unknown, and disabled capability states;
|
||||||
focused storage-api check; migration guard; formatting; diff hygiene; and
|
focused storage-api check; migration guard; formatting; diff hygiene; and
|
||||||
three-expert review.
|
three-expert review.
|
||||||
|
|
||||||
|
- [x] `PR-05/TEST-SCH-001` Add scheduler preservation tests.
|
||||||
|
- Completed slice: pin worker over-release clamping, reusable scheduler
|
||||||
|
default thresholds and priority boundaries, backpressure pipe metadata
|
||||||
|
reads, and get-object queue snapshot saturation/zero-total semantics.
|
||||||
|
- Acceptance: current reusable scheduling and admission-facing behavior is
|
||||||
|
covered before later read-only snapshot extraction.
|
||||||
|
- Must preserve: scheduler algorithm, queue capacity, threshold defaults,
|
||||||
|
Tokio runtime settings, request admission, scanner admission, heal
|
||||||
|
admission, replication admission, and background task admission behavior.
|
||||||
|
- Verification: focused concurrency tests, focused concurrency check,
|
||||||
|
migration guard, formatting, diff hygiene, and three-expert review.
|
||||||
|
|
||||||
|
- [x] `PR-07/R-015` Add runtime workload class contract.
|
||||||
|
- Completed slice: add `WorkloadClass`, `AdmissionState`,
|
||||||
|
`WorkloadAdmissionSnapshot`, `WorkloadAdmissionRegistrySnapshot`, and
|
||||||
|
`WorkloadAdmissionSnapshotProvider` to `rustfs-concurrency`.
|
||||||
|
- Acceptance: foreground read, foreground write, metadata, scanner, repair,
|
||||||
|
and replication workload classes are representable through read-only
|
||||||
|
admission registry snapshots without ECStore dependency.
|
||||||
|
- Must preserve: no SchedulerManager decision logic, Tokio worker defaults,
|
||||||
|
scanner/heal admission behavior, replication admission behavior, cluster
|
||||||
|
scheduling, placement, membership, or business call-site migration.
|
||||||
|
- Verification: workload contract unit tests, focused concurrency check,
|
||||||
|
migration guard, formatting, diff hygiene, and three-expert review.
|
||||||
- [x] `TEST-PRTYPE-001` Check PR type enum consistency.
|
- [x] `TEST-PRTYPE-001` Check PR type enum consistency.
|
||||||
- Acceptance: `./scripts/check_architecture_migration_rules.sh` parses the
|
- Acceptance: `./scripts/check_architecture_migration_rules.sh` parses the
|
||||||
allowed PR types from [`crate-boundaries.md`](crate-boundaries.md) and fails
|
allowed PR types from [`crate-boundaries.md`](crate-boundaries.md) and fails
|
||||||
@@ -1704,7 +1729,9 @@ Status values: `[ ]` not started, `[~]` in progress, `[x]` complete, `[!]` block
|
|||||||
1. `contract`/`consumer-migration`: wire read-only observability and topology
|
1. `contract`/`consumer-migration`: wire read-only observability and topology
|
||||||
snapshots to implementation owners without changing runtime, profiling,
|
snapshots to implementation owners without changing runtime, profiling,
|
||||||
placement, or admin route behavior.
|
placement, or admin route behavior.
|
||||||
2. `pure-move`/`consumer-migration`: continue larger cleanup slices with the
|
2. `api-extraction`: expose the set-local scheduler snapshot after the
|
||||||
|
TEST-SCH-001 and R-015 protection/contract slice.
|
||||||
|
3. `pure-move`/`consumer-migration`: continue larger cleanup slices with the
|
||||||
loss-prevention guards active for remaining ECStore compatibility contracts
|
loss-prevention guards active for remaining ECStore compatibility contracts
|
||||||
now that broad compatibility passthroughs are fully closed.
|
now that broad compatibility passthroughs are fully closed.
|
||||||
|
|
||||||
@@ -1712,14 +1739,24 @@ Status values: `[ ]` not started, `[~]` in progress, `[x]` complete, `[!]` block
|
|||||||
|
|
||||||
| Expert | Status | Notes |
|
| Expert | Status | Notes |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| Quality/architecture | passed | S-015 removes obsolete KMS admin policy action variants after the handler fallback cleanup; API-042/API-043/API-044/API-045/API-046/API-047/API-048/API-049/API-050/API-051/API-052/API-053/API-054 narrow notify, S3 Select, OBS, IAM, Swift, heal, scanner, RustFS runtime, test, fuzz, lifecycle helper, harness, and RustFS runtime compatibility contracts without moving ECStore storage metadata ownership; G-011/G-012/G-013 add docs-only baselines for scheduler, placement/repair, and profiling/NUMA work; Issue #660 PR-08/PR-09 add read-only observability and topology contracts in rustfs-storage-api only. |
|
| Quality/architecture | passed | S-015 removes obsolete KMS admin policy action variants after the handler fallback cleanup; API-042/API-043/API-044/API-045/API-046/API-047/API-048/API-049/API-050/API-051/API-052/API-053/API-054 narrow notify, S3 Select, OBS, IAM, Swift, heal, scanner, RustFS runtime, test, fuzz, lifecycle helper, harness, and RustFS runtime compatibility contracts without moving ECStore storage metadata ownership; G-011/G-012/G-013 add docs-only baselines for scheduler, placement/repair, and profiling/NUMA work; Issue #660 PR-08/PR-09 add read-only observability and topology contracts in storage-api only; current PR-05/PR-07 slice adds scheduler preservation tests and a small workload admission contract in concurrency only. |
|
||||||
| Migration preservation | passed | KMS endpoint URLs, query aliases, request bodies, response contracts, and dedicated `kms:*` authorization behavior are preserved; event builder call sites, ECStore event bridge conversion, restore event data, version IDs, metadata filtering, config read/save semantics, S3 Select store/error/buffer semantics, OBS metrics state reads, IAM config/notification/error semantics, Swift bucket metadata access, heal disk/resume/task behavior, scanner lifecycle/replication/data-usage behavior, RustFS startup/admin/app/storage runtime access, e2e/test/fuzz import behavior, lifecycle expiration/transition helper DTO field contracts, flattened harness and RustFS runtime scalar/secondary alias behavior, unchanged no-op handling, remove-event behavior, scheduler/readiness/placement/profiling runtime behavior, platform gates, missing/unknown capability states, and placement/topology labels are preserved. |
|
| Migration preservation | passed | KMS endpoint URLs, query aliases, request bodies, response contracts, and dedicated `kms:*` authorization behavior are preserved; event builder call sites, ECStore event bridge conversion, restore event data, version IDs, metadata filtering, config read/save semantics, S3 Select store/error/buffer semantics, OBS metrics state reads, IAM config/notification/error semantics, Swift bucket metadata access, heal disk/resume/task behavior, scanner lifecycle/replication/data-usage behavior, RustFS startup/admin/app/storage runtime access, e2e/test/fuzz import behavior, lifecycle expiration/transition helper DTO field contracts, flattened harness and RustFS runtime scalar/secondary alias behavior, unchanged no-op handling, remove-event behavior, scheduler/readiness/placement/profiling runtime behavior, platform gates, missing/unknown capability states, placement/topology labels, scheduler thresholds, queue snapshot semantics, and admission behavior are preserved. |
|
||||||
| Testing/verification | passed | Focused compiles/tests, fuzz target compile, guards, formatting, diff hygiene, risk scan, and full `make pre-commit` passed for prior code slices; current Issue #660 PR-08/PR-09 contract slice uses storage-api tests/checks, migration guard, formatting, diff hygiene, and three-expert review. |
|
| Testing/verification | passed | Focused compiles/tests, fuzz target compile, guards, formatting, diff hygiene, risk scan, and full `make pre-commit` passed for prior code slices; current Issue #660 PR-05/PR-07 slice uses concurrency tests/checks, migration guard, formatting, diff hygiene, and three-expert review. |
|
||||||
|
|
||||||
## Verification Notes
|
## Verification Notes
|
||||||
|
|
||||||
Passed before push:
|
Passed before push:
|
||||||
|
|
||||||
|
- Issue #660 PR-05/PR-07 current slice:
|
||||||
|
- `cargo test -p rustfs-concurrency --no-fail-fast`: passed.
|
||||||
|
- `cargo check -p rustfs-concurrency`: passed.
|
||||||
|
- `./scripts/check_architecture_migration_rules.sh`: passed.
|
||||||
|
- `./scripts/check_layer_dependencies.sh`: passed.
|
||||||
|
- `cargo fmt --all --check`: passed.
|
||||||
|
- `git diff --check`: passed.
|
||||||
|
- `make pre-commit`: passed.
|
||||||
|
- Three-expert review: passed.
|
||||||
|
|
||||||
- Issue #660 PR-08/PR-09 current slice:
|
- Issue #660 PR-08/PR-09 current slice:
|
||||||
- `cargo test -p rustfs-storage-api`: passed.
|
- `cargo test -p rustfs-storage-api`: passed.
|
||||||
- `cargo check -p rustfs-storage-api`: passed.
|
- `cargo check -p rustfs-storage-api`: passed.
|
||||||
|
|||||||
@@ -0,0 +1,43 @@
|
|||||||
|
# Workload Admission Contracts
|
||||||
|
|
||||||
|
This document records the `rustfs/backlog#660` PR-05 and PR-07 scheduler
|
||||||
|
preservation and runtime workload-class contract slice.
|
||||||
|
|
||||||
|
## Preservation Coverage
|
||||||
|
|
||||||
|
The `rustfs-concurrency` tests pin the current reusable scheduler and
|
||||||
|
admission-facing behavior before later snapshot extraction:
|
||||||
|
|
||||||
|
- Worker slot over-release remains clamped by the configured worker limit.
|
||||||
|
- Scheduler default buffer and priority thresholds remain unchanged.
|
||||||
|
- Scheduler priority boundaries remain high below the high threshold, normal at
|
||||||
|
both thresholds, and low above the low threshold.
|
||||||
|
- Backpressure pipe metadata reads preserve buffer capacity and state without
|
||||||
|
mutating the manager state.
|
||||||
|
- `GetObjectQueueSnapshot` preserves saturated, over-available, and zero-total
|
||||||
|
permit semantics.
|
||||||
|
|
||||||
|
## Workload Class Contract
|
||||||
|
|
||||||
|
`WorkloadClass` defines the required future admission categories:
|
||||||
|
|
||||||
|
- Foreground read.
|
||||||
|
- Foreground write.
|
||||||
|
- Metadata.
|
||||||
|
- Scanner.
|
||||||
|
- Repair.
|
||||||
|
- Replication.
|
||||||
|
|
||||||
|
`AdmissionState`, `WorkloadAdmissionSnapshot`, and
|
||||||
|
`WorkloadAdmissionRegistrySnapshot` define read-only status shapes for later
|
||||||
|
runtime owners. They do not replace the current scheduler, request guard,
|
||||||
|
scanner, heal, replication, or ECStore placement behavior.
|
||||||
|
|
||||||
|
## Boundary Rules
|
||||||
|
|
||||||
|
- `rustfs-concurrency` owns this reusable contract surface.
|
||||||
|
- The contract does not depend on `rustfs-ecstore` or RustFS binary runtime
|
||||||
|
state.
|
||||||
|
- No scheduler decision logic, queue capacity, Tokio runtime default, scanner
|
||||||
|
admission, heal admission, replication admission, placement, membership, or
|
||||||
|
NUMA behavior changes are part of this slice.
|
||||||
@@ -212,6 +212,18 @@ require_source_line \
|
|||||||
"crates/storage-api/src/lib.rs" \
|
"crates/storage-api/src/lib.rs" \
|
||||||
"pub use capability::{CapabilitySnapshotError, CapabilityState, CapabilityStatus};" \
|
"pub use capability::{CapabilitySnapshotError, CapabilityState, CapabilityStatus};" \
|
||||||
"storage-api public capability contract re-export"
|
"storage-api public capability contract re-export"
|
||||||
|
require_source_contains \
|
||||||
|
"crates/concurrency/src/lib.rs" \
|
||||||
|
"pub use workload::{" \
|
||||||
|
"concurrency public workload admission contract re-export"
|
||||||
|
require_source_contains \
|
||||||
|
"crates/concurrency/src/lib.rs" \
|
||||||
|
"AdmissionState, WorkloadAdmissionRegistrySnapshot, WorkloadAdmissionSnapshot, WorkloadAdmissionSnapshotProvider," \
|
||||||
|
"concurrency public workload admission contract status re-exports"
|
||||||
|
require_source_contains \
|
||||||
|
"crates/concurrency/src/lib.rs" \
|
||||||
|
"WorkloadClass," \
|
||||||
|
"concurrency public workload class re-export"
|
||||||
require_source_line \
|
require_source_line \
|
||||||
"crates/storage-api/src/lib.rs" \
|
"crates/storage-api/src/lib.rs" \
|
||||||
"pub use multipart::{CompletePart, ListMultipartsInfo, ListPartsInfo, MultipartInfo, MultipartUploadResult, PartInfo};" \
|
"pub use multipart::{CompletePart, ListMultipartsInfo, ListPartsInfo, MultipartInfo, MultipartUploadResult, PartInfo};" \
|
||||||
|
|||||||
Reference in New Issue
Block a user