El día de hoy veremos cómo podemos manejar errores adecuadamente en Power Automate, incluyendo los errores más esperados por parte de APIs y conectores, así como también veremos cómo lidiar con problemas de rendimiento (throttling).
La respuesta de Power Automate por defecto frente a errores de conectores es bastante simple, ya que simplemente se sale del flujo de trabajo en ese momento y graba toda la secuencia como un fallo. En la mayoría de casos esto es lo que podríamos necesitar, pero algunas veces es necesario manejar un error por cuenta propia. O incluso si queremos ignorar el error y continuar, parecido al método try-catch usado en muchos lenguajes de programación.
Errores de consulta de objetos Sharepoint
Por ejemplo, antes de enviar un registro, puede que queramos revisar si ya existe. De ser así, entonces haremos una actualización; de no existir, entonces lo crearemos. Al llamar al servicio web RESTful para recuperar un registro por su ID única, y de no poder ser encontrado, el servicio seguramente nos regresará un código de estado 404. En Flow, un 404 es considerado un error y por lo tanto el flujo de trabajo fallará y terminará en ese punto a menos que implementemos manejo de error adicional. En este caso, un 404 no debería ser considerado un error por así decirlo, pues es una respuesta legítima que nos está diciendo algo, lo cual querremos manejar para poder continuar.
Para manejar un error en Flow, tenemos que configurar primero el comportamiento Run After de la Acción que queremos que pase luego del error. Podemos configurar el comportamiento Run After al darle click a los tres puntos (…) en la barra de título de una Acción y escogiendo «Configure run after».
El ajuste por defecto para cada acción es correr solo si la acción previa fue exitosa. Si la acción previa genera un error, entonces el flujo de trabajo saldrá andes de ejecutar la acción siguiente. Para manejar un error entonces necesitaremos hacer que la acción siguiente corra aun si la acción previa fallo, lo cual podemos habilitar con la opción «has failed».
En la imagen de arriba tenemos la acción GetItem de SharePoint seguida de una acción Switch. Esta acción Switch está configurada para correr independiente de si la acción de SharePoint falla o tiene exito.
MANEJANDO CÓDIGOS DE ESTADO
Uno de los mejores aspectos sobre los Conectores en toda la Power Platform[?] es que son creados con estándares de servicio web. Cada conector es básicamente una envoltura sobre un servicio web nativo o de terceros y toma ventaja de las peticiones HTTP para comunicarse. Dado que cada petición a través de un conector es solo una llamada de servicio web, entonces deberíamos poder obtener la respuesta del código de estado, los encabezados que el servidor envió de vuelta y el cuerpo de la respuesta.
Power Automate nos expone todo esto por medio de Expressions, las cuales vienen integradas usando el Lenguaje de Definición de Flujo de Trabajo de Azure Logic Apps. Usando la función outputs() en una Expresión, seremos capaces de obtener la respuesta HTTP completa de una acción conectora. Si revisamos la documentación para esta función veremos una respuesta JSON de muestra:
{
"statusCode": 200,
"headers": {
"Transfer-Encoding": "chunked",
"Vary": "Origin,Accept-Encoding",
"X-SharePointHealthScore": "3",
"X-MS-SPConnector": "1",
"X-SP-SERVERSTATE": "ReadOnly=0",
"DATASERVICEVERSION": "3.0",
"SPClientServiceRequestDuration": "138",
"SPRequestGuid": "55e64f49-972f-4177-a339-6058104ca568",
"request-id": "55e64f49-972f-4177-a339-6058104ca568",
"MS-CV": "SU/mVS+Xd0GjOWBYEEylaA.0",
"Strict-Transport-Security": "max-age=31536000",
"X-FRAME-OPTIONS": "SAMEORIGIN",
"Content-Security-Policy": "frame-ancestors 'self' teams.microsoft.com *.teams.microsoft.com *.skype.com *.teams.microsoft.us local.teams.office.com *.powerapps.com *.yammer.com *.officeapps.live.com *.office.com *.stream.azure-test.net *.microsoftstream.com *.dynamics.com;",
"MicrosoftSharePointTeamServices": "16.0.0.21827",
"X-Content-Type-Options": "nosniff",
"X-MS-InvokeApp": "1; RequireReadOnly",
"Timing-Allow-Origin": "*",
"x-ms-apihub-cached-response": "false",
"Cache-Control": "max-age=0, private",
"Date": "Thu, 18 Nov 2021 03:42:07 GMT",
"P3P": "CP=\"ALL IND DSP COR ADM CONo CUR CUSo IVAo IVDo PSA PSD TAI TELo OUR SAMo CNT COM INT NAV ONL PHY PRE PUR UNI\"",
"X-AspNet-Version": "4.0.30319",
"X-Powered-By": "ASP.NET",
"Content-Type": "application/json; charset=utf-8",
"Expires": "Wed, 03 Nov 2021 02:42:08 GMT",
"Last-Modified": "Thu, 18 Nov 2021 03:42:08 GMT",
"Content-Length": "3154"
},
"body": {
"@odata.etag": "\"11\"",
"ItemInternalId": "5",
"ID": 5,
"Title": "Sebastian Vallejo",
"Mails": "svallejo@excelcute.com",
"vegetariano": "No",
"talla": "M",
"Usuarios": [
{
"@odata.type": "#Microsoft.Azure.Connectors.SharePoint.SPListExpandedUser",
"Claims": "i:0#.f|membership|admin@kbflux.com",
"DisplayName": "SEBASTIAN VALLEJO",
"Email": "admin@kbflux.com",
"Picture": "https://cutexcel.sharepoint.com/sites/TestSite/_layouts/15/UserPhoto.aspx?Size=L&AccountName=admin@kbflux.com",
"Department": "Proyectos",
"JobTitle": "Gerente de Desarrollos"
},
{
"@odata.type": "#Microsoft.Azure.Connectors.SharePoint.SPListExpandedUser",
"Claims": "i:0#.f|membership|poliver@kbflux.com",
"DisplayName": "SEBASTIAN VALLEJO",
"Email": "poliver@kbflux.com",
"Picture": "https://cutexcel.sharepoint.com/sites/TestSite/_layouts/15/UserPhoto.aspx?Size=L&AccountName=poliver@kbflux.com",
"Department": "Marketing",
"JobTitle": "Mordidista Senior"
}
],
"Usuarios@odata.type": "#Collection(Microsoft.Azure.Connectors.SharePoint.SPListExpandedUser)",
"Usuarios#Claims": [
"i:0#.f|membership|admin@kbflux.com",
"i:0#.f|membership|poliver@kbflux.com"
],
"Usuarios#Claims@odata.type": "#Collection(String)",
"Author": [
{
"@odata.type": "#Microsoft.Azure.Connectors.SharePoint.SPListExpandedUser",
"Claims": "i:0#.f|membership|admin@kbflux.com",
"DisplayName": "SEBASTIAN VALLEJO",
"Email": "admin@kbflux.com",
"Picture": "https://cutexcel.sharepoint.com/sites/TestSite/_layouts/15/UserPhoto.aspx?Size=L&AccountName=admin@kbflux.com",
"Department": "Proyectos",
"JobTitle": "Gerente de Desarrollos"
},
{
"@odata.type": "#Microsoft.Azure.Connectors.SharePoint.SPListExpandedUser",
"Claims": "i:0#.f|membership|poliver@kbflux.com",
"DisplayName": "SEBASTIAN VALLEJO",
"Email": "poliver@kbflux.com",
"Picture": "https://cutexcel.sharepoint.com/sites/TestSite/_layouts/15/UserPhoto.aspx?Size=L&AccountName=poliver@kbflux.com",
"Department": "Marketing",
"JobTitle": "Mordidista Senior"
}
],
"Author@odata.type": "#Collection(Microsoft.Azure.Connectors.SharePoint.SPListExpandedUser)",
"Author#Claims": [
"i:0#.f|membership|admin@kbflux.com",
"i:0#.f|membership|poliver@kbflux.com"
],
"Author#Claims@odata.type": "#Collection(String)",
"Modified": "2021-10-27T02:25:29Z",
"Created": "2021-09-08T15:23:24Z",
"Editor": {
"@odata.type": "#Microsoft.Azure.Connectors.SharePoint.SPListExpandedUser",
"Claims": "i:0#.f|membership|admin@kbflux.com",
"DisplayName": "SEBASTIAN VALLEJO",
"Email": "admin@kbflux.com",
"Picture": "https://cutexcel.sharepoint.com/sites/TestSite/_layouts/15/UserPhoto.aspx?Size=L&AccountName=admin@kbflux.com",
"Department": "Proyectos",
"JobTitle": "Gerente de Desarrollos"
},
"Editor#Claims": "i:0#.f|membership|admin@kbflux.com",
"{Identifier}": "Lists%252fKickOffs%252f5_.000",
"{IsFolder}": false,
"{Thumbnail}": {
"Large": null,
"Medium": null,
"Small": null
},
"{Link}": "https://cutexcel.sharepoint.com/sites/TestSite/_layouts/15/listform.aspx?PageType=4&ListId=296a0093%2Df8fe%2D446a%2Daf29%2Df7e9b7869d71&ID=5&ContentTypeID=0x01000884B797BCF25A45A960B6A50D3D931D0029EE54B4D3FDBE448019C0130680636D",
"{Name}": "Sebastian Vallejo",
"{FilenameWithExtension}": "Sebastian Vallejo",
"{Path}": "Lists/KickOffs/",
"{FullPath}": "Lists/KickOffs/5_.000",
"{HasAttachments}": true,
"{VersionNumber}": "11.0"
}
}
Nomenclantura para el StatusCode
Notaremos la colección de encabezados a la que tenemos acceso, el cuerpo de la respuesta y el statusCode. Usando esto, podemos escribir las Condiciones que revisan el código de estado de regreso y manejar los errores de manera adecuada. La síntaxis para obtener el Código de Estado HTTP en una Expresión es el siguiente:
outputs('your_action_name').statusCode
El nombre de nuestra acción necesita estar entre apóstrofes (‘) y si tenemos espacios en el nombre de nuestra Acción (lo cual es normal), tendremos que reemplazarlos con guiones bajos (_) en su lugar.
Un buen patrón para manejo de errores es usar una acción Switch y usar la fórmula de arriba en el campo «On». Vamos a darle click en este campo y luego click en la pestaña Expression. Vamos a escribir esta fórmula y daremos click en el botón OK para insertar nuestra expresión:
Luego de esto podemos crear un Caso para cada código de error esperado. Por ejemplo:
- Para el Caso ‘200’ podemos entonces Actualizar el objeto
- Para el Caso ‘404’ crearemos un nuevo objeto
- Y para el Caso ‘500’ terminaremos el flujo de trabajo con un mensaje de error (porque algo malo que no puede remediarse seguramente ocurrió).
A continuación podemos ver una imagen de un Flujo en donde estoy buscando un objeto específico por ID de SharePoint y un Switch que corra si esa acción falla o tiene éxito y que luego procese 200, 404 y lo que sea en casos separados:
Y aquí lo podemos ver corriendo con un código de fallo 404 (busqué un objeto con ID 256, el cual no existe). Veremos cómo es que corrió con el caso 404 en el Switch:
MANEJANDO RESPUESTAS DE CUELLO DE BOTELLA (THROTTLING)
Cuando experimentamos problemas de rendimiento (throttling) por un servicio web, usualmente nos regresará en código de estado 429. Estos ya son manejados por Power Automate, por lo que no tenemos que manejarlos nosotros mismos con ‘lógica de reintento de loop de cosecha propia’ (home grown looping retry logic). Power Automate ya tiene mecanismos integrados que manejan estos cuellos de botella (throttling), incluyendo reintentos automáticos y retrocesos exponenciales.
Podemos configurar la respuesta al comportamiento de cuello de botella (throttling) al darle click a los tres puntos (…) en la barra de título de la Acción y eligiendo Ajustes.
Casi al final de la página, podemos encontrar los ajustes para la Política de Reintento. Por defecto tenemos un reintento Exponencial con dos intentos. Podemos configurar un # total de reintentos, método de retroceso (ya sea fijo o exponencial) e Intervalos. Notaremos que 429 (muchas peticiones), 408 (se agotó el tiempo de espera de la petición) y 5XX (error interno del servidor) son manejados de esta forma para ti.
Esto sería el most-to-know de como manejar errores con Power Automate y el statusCode. Cualquier duda, nos leemos abajo.