Skip to content

Instantly share code, notes, and snippets.

@weidongxu-microsoft
Last active February 1, 2024 09:04
Show Gist options
  • Save weidongxu-microsoft/ab911639b93208f2214bdc41b13f936f to your computer and use it in GitHub Desktop.
Save weidongxu-microsoft/ab911639b93208f2214bdc41b13f936f to your computer and use it in GitHub Desktop.
DevBox method signature issue (DevCenter)

Context

Related issue:

PR

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.

First Question: Do we accept this client method signature design?

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.

Second Question: Should we support this client method signature as default?

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.

@haolingdong-msft
Copy link

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment