Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions specification/storagecache/cspell.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ import:
words:
- amlfilesystem
- clfs
- mebibytes

Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import "@azure-tools/typespec-azure-core";
import "@azure-tools/typespec-azure-resource-manager";
import "@typespec/rest";
import "@typespec/versioning";
import "./models.tsp";
import "./AmlFilesystem.tsp";

using TypeSpec.Rest;
using TypeSpec.Versioning;
using Azure.ResourceManager;
using TypeSpec.Http;

namespace Microsoft.StorageCache;

/**
* A rebalance job instance. Rebalances OST data across storage targets after a cluster expansion.
* Follows Azure Resource Manager standards: https://github.com/Azure/azure-resource-manager-rpc/blob/master/v1.0/resource-api-reference.md
*/
@added(Versions.v2026_08_01)
@parentResource(AmlFilesystem)
model RebalanceJob
is Azure.ResourceManager.ProxyResource<RebalanceJobProperties> {
...ResourceNameParameter<
Resource = RebalanceJob,
KeyName = "rebalanceJobName",
SegmentName = "rebalanceJobs",
NamePattern = "^[0-9a-zA-Z][-0-9a-zA-Z_]{0,78}[0-9a-zA-Z]$"
>;
}

@added(Versions.v2026_08_01)
@armResourceOperations(#{ omitTags: true })
interface RebalanceJobs {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

[NEW] 🔵 Suggestion [ARM job-cancellation pattern]RebalanceJobs exposes GET/LIST/PATCH/DELETE, no PUT; cancellation is via PATCH adminStatus: Cancel.

Classification reasoning: New resource interface added in this PR.

Issue: A dedicated POST cancel action is the more idiomatic ARM pattern for cancelling a job, versus overloading PATCH with an adminStatus field.

Suggested fix: Optional / design observation only — PATCH-adminStatus matches this project's existing job-resource family (ImportJob, AutoExportJob, etc.), so keeping it for consistency is reasonable. No PUT is correct here since RebalanceJob is system-created via the expansion runRebalanceJob flag.

/**
* Returns a rebalance job.
*/
@tag("rebalanceJobs")
get is ArmResourceRead<RebalanceJob, Error = CloudError>;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

[NEW] 🔵 Suggestion [Consistent error responses §2.7] — mixed error models within the same interface.

Classification reasoning: New resource interface added in this PR.

Issue: get (this line) and listByAmlFilesystem (line 74) use Error = CloudError, while update (line 51) and delete (line 64) use Error = ErrorResponse. Mixed error models across operations of the same resource produce inconsistent error schemas in the generated spec and SDKs.

Suggested fix: Use a single consistent error model across all operations of the RebalanceJobs interface.


/**
* Update a rebalance job instance.
*/
@tag("rebalanceJobs")
@patch(#{ implicitOptionality: false })
@Azure.Core.useFinalStateVia("azure-async-operation")
update is ArmCustomPatchAsync<
RebalanceJob,
PatchModel = RebalanceJobUpdate,
LroHeaders = ArmCombinedLroHeaders<FinalResult = RebalanceJob> &
Azure.Core.Foundations.RetryAfterHeader,
Error = ErrorResponse
>;

/**
* Schedules a rebalance job for deletion.
*/
@tag("rebalanceJobs")
delete is ArmResourceDeleteWithoutOkAsync<
RebalanceJob,
Response =
| ArmDeleteAcceptedLroResponse<ArmCombinedLroHeaders<FinalResult = void> &
Azure.Core.Foundations.RetryAfterHeader>
| ArmDeletedNoContentResponse,
Error = ErrorResponse
>;

/**
* Returns all the rebalance jobs the user has access to under an AML File System.
*/
@tag("rebalanceJobs")
listByAmlFilesystem is ArmResourceListByParent<
RebalanceJob,
Response = ArmResponse<RebalanceJobsListResult>,
Error = CloudError
>;
}

@@maxLength(RebalanceJob.name, 80);
@@minLength(RebalanceJob.name, 2);
@@doc(
RebalanceJob.name,
"Name for the rebalance job. Allows alphanumerics, underscores, and hyphens. Start and end with alphanumeric."
);
@@doc(RebalanceJob.properties, "Properties of the rebalance job.");
@@doc(
RebalanceJobs.update::parameters.properties,
"Object containing the user-selectable properties of the rebalance job. If read-only properties are included, they must match the existing values of those properties."
);
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,9 @@ using Microsoft.StorageCache;
#suppress "@azure-tools/typespec-azure-core/no-legacy-usage" "FIXME: Update justification, follow aka.ms/tsp/conversion-fix for details"
@@Legacy.flattenProperty(ExpansionJob.properties);

#suppress "@azure-tools/typespec-azure-core/no-legacy-usage" "Required for ProvisioningStateMustBeReadOnly lint rule to traverse properties"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

[NEW] 🔵 Suggestion [@flattenProperty on new APIs §5]@@Legacy.flattenProperty(RebalanceJob.properties) with a no-legacy-usage suppression.

Classification reasoning: New resource (RebalanceJob) added in this PR; this legacy flatten + suppression are new.

Issue: New resource types should avoid legacy property flattening (SDK-breaking risk). The suppression reason ("Required for ProvisioningStateMustBeReadOnly lint rule to traverse properties") is technically questionable — flattening is not generally required for that rule.

Suggested fix: Verify whether flattening is truly required. If kept for consistency with the sibling job resources, document that concrete rationale in the suppression reason. Low severity given family consistency.

@@Legacy.flattenProperty(RebalanceJob.properties);

@@clientName(Caches.createOrUpdate::parameters.resource, "cache");
@@clientName(Caches.update::parameters.properties, "cache");
@@clientName(Caches.startPrimingJob::parameters.body, "primingjob");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"parameters": {
"operationId": "testoperationid",
"api-version": "2026-08-01",
"location": "westus",
"subscriptionId": "00000000-0000-0000-0000-000000000000"
},
"responses": {
"200": {
"body": {
"name": "testoperationid",
"endTime": "2023-01-01T16:13:13.933Z",
"id": "/subscriptions/id/locations/westus/ascOperations/testoperationid",
"startTime": "2023-01-01T13:13:13.933Z",
"status": "Succeeded"
}
}
},
"operationId": "AscOperations_Get",
"title": "AscOperations_Get"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"parameters": {
"api-version": "2026-08-01",
"location": "eastus",
"subscriptionId": "00000000-0000-0000-0000-000000000000"
},
"responses": {
"200": {
"body": {
"value": [
{
"name": {
"localizedValue": "Cache",
"value": "Cache"
},
"currentValue": 1,
"limit": 4,
"unit": "Count"
},
{
"name": {
"localizedValue": "AmlFilesystem",
"value": "AmlFilesystem"
},
"currentValue": 0,
"limit": 4,
"unit": "Count"
}
]
}
}
},
"operationId": "AscUsages_List",
"title": "AscUsages_List"
}
Loading
Loading