Related issue:
PR
- Azure/azure-rest-api-specs#26359 (only a draft)
DevBox resource model is
@resource("devboxes")
@parentResource(User)
model DevBox {
@key("devBoxName")
@visibility("read", "create")
name: string;
@path("projectName")
@visibility("read", "create")
projectName: string;
@path("userId")
@visibility("read", "create")
user: string;
...
}REST API is PUT /projects/{projectName}/users/{userId}/devboxes/{devBoxName}. Path parameter is projectName, userId, devBoxName.
The projectName, user, projectName in the resource model won't be in request body, and they would be in response body (hence "read" in @visibility).
The typical client method signature would be
class DevBox {
name: getter;
projectName: getter;
user: getter;
}
DevBox createDevBox(String projectName, String userId, String devBoxName, DevBox devBox)Some SDK arch discuss whether the client method signature should be
class DevBox {
name: setter; getter;
projectName: setter; getter;
user: setter; getter;
}
DevBox createDevBox(DevBox devBox) {
return createDevBoxREST(devBox.projectName, devBox.user, devBox.name, devBox);
}That the 3 path parameter would be directly set to endpoint URL, via the 3 properties in DevBox class.
One issue raised during discussion is that it could cause different pattern of client method signature on resource create/update.
For those that have these path segment value in response, the signature be createDevBox(DevBox); while for those not having all path segment value in response, it would be e.g. createToyBox(pathParam1, pathParam2, ToyBox).
And it could also make version resiliency more complicated. Adding a read-only property to a response is not breaking change on REST API. But adding read-only pathParam1 pathParam2 into ToyBox response in above example would change the method signature to createToyBox(ToyBox).
Another minor issue I can think of is that this PUT is typically a "create or replace".
In runtime, SDK won't know whether the REST API would do a "create" or "replace" (which depends on the existence of the resource in backend).
If user gets a DevBox model from GET, then sets a new name and call createDevBox, they may think they just "updated" that DevBox with a new name, while in reality they "created" a new one.
This problem would exist in current client method signature, but there these method level parameters at least make them distinguished from class level properties in DevBox.
If it is "yes" to first question, then it is a question whether we should support it as a general feature (instead of a one-time customization).
This 3 path/property case is the same scenario of a very common 1 path/property case of resource model
@resource("resources")
model ResourceModel {
@key("resourceName")
@visibility("read")
name: string;
...
}And changing the default client method signature would affect many existing cases. That
ResourceModel createOrReplace(String resourceName, ResourceModel resourceModel) to ResourceModel createOrReplace(ResourceModel resourceModel).
Alternatively, we can apply this signature only when "create" is applied to this path/property. E.g.
@resource("resources")
model ResourceModel {
@key("resourceName")
@visibility("read", "create")
name: string;
...
}This way, at least it won't break existing SDKs.
For me, I tend to treat it as customization. If we do want to support it, we could apply the logic for operation which has more than
npath parameter. e.g. if n=2, if there are more than 2 path parameters, we will just use the model, otherwise, we will put the path parameters to the method signature.