Implementar operações do controle de versão
Conectores personalizados para Aplicativos Lógicos do Azure, Microsoft Power Automate ou Microsoft Power Apps devem fornecer um arquivo de especificação OpenAPI. Essa especificação OpenAPI define pontos de entrada individuais conhecidos como operações. Cada operação tem um operationId
exclusivo e uma combinação exclusiva de urlPath
e HttpVerb
.
{
"/items": {
"get": {
"summary": "Get rows",
"description": "This operation gets a list of items.",
"operationId": "GetItems"
},
"post": {
"summary": "Insert row",
"description": "This operation inserts an item.",
"operationId": "PostItem"
}
}
}
Essas operações podem crescer e mudar ao longo do tempo à medida que recursos são adicionados ou expandidos. Algumas alterações são meramente aditivas e não necessariamente quebram o contrato existente entre clientes e servidores. Adicionar novos parâmetros, retornar mais dados ou permitir entradas mais flexíveis podem cair nessa categoria.
No entanto, muitas alterações podem acabar rescindindo o contrato descrito na especificação OpenAPI. Entre as ações que se enquadram na categoria de "alteração interruptiva", estão: remover parâmetros, não oferecer mais suporte a determinadas entradas ou alterar o significado e o comportamento de uma entrada, saída ou a própria operação.
Para desenvolver uma API com segurança, é importante ter um padrão que os clientes possam seguir. É responsabilidade da API manter a compatibilidade com versões anteriores, comunicar a intenção e delinear os atributos de controle de versão. É responsabilidade do cliente mostrar ou ocultar operações que foram preteridas, expiradas ou que possam ter versões mais recentes disponíveis. Dessa forma, as operações podem crescer e desenvolver ao longo do tempo, sem causar fragilidade indevida nos aplicativos que dependem delas.
Anotação da API
A OpenAPI não tem suporte intrínseco para controle de versão operacional. Para atingir nosso objetivo, grande parte do trabalho é feita por meio do objeto x-ms-api-annotation
, que é aplicado no escopo global e no escopo da operação. O objeto global contém propriedades que se aplicam à API como um todo:
{
"x-ms-api-annotation": {
"status": "Preview"
}
}
Propriedade | Valores | Padrão | Descrição |
---|---|---|---|
status | "Preview" "Production" |
"Preview" |
Status da API como um todo — começando na Versão preliminar e passando para a Produção, como ditam o uso e a estabilidade |
No escopo operacional, esse objeto contém propriedades mais detalhadas. Também existem propriedades adicionais fora do objeto, as quais se aplicam e participam do processo evolucionário do controle de versão:
{
"deprecated": true,
"x-ms-api-annotation": {
"status": "Production",
"family": "MyOperation",
"revision": 2
}
}
Propriedade | Valores | Padrão | Descrição |
---|---|---|---|
deprecated | null false true |
false |
Indica se a operação está preterida |
x-ms-visibility | null "" "Important" "Advanced" "Internal" |
"" |
A visibilidade e a proeminência pretendidas dessa operação, em que null ou "" implica um estado Normal |
status | "Preview" "Production" |
"Production" |
Status da operação — isso pode ser diferente do estado da própria API, mas, caso não seja especificado, será herdado do status da API de nível superior |
family | {common operation name} | operationName | Nome que se aplica a todas as revisões dessa operação |
revision | numérico (1, 2, 3...) | 1 |
Revisão da família operacional especificada |
expires | Data da ISO8601 | (nenhum) | Dica opcional ao cliente para indicar o fim do suporte projetado |
Preterido pode ser definido como true
quando não for mais desejável que os clientes usem essa operação. Essa propriedade existe na especificação Campos fixos da OpenAPI.
Visibilidade é um indicador da proeminência relativa pretendida da operação. Uma visibilidade "Important"
indica que a operação deve se dar em direção à parte superior da lista, exibida de forma proeminente. O padrão é uma visibilidade normal (indicada por null
ou cadeia de caracteres vazia ""
) e significa que a operação aparecerá na lista, provavelmente após as operações importantes. Uma visibilidade "Advanced"
indica que a operação pode se dar em direção à parte inferior da lista ou até mesmo ficar oculta, inicialmente, por trás de um controle expando. As operações avançadas podem ser mais difíceis de usar, além de menos populares ou mais restritas. Uma visibilidade "Internal"
indica que a operação não deve ser exposta aos usuários e só deve ser usada internamente. As operações internas são programaticamente úteis e valiosas, mas não se destinam aos usuários finais. As operações internas também podem ser marcadas como tal para ocultá-las de qualquer tipo de interface do usuário durante o processo de preterimento sem realmente removê-las da API, o que causaria uma alteração significativa.
Status indica a estabilidade da API ou da operação. "Preview"
indica que a operação ou a API é nova e possivelmente não comprovada. Versão preliminar é um indicador de que os sistemas de produção devem ser cautelosos sobre assumir uma dependência. Assim que a operação ou a API estiver mais estabelecida e tiver sido comprovado que atende aos padrões de confiabilidade, à taxa de êxito e à escalabilidade, ela poderá ser atualizada intencionalmente para o status "Production"
.
Os requisitos de métrica a seguir geralmente se aplicam às operações que buscam o status "Production"
:
- 80% de taxa de êxito por um período de três semanas
- definida como a porcentagem de códigos de resposta HTTP no intervalo 2xx
- 99,9% de confiabilidade, sustentada por um período de três semanas
- definida como a porcentagem de códigos de resposta HTTP no intervalo que não seja 5xx (502, 504 e 520 são excluídos desse cálculo)
Família indica a relação entre as operações, as quais são conceitualmente a mesma operação, mas são revisões diferentes com alterações possivelmente significativas entre elas. Várias operações compartilharão o mesmo nome de família caso devam ser consideradas revisões umas das outras e serão sequenciadas por seus números de revisão exclusivos.
Revisão indica a ordem evolucionária da operação dentro na família de operações. Cada operação em uma família terá uma revisão, que se trata de um índice integral que implica uma sequência. Uma revisão vazia será considerada como revisão 1
. Quando revisões mais recentes de uma operação estiverem disponíveis, os clientes devem exibi-las de modo mais proeminente e recomendá-las de modo mais intencional, mas ainda permitir a seleção de revisões potencialmente mais antigas que ainda não tenham sido preteridas.
Expira é opcional e indica um possível prazo do fim da vida útil em que o suporte para a operação não será mais garantido. Isso só deve ser definido para operações preteridas e, no momento, não está refletido em nenhuma interface.
Tempo de vida operacional
As operações têm um tempo de vida previsível que pode ser mostrado como exemplo.
Ponto inicial
Inicialmente, pode ser que as operações não indiquem necessariamente nada sobre revisões. Essas operações têm padrões aplicados e, portanto, são consideradas como revisão 1 em um nome de família equivalente a operationId
.
{
"/{list}/items": {
"get": {
"summary": "Get rows",
"description": "This operation gets a list of items.",
"operationId": "GetItems"
}
}
}
Isso é equivalente à definição mais explícita:
{
"/{list}/items": {
"get": {
"summary": "Get rows",
"description": "This operation gets a list of items.",
"operationId": "GetItems",
"deprecated": false,
"x-ms-api-annotation": {
"status": "Production",
"family": "GetItems",
"revision": 1
}
}
}
}
Início da operação
A maioria das evoluções de uma API estabelece a adição de uma operação. Novos métodos e novas revisões de métodos existentes, por exemplo. Para iniciar uma nova revisão de modo seguro, você ajustou a especificação de OpenAPI desta maneira:
{
"/{list}/items": {
"get": {
"summary": "Get rows (V1 - downplayed)",
"description": "This operation gets a list of items.",
"operationId": "GetItems",
"deprecated": false,
"x-ms-visibility": "advanced",
"x-ms-api-annotation": {
"status": "Production",
"family": "GetItems",
"revision": 1
}
}
}
"/v2/{list}/items": {
"get": {
"summary": "Get rows (V2 - new hotness)",
"description": "This operation gets a list of items.",
"operationId": "GetItems_V2",
"deprecated": false,
"x-ms-api-annotation": {
"status": "Preview",
"family": "GetItems",
"revision": 2
}
}
}
}
Importante
Observe que GetItems V2 tem uma operationId
exclusiva e está, inicialmente, listado no status de versão preliminar.
Observe também que agora GetItems v1 tem visibilidade avançada, portanto, não será exibido de forma proeminente.
Preterimento de operação
Às vezes, os pontos de entrada v1 existentes permanecem indefinidamente caso continuem a fornecer valor, e não há um motivo convincente para encerrá-los. No entanto, muitos pontos de entrada v2 substituem intencionalmente o ponto de entrada V1. Para fazer isso com segurança, todo o tráfego deve alcançar o valor nominal zero para a operação original. Assim que a telemetria confirmar essa circunstância, a seguinte alteração poderá ser feita:
{
"/{list}/items": {
"get": {
"summary": "Get rows (deprecated)",
"description": "This operation gets a list of items.",
"operationId": "GetItems",
"deprecated": true,
"x-ms-api-annotation": {
"status": "Production",
"family": "GetItems",
"revision": 1
}
}
}
"/v2/{list}/items": {
"get": {
"summary": "Get rows",
"description": "This operation gets a list of items.",
"operationId": "GetItems_V2",
"deprecated": false,
"x-ms-api-annotation": {
"status": "Production",
"family": "GetItems",
"revision": 2
}
}
}
}
Importante
Observe que agora GetItems v1 está marcado como preterido. Essa é a transição final para operações de preterimento. Agora, GetItems v2 substituiu completamente GetItems v1.
Por que se preocupar?
Há muitos motivos para aderir ao controle de versão operacional. Essencialmente, isso garantirá que clientes como os Aplicativos Lógicos do Azure e o Power Automate continuem a funcionar corretamente quando os usuários integrarem operações de conector em seus fluxos de dados. As operações devem ter controle de versão usando o método acima sempre que:
- Uma nova revisão de uma operação for adicionada
- Uma operação existente adicionar ou remover parâmetros
- Uma operação existente altera a entrada ou a saída significativamente
Estritamente falando
Pode haver casos em que seja possível não fazer o controle de versão—mas você deve ter cuidado ao fazer isso e também deve fazer vários testes para garantir que não tenha ignorado os casos extremos em que os usuários podem ser interrompidos inesperadamente. Veja uma breve lista de cuidados a serem tomados quanto ao não fazer o controle de versão:
Uma nova operação é adicionada.
Isso não interromperia especificamente os clientes existentes.
Um novo parâmetro opcional é adicionado a uma operação existente.
Isso não interromperia as chamadas existentes, mas é uma opção que deve ser considerada com cautela.
Uma operação existente altera sutilmente o comportamento.
Isso pode não interromper os chamadores existentes com base na natureza da alteração e de que os usuários dependem. Essa é a opção mais precária, uma vez que uma diferença relevante na aceitação da entrada, na geração de saída, no tempo ou no processamento pode afetar o comportamento da operação, dificultando a determinação do risco da alteração.
É sempre recomendável pecar pelo cuidado e iterar uma revisão quando ao fazer qualquer alteração de API não trivial.
Enviar comentários
Agradecemos muito os comentários sobre problemas com nossa plataforma de conectores ou novas ideias de recursos. Para fornecer comentários, acesseEnviar problemas ou obter ajuda com conectores e selecione o tipo de comentário.