Base de datos del panel de VTS

Para admitir un panel de integración continua que sea escalable, eficiente y flexible, el backend del panel de VTS debe diseñarse con cuidado y tener un conocimiento sólido de la funcionalidad de la base de datos. Cloud Datastore de Google Cloud es una base de datos NoSQL que ofrece garantías ACID transaccionales y coherencia eventual, así como coherencia sólida dentro de los grupos de entidades. Sin embargo, la estructura es muy diferente a la de las bases de datos SQL (e incluso a la de Cloud Bigtable). En lugar de tablas, filas y celdas, hay tipos, entidades y propiedades.

En las siguientes secciones, se describen la estructura de datos y los patrones de consulta para crear un backend eficaz para el servicio web de VTS Dashboard.

Entidades

Las siguientes entidades almacenan resúmenes y recursos de las ejecuciones de prueba de VTS:

  • Entidad de prueba. Almacena metadatos sobre las ejecuciones de prueba de una prueba en particular. Su clave es el nombre de la prueba, y sus propiedades incluyen el recuento de fallas, el recuento de pruebas aprobadas y la lista de fallas de casos de prueba desde que las tareas de alerta la actualizan.
  • Entidad de ejecución de prueba. Contiene metadatos de las ejecuciones de una prueba en particular. Debe almacenar las marcas de tiempo de inicio y finalización de la prueba, el ID de compilación de la prueba, la cantidad de casos de prueba aprobados y con errores, el tipo de ejecución (p.ej., antes del envío, después del envío o local), una lista de vínculos de registro, el nombre de la máquina anfitrión y los recuentos de resumen de cobertura.
  • Entidad de información del dispositivo. Contiene detalles sobre los dispositivos que se usaron durante la ejecución de la prueba. Incluye el ID de compilación del dispositivo, el nombre del producto, el objetivo de compilación, la rama y la información de ABI. Se almacena por separado de la entidad de ejecución de prueba para admitir ejecuciones de prueba en varios dispositivos de forma uno a muchos.
  • Entidad de ejecución de punto de perfil. Resume los datos recopilados para un punto de perfil específico dentro de una ejecución de prueba. Describe las etiquetas del eje, el nombre del punto de perfil, los valores, el tipo y el modo de regresión de los datos de perfil.
  • Entidad de cobertura. Describe los datos de cobertura recopilados para un archivo. Contiene la información del proyecto de Git, la ruta de acceso del archivo y la lista de recuentos de cobertura por línea en el archivo fuente.
  • Entidad de ejecución de casos de prueba. Describe el resultado de un caso de prueba particular de una ejecución de prueba, incluido el nombre del caso de prueba y su resultado.
  • Entidad de favoritos del usuario. Cada suscripción del usuario se puede representar en una entidad que contiene una referencia a la prueba y el ID del usuario generado desde el servicio de usuarios de App Engine. Esto permite realizar consultas bidireccionales eficientes (es decir, para todos los usuarios que se suscribieron a una prueba y para todas las pruebas que un usuario marcó como favoritas).

Agrupación de entidades

Cada módulo de prueba representa la raíz de un grupo de entidades. Las entidades de ejecución de prueba son elementos secundarios de este grupo y elementos superiores de las entidades de dispositivo, las entidades de punto de perfilado y las entidades de cobertura relevantes para la prueba y el ancestro de ejecución de prueba respectivos.

Figura 1. Prueba la ascendencia de la entidad.

Punto clave: Cuando diseñes relaciones de ascendencia, debes equilibrar la necesidad de proporcionar mecanismos de consulta eficaces y coherentes con las limitaciones que impone la base de datos.

Beneficios

El requisito de coherencia garantiza que las operaciones futuras no vean los efectos de una transacción hasta que se confirme y que las transacciones anteriores sean visibles para las operaciones actuales. En Cloud Datastore, el agrupamiento de entidades crea islas de coherencia sólida de lectura y escritura dentro del grupo, que en este caso son todas las ejecuciones de prueba y los datos relacionados con un módulo de prueba. Esto ofrece los siguientes beneficios:

  • Las operaciones de lectura y actualización para probar el estado del módulo por trabajos de alerta se pueden tratar como atómicas.
  • Vista coherente garantizada de los resultados de los casos de prueba dentro de los módulos de prueba
  • Consultas más rápidas en los árboles genealógicos

Limitaciones

No se recomienda escribir en un grupo de entidades a una velocidad superior a una entidad por segundo, ya que es posible que se rechacen algunas operaciones de escritura. Siempre que las tareas de alerta y la carga no se realicen a una velocidad superior a una operación de escritura por segundo, la estructura es sólida y garantiza una coherencia sólida.

En última instancia, el límite de una operación de escritura por módulo de prueba por segundo es razonable, ya que las ejecuciones de prueba suelen tardar al menos un minuto, incluida la sobrecarga del framework de VTS. A menos que una prueba se ejecute de forma coherente y simultánea en más de 60 hosts diferentes, no puede haber un cuello de botella de escritura. Esto se vuelve aún más improbable, ya que cada módulo forma parte de un plan de prueba que, a menudo, tarda más de una hora. Las anomalías se pueden controlar fácilmente si los hosts ejecutan las pruebas al mismo tiempo, lo que genera ráfagas cortas de operaciones de escritura en los mismos hosts (p.ej., capturando errores de escritura y volviendo a intentarlo).

Consideraciones sobre el escalamiento

Una ejecución de prueba no necesariamente debe tener la prueba como elemento superior (p. ej., podría tomar alguna otra clave y tener el nombre de la prueba y la hora de inicio de la prueba como propiedades). Sin embargo, esto intercambiará la coherencia estricta por la coherencia eventual. Por ejemplo, es posible que el trabajo de alerta no vea una instantánea mutuamente coherente de las ejecuciones de prueba más recientes dentro de un módulo de prueba, lo que significa que el estado global puede no representar una representación completamente precisa de la secuencia de ejecuciones de prueba. Esto también puede afectar la visualización de las ejecuciones de prueba dentro de un solo módulo de prueba, que no necesariamente es una instantánea coherente de la secuencia de ejecución. Con el tiempo, la instantánea será coherente, pero no hay garantías de que los datos sean los más recientes.

Casos de prueba

Otro cuello de botella potencial son las pruebas grandes con muchos casos de prueba. Las dos restricciones operativas son la capacidad de procesamiento de escritura máxima dentro de un grupo de entidades de una por segundo, junto con un tamaño de transacción máximo de 500 entidades.

Un enfoque sería especificar un caso de prueba que tenga una ejecución de prueba como ancestro (similar a la forma en que se almacenan los datos de cobertura, los datos de perfil y la información del dispositivo):

Figura 2: Los casos de prueba provienen de las ejecuciones de prueba (NO RECOMENDABLE).

Si bien este enfoque ofrece atomicidad y coherencia, impone limitaciones estrictas a las pruebas: si una transacción se limita a 500 entidades, una prueba no puede tener más de 498 casos de prueba (suponiendo que no haya datos de cobertura ni perfiles). Si una prueba superara este valor, una sola transacción no podría escribir todos los resultados del caso de prueba a la vez, y dividir los casos de prueba en transacciones separadas podría exceder la capacidad de procesamiento de escritura máxima del grupo de entidades de una iteración por segundo. Como esta solución no se escalará bien sin sacrificar el rendimiento, no se recomienda.

Sin embargo, en lugar de almacenar los resultados de los casos de prueba como elementos secundarios de la ejecución de prueba, los casos de prueba se pueden almacenar de forma independiente y sus claves se pueden proporcionar a la ejecución de prueba (una ejecución de prueba contiene una lista de identificadores para sus entidades de casos de prueba):

Figura 3: Casos de prueba almacenados de forma independiente (RECOMENDADO).

A primera vista, puede parecer que se incumple la garantía de coherencia sólida. Sin embargo, si el cliente tiene una entidad de ejecución de prueba y una lista de identificadores de casos de prueba, no es necesario que construya una consulta. En su lugar, puede obtener directamente los casos de prueba por sus identificadores, lo que siempre garantiza que sean coherentes. Este enfoque alivia en gran medida la restricción de la cantidad de casos de prueba que puede tener una ejecución de prueba y, al mismo tiempo, obtiene una coherencia sólida sin amenazar la escritura excesiva dentro de un grupo de entidades.

Patrones de acceso a los datos

El panel de VTS usa los siguientes patrones de acceso a los datos:

  • Favoritos del usuario: Se puede consultar con un filtro de igualdad en las entidades de favoritos del usuario que tienen el objeto de usuario de App Engine en particular como propiedad.
  • Ficha de prueba. Búsqueda simple de entidades de prueba. Para reducir la amplitud de banda para renderizar la página principal, se puede usar una proyección en los recuentos de aprobación y rechazo para omitir la lista potencialmente larga de IDs de casos de prueba fallidos y otros metadatos que usan las tareas de alerta.
  • Ejecuciones de prueba: La consulta de entidades de ejecución de prueba requiere una clasificación en la clave (marca de tiempo) y un posible filtrado en las propiedades de ejecución de prueba, como el ID de compilación, el recuento de aprobaciones, etcétera. Cuando se realiza una consulta de ancestros con una clave de entidad de prueba, la lectura es muy coherente. En este punto, todos los resultados del caso de prueba se pueden recuperar con la lista de IDs almacenados en una propiedad de ejecución de prueba. Esto también garantiza que sea un resultado muy coherente debido a la naturaleza de las operaciones de recuperación del almacén de datos.
  • Datos de perfiles y cobertura. Las consultas de datos de generación de perfiles o cobertura asociados con una prueba se pueden realizar sin recuperar ningún otro dato de ejecución de prueba (como otros datos de generación de perfiles o cobertura, datos de casos de prueba, etc.). Una consulta de ancestro que use las claves de entidad de prueba y ejecución de prueba recuperará todos los puntos de perfilización registrados durante la ejecución de prueba. Si también se filtra por el nombre o el nombre de archivo del punto de perfilización, se puede recuperar una sola entidad de perfilización o cobertura. Debido a la naturaleza de las consultas principales, esta operación es muy coherente.

Para obtener detalles sobre la IU y capturas de pantalla de estos patrones de datos en acción, consulta IU del panel de VTS.