VTS-Dashboard-Datenbank

Um ein Dashboard für die kontinuierliche Integration zu unterstützen, das skalierbar, leistungsfähig und flexibel ist, muss das VTS-Dashboard-Backend sorgfältig mit einem umfassenden Verständnis der Datenbankfunktionalität entworfen werden. Google Cloud Datastore ist eine NoSQL-Datenbank, die Transaktions-ACID-Garantien und eventuelle Konsistenz sowie eine starke Konsistenz innerhalb von Entitätsgruppen bietet. Die Struktur unterscheidet sich jedoch stark von SQL-Datenbanken (und sogar Cloud Bigtable). Anstelle von Tabellen, Zeilen und Zellen gibt es Arten, Entitäten und Eigenschaften.

In den folgenden Abschnitten werden die Datenstruktur und die Abfragemuster zum Erstellen eines effektiven Backends für den VTS Dashboard-Webdienst beschrieben.

Entitäten

Die folgenden Entitäten speichern Zusammenfassungen und Ressourcen aus VTS-Testläufen:

  • Testeinheit . Speichert Metadaten zu Testläufen eines bestimmten Tests. Der Schlüssel ist der Testname. Zu seinen Eigenschaften gehören die Anzahl der Fehler, die Anzahl der bestandenen Tests und die Liste der Testfallfehler ab dem Zeitpunkt, an dem die Warnaufträge ihn aktualisieren.
  • Testlauf-Entität . Enthält Metadaten aus Läufen eines bestimmten Tests. Es muss die Zeitstempel für den Start und das Ende des Tests, die Testbuild-ID, die Anzahl der bestandenen und fehlgeschlagenen Testfälle, die Art des Laufs (z. B. vor dem Senden, nach dem Senden oder lokal), eine Liste der Protokollverknüpfungen und den Host speichern Maschinenname und Abdeckungszusammenfassung zählen.
  • Geräteinformationseinheit . Enthält Details zu den während des Testlaufs verwendeten Geräten. Es enthält die Geräte-Build-ID, den Produktnamen, das Build-Ziel, den Zweig und die ABI-Informationen. Dies wird getrennt von der Testlaufentität gespeichert, um Testläufe mit mehreren Geräten eins zu viele zu unterstützen.
  • Profiling Point Run Entity . Fasst die Daten zusammen, die für einen bestimmten Profilierungspunkt innerhalb eines Testlaufs gesammelt wurden. Es beschreibt die Achsenbeschriftungen, den Profilpunktnamen, die Werte, den Typ und den Regressionsmodus der Profildaten.
  • Deckungseinheit . Beschreibt die für eine Datei gesammelten Abdeckungsdaten. Es enthält die Git-Projektinformationen, den Dateipfad und die Liste der Coverage-Zählungen pro Zeile in der Quelldatei.
  • Testfall-Ausführungsentität . Beschreibt das Ergebnis eines bestimmten Testfalls aus einem Testlauf, einschließlich des Testfallnamens und seines Ergebnisses.
  • Benutzer Favoriten Entität . Jedes Benutzerabonnement kann in einer Entität dargestellt werden, die einen Verweis auf den Test und die vom App Engine-Benutzerdienst generierte Benutzer-ID enthält. Dies ermöglicht eine effiziente bidirektionale Abfrage (dh für alle Benutzer, die einen Test abonniert haben, und für alle von einem Benutzer bevorzugten Tests).

Entitätsgruppierung

Jedes Testmodul repräsentiert die Wurzel einer Entitätsgruppe. Testlaufentitäten sind sowohl untergeordnete Elemente dieser Gruppe als auch übergeordnete Elemente für Geräteentitäten, Profilpunktentitäten und Abdeckungsentitäten, die für den jeweiligen Test- und Testlaufvorfahren relevant sind.

Abbildung 1 . Test Entity Abstammung.

Wichtigster Punkt: Beim Entwerfen von Ahnenbeziehungen müssen Sie die Notwendigkeit, effektive und konsistente Abfragemechanismen bereitzustellen, gegen die von der Datenbank erzwungenen Einschränkungen abwägen.

Leistungen

Die Konsistenzanforderung stellt sicher, dass zukünftige Vorgänge die Auswirkungen einer Transaktion erst sehen, wenn sie festgeschrieben wird, und dass Transaktionen in der Vergangenheit für aktuelle Vorgänge sichtbar sind. Im Cloud-Datenspeicher werden durch die Entitätsgruppierung Inseln mit starker Lese- und Schreibkonsistenz innerhalb der Gruppe erstellt. In diesem Fall handelt es sich um alle Testläufe und Daten, die sich auf ein Testmodul beziehen. Dies bietet folgende Vorteile:

  • Lesevorgänge und Aktualisierungen des Testmodulstatus durch Warnaufträge können als atomar behandelt werden
  • Garantierte konsistente Ansicht der Testfallergebnisse innerhalb der Testmodule
  • Schnelleres Abfragen in Ahnenbäumen

Einschränkungen

Es wird nicht empfohlen, schneller als eine Entität pro Sekunde in eine Entitätsgruppe zu schreiben, da einige Schreibvorgänge möglicherweise abgelehnt werden. Solange die Warnaufträge und das Hochladen nicht schneller als ein Schreibvorgang pro Sekunde erfolgen, ist die Struktur solide und garantiert eine starke Konsistenz.

Letztendlich ist die Obergrenze von einem Schreibvorgang pro Testmodul und Sekunde angemessen, da Testläufe in der Regel mindestens eine Minute dauern, einschließlich des Overheads des VTS-Frameworks. Wenn ein Test nicht konsistent gleichzeitig auf mehr als 60 verschiedenen Hosts ausgeführt wird, kann es keinen Schreibengpass geben. Dies wird umso unwahrscheinlicher, als jedes Modul Teil eines Testplans ist, der oft länger als eine Stunde dauert. Anomalien können leicht behoben werden, wenn Hosts die Tests gleichzeitig ausführen, was zu kurzen Schreibausbrüchen auf denselben Hosts führt (z. B. durch Abfangen von Schreibfehlern und erneutes Versuchen).

Überlegungen zur Skalierung

Ein Testlauf muss nicht unbedingt den Test als übergeordnetes Element haben (z. B. könnte er einen anderen Schlüssel verwenden und den Testnamen, die Teststartzeit als Eigenschaften haben). Dies wird jedoch eine starke Konsistenz gegen eine eventuelle Konsistenz austauschen. Beispielsweise sieht der Warnauftrag möglicherweise keine konsistente Momentaufnahme der letzten Testläufe innerhalb eines Testmoduls, was bedeutet, dass der globale Status möglicherweise keine vollständig genaue Darstellung der Sequenz von Testläufen darstellt. Dies kann sich auch auf die Anzeige von Testläufen innerhalb eines einzelnen Testmoduls auswirken. Dies ist möglicherweise nicht unbedingt eine konsistente Momentaufnahme der Laufsequenz. Letztendlich wird der Schnappschuss konsistent sein, es gibt jedoch keine Garantie dafür, dass die aktuellsten Daten vorliegen.

Testfälle

Ein weiterer möglicher Engpass sind große Tests mit vielen Testfällen. Die beiden operativen Einschränkungen sind das maximale Schreibdurchsatz innerhalb einer Entitätsgruppe von einer pro Sekunde sowie eine maximale Transaktionsgröße von 500 Entitäten.

Ein Ansatz wäre, einen Testfall anzugeben, der einen Testlauf als Vorfahr hat (ähnlich wie Speicherabdeckungsdaten, Profildaten und Geräteinformationen gespeichert werden):

Abbildung 2 . Testfälle stammen von Testläufen ab (NICHT EMPFOHLEN).

Dieser Ansatz bietet zwar Atomizität und Konsistenz, schränkt die Tests jedoch stark ein: Wenn eine Transaktion auf 500 Entitäten beschränkt ist, kann ein Test nicht mehr als 498 Testfälle enthalten (vorausgesetzt, es werden keine Daten zur Abdeckung oder Profilerstellung erstellt). Wenn ein Test dies überschreitet, kann eine einzelne Transaktion nicht alle Testergebnisse auf einmal schreiben, und die Aufteilung der Testfälle in separate Transaktionen kann den maximalen Schreibdurchsatz für Entitätsgruppen von einer Iteration pro Sekunde überschreiten. Da diese Lösung ohne Leistungseinbußen nicht gut skaliert werden kann, wird sie nicht empfohlen.

Anstatt die Testfallergebnisse als untergeordnete Elemente des Testlaufs zu speichern, können die Testfälle unabhängig voneinander gespeichert und ihre Schlüssel für den Testlauf bereitgestellt werden (ein Testlauf enthält eine Liste von Kennungen für seine Testfallentitäten):

Abbildung 3 . Testfälle, die unabhängig voneinander gespeichert werden (EMPFOHLEN).

Auf den ersten Blick scheint dies die starke Konsistenzgarantie zu brechen. Wenn der Client jedoch über eine Testlaufentität und eine Liste von Testfallkennungen verfügt, muss keine Abfrage erstellt werden. Stattdessen können die Testfälle direkt anhand ihrer Kennungen abgerufen werden, was immer garantiert konsistent ist. Dieser Ansatz verringert die Beschränkung der Anzahl von Testfällen, die ein Testlauf haben kann, erheblich, während eine starke Konsistenz erreicht wird, ohne übermäßiges Schreiben innerhalb einer Entitätsgruppe zu bedrohen.

Datenzugriffsmuster

Das VTS-Dashboard verwendet die folgenden Datenzugriffsmuster:

  • Benutzerfavoriten . Kann mithilfe eines Gleichheitsfilters für Benutzerfavoriten-Entitäten mit dem bestimmten App Engine-Benutzerobjekt als Eigenschaft abgefragt werden.
  • Testliste . Einfache Abfrage von Testentitäten. Um die Bandbreite für das Rendern der Startseite zu verringern, kann eine Projektion für das Bestehen und Nichtbestehen von Zählungen verwendet werden, um die möglicherweise lange Liste fehlgeschlagener Testfall-IDs und anderer Metadaten, die von den Warnaufträgen verwendet werden, wegzulassen.
  • Testläufe . Das Abfragen von Testlaufentitäten erfordert eine Sortierung des Schlüssels (Zeitstempel) und eine mögliche Filterung der Testlaufeigenschaften wie Build-ID, Anzahl der bestandenen Punkte usw. Durch Ausführen einer Vorgängerabfrage mit einem Testentitätsschlüssel ist der Lesevorgang stark konsistent. Zu diesem Zeitpunkt können alle Testfallergebnisse mithilfe der Liste der IDs abgerufen werden, die in einer Testlaufeigenschaft gespeichert sind. Dies ist auch aufgrund der Art der Datenspeicher-Abrufvorgänge garantiert ein stark konsistentes Ergebnis.
  • Profilierungs- und Abdeckungsdaten . Das Abfragen von Profilierungs- oder Abdeckungsdaten, die einem Test zugeordnet sind, kann durchgeführt werden, ohne dass auch andere Testlaufdaten abgerufen werden müssen (z. B. andere Profilierungs- / Abdeckungsdaten, Testfalldaten usw.). Bei einer Vorfahrenabfrage mit den Entitätstasten Testtest und Testlauf werden alle während des Testlaufs aufgezeichneten Profilierungspunkte abgerufen. Durch Filtern auch nach dem Profilierungspunktnamen oder Dateinamen kann eine einzelne Profilierungs- oder Abdeckungsentität abgerufen werden. Aufgrund der Art der Ahnenabfragen ist diese Operation stark konsistent.

Ausführliche Informationen zur Benutzeroberfläche und Screenshots dieser Datenmuster in Aktion finden Sie unter VTS-Dashboard-Benutzeroberfläche .