Evolución de la API con el control de versiones

Conectores personalizados para Azure Logic Apps, Microsoft Power Automate o Microsoft Power Apps debe proporcionar un archivo de especificaciones OpenAPI. Esta especificación de OpenAPI define puntos de entrada individuales conocidos como operaciones. Cada operación tiene un operationId único y una urlPath única y una combinación 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"
        }
    }
}

Estas operaciones pueden crecer y cambiar con el tiempo a medida que se agregan o se expanden características. Algunos cambios son simples adiciones y no interrumpen necesariamente el contrato que existe entre clientes y servidores. Agregar nuevos parámetros, devolver más datos o permitir entradas más flexibles puede entrar en esta categoría.

Sin embargo, muchos cambios pueden interrumpir realmente el contrato descrito en la especificación de OpenAPI. La eliminación de los parámetros, que ya no sean compatibles con determinadas entradas, o el cambio del significado y el comportamiento de una entrada, salida o de la propia operación, entran en la categoría de "cambios importantes".

Para desarrollar una API de forma segura, es importante seguir un patrón por el que puedan navegar los clientes. Es responsabilidad de la API mantener la compatibilidad con las versiones anteriores, comunicar las intenciones y definir los atributos del control de versiones. Es responsabilidad del cliente mostrar u ocultar las operaciones que están en desuso, han expirado o puedan tener disponibles versiones más recientes. De esta manera, las operaciones pueden crecer y desarrollarse con el tiempo sin causar una fragilidad indebida en las aplicaciones que dependen de ellas.

Anotación de API

OpenAPI no presenta una compatibilidad intrínseca con el control de versiones operativo. Para lograr el objetivo, gran parte del trabajo se realiza mediante el objeto x-ms-api-annotation, que se aplica tanto en el ámbito global como en el ámbito de la operación. El objeto global contiene propiedades que se aplican a la API en su conjunto:

{
    "x-ms-api-annotation": {
        "status": "Preview"
    }
}
Propiedad Valores Predeterminado Descripción
estado "Preview" "Production" "Preview" Estado de la API en su conjunto: a partir de Preview (Versión preliminar) y escalando a Production (Producción), tal como lo dicten el uso y la estabilidad

En el ámbito operativo, este objeto contiene propiedades más detalladas. También hay propiedades adicionales fuera del objeto que se aplican y participan en el proceso evolutivo del control de versiones:

{
    "deprecated": true,
    "x-ms-api-annotation": {
        "status": "Production",
        "family": "MyOperation",
        "revision": 2
    }
}
Propiedad Valores Valor predeterminado Descripción
en desuso null false true false Indica si la operación está en desuso
x-ms-visibility null "" "Important" "Advanced" "Internal" "" Visibilidad prevista e importancia de esta operación, donde null o "" implica un estado Normal
estado "Preview" "Production" "Production" Estado de la operación: esto puede diferir del estado de la propia API, pero si no se especifica, se heredará del estado de la API del nivel superior
familia {nombre de la operación común} operationName Nombre que se aplica a cada revisión de esta operación
revisión valor numérico (1,2,3...) 1 Revisión de la familia operativa especificada
expira Fecha de la ISO8601 (ninguno) Sugerencia opcional para el cliente con la indicación del fin previsto del soporte técnico

Deprecated (En desuso) se puede establecer en true cuando ya no es deseable que los clientes utilicen esta operación. Esta propiedad existe en la especificación de Campos fijos de OpenAPI.

Visibility (Visibilidad) es un indicador de la importancia relativa prevista de la operación. Una visibilidad "Important" indica que la operación debe estar en la parte superior de la lista, mostrada de forma destacada. Una visibilidad normal (indicada por null o una cadena vacía "") es el valor predeterminado y significa que la operación aparecerá en la lista, probablemente después de las operaciones importantes. Una visibilidad "Advanced" indica que la operación puede estar en la parte inferior de la lista o incluso estar inicialmente oculta detrás de un control expando. Las operaciones avanzadas pueden ser más difíciles de utilizar, menos populares o aplicables de un modo más restrictivo. Una visibilidad "Internal" indica que la operación no se debe exponer a los usuarios y que solo se debe usar internamente. Las operaciones internas son valiosas y útiles de manera programática, pero no están destinadas a los usuarios finales. Las operaciones internas también pueden marcarse como tales para que estén ocultas en cualquier tipo de interfaz de usuario durante el proceso de caída en desuso sin quitarlas realmente de la API, lo que podría provocar un cambio importante.

Status (Estado) indica la estabilidad de la API u operación. "Preview" indica que la operación o la API es nueva y posiblemente esté poco probada. Preview (Versión preliminar) es un indicador de que los sistemas de producción deben ser prudentes a la hora de suponer una dependencia. Una vez que la operación o la API esté más establecida y haya demostrado que cumple con los estándares de confiabilidad, tasa de éxito y escalabilidad, se puede actualizar voluntariamente al estado "Production".

Los siguientes requisitos de métricas se suelen aplicar a las operaciones que buscan el estado "Production":

  • Un 80 % de tasa de éxito durante un período de tres semanas
    • definido como porcentaje de códigos de respuesta HTTP en el intervalo 2xx
  • Un 99,9 % de confiabilidad mantenido durante un período de tres semanas
    • definido como porcentaje de códigos de respuesta HTTP en el intervalo no de 5xx (502, 504 y 520 están excluidos de este cálculo)

Family (Familia) indica la relación entre las operaciones que constituyen conceptualmente la misma operación, pero que son distintas revisiones con cambios potencialmente importantes entre ellas. Varias operaciones compartirán el mismo nombre de familia si se deben considerar revisiones entre sí y se secuenciarán por sus números de revisión únicos.

Revision (Revisión) indica el orden evolutivo de la operación dentro de la familia de operaciones. Cada operación dentro de una familia tendrá una revisión que es un índice entero que implica una secuencia. Una revisión vacía se considerará como revisión 1. Cuando haya disponibles revisiones más recientes de una operación, los clientes deben mostrarlas de forma más destacada y recomendarlas expresamente, pero aún así deben permitir la selección de las revisiones potencialmente más antiguas que todavía no están en desuso.

Expires (Expira) es opcional e indica una posible fecha límite de fin de ciclo de vida en la que ya no se garantiza la compatibilidad con la operación. Solo se debe configurar para las operaciones en desuso y actualmente no se refleja en ninguna interfaz.

Duración operativa

Las operaciones tienen un período de duración predecible que se puede mostrar con un ejemplo.

Punto de partida

En un principio, las operaciones no tienen por qué indicar necesariamente algo sobre las revisiones. Estas operaciones tienen valores predeterminados aplicados y, por lo tanto, se consideran como revisión 1 en un nombre de familia que equivale al valor de operationId.

{
    "/{list}/items": {
        "get": {
            "summary": "Get rows",
            "description": "This operation gets a list of items.",
            "operationId": "GetItems"
        }
    }
}

Esto es equivalente a la definición más 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
            }
        }
    }
}

Iniciación de operación

La mayoría de las evoluciones de una API suponen la incorporación de una operación. Nuevos métodos y nuevas revisiones de métodos existentes, por ejemplo. Para iniciar una nueva revisión de forma segura, se ajusta la especificación de OpenAPI de esta manera:

{
    "/{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 tiene un valor de operationId único y se muestra inicialmente en estado de versión preliminar. Observe también que GetItems V1 tiene ahora una visibilidad avanzada, por lo que no se mostrará de forma destacada.

Operación en desuso

A veces, los puntos de entrada V1 existentes permanecen indefinidamente si continúan proporcionando valor y no hay ningún motivo convincente para retirarlos. Sin embargo, muchos puntos de entrada V2 sustituyen voluntariamente al punto de entrada V1. Para hacerlo de forma segura, todo el tráfico debe llegar al cero nominal en la operación original. Una vez que la telemetría confirme esta circunstancia, se puede realizar el siguiente cambio:

{
    "/{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 GetItems V1 ahora está marcado como en desuso. Esta es la transición final para las operaciones en desuso. GetItems V2 ha reemplazado por completo a GetItems V1.

Razones para el control

Hay numerosas razones para tener en cuenta el control de versiones operativo. Ante todo, se asegurará de que los clientes como Azure Logic Apps y Power Automate sigan funcionando correctamente cuando los usuarios integren operaciones de conector en sus flujos de datos. Se deben realizar versiones de las operaciones utilizando el método anterior siempre que:

  • Se agregue una nueva revisión de una operación
  • Una operación existente agregue o quite parámetros
  • Una operación existente cambia significativamente la entrada o la salida

Hablando en sentido estricto

Podría haber casos que pueda resolverlos sin el control de versiones, pero debe tener cuidado al hacerlo y realizar una gran cantidad de pruebas para asegurarse de no pasar por alto los casos extremos en los que los usuarios se podrían interrumpir de forma inesperada. Esta es una breve lista de precauciones para cuando no pueda resolver algo sin el control de versiones:

  • Se agrega una nueva operación.

    Esto no interrumpirá específicamente a los clientes existentes.

  • Se agrega un nuevo parámetro opcional a una operación existente.

    Esto no interrumpiría las llamadas existentes, pero debe prestar una atención especial.

  • Una operación existente cambia sutilmente el comportamiento.

    Esto podría no interrumpir los autores de llamadas existentes en función de la naturaleza del cambio y de aquello de lo que dependan los usuarios. Este caso es el más precario de todos, ya que una diferencia significativa en la aceptación de la entrada, la generación de la salida, el tiempo o el procesamiento podrían afectar al comportamiento de la operación de forma que pueda dificultar determinar el riesgo del cambio.

Es preferible siempre excederse en la cautela e iterar una revisión cuando se realiza cualquier cambio de API no trivial.

Proporcionar comentarios

Agradecemos enormemente los comentarios sobre problemas con nuestra plataforma de conectores o nuevas ideas de características. Para enviar comentarios, vaya a Enviar problemas u obtener ayuda con los conectores y seleccione el tipo de comentario.