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
n
path 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.