[current_results] Implement data store for current results in memory
Change-Id: I4d49c36ccadf76cccc756aad30bda453aac4f6b2
Reviewed-on: https://dart-review.googlesource.com/c/dart_ci/+/150483
Commit-Queue: William Hesse <whesse@google.com>
Reviewed-by: Alexander Thomas <athom@google.com>
diff --git a/current_results/bin/server.dart b/current_results/bin/server.dart
index 85f58cd..15afb63 100644
--- a/current_results/bin/server.dart
+++ b/current_results/bin/server.dart
@@ -5,28 +5,23 @@
import 'dart:convert';
import 'dart:io';
-import 'package:shelf/shelf.dart' as shelf;
-import 'package:shelf/shelf_io.dart' as io;
import 'package:gcloud/storage.dart';
import 'package:googleapis_auth/auth_io.dart';
import 'package:http/http.dart';
+import 'package:pool/pool.dart';
-import '../gen/result.pbserver.dart';
+import 'package:current_results/src/slice.dart';
// For Google Cloud Run, set _hostname to '0.0.0.0'.
var _hostname = '0.0.0.0';
Future initialized;
+final current = Slice();
+
void main(List<String> args) async {
initialized = loadData();
- var port = int.tryParse(Platform.environment['PORT'] ?? '8080');
- var handler = const shelf.Pipeline()
- .addMiddleware(shelf.logRequests())
- .addHandler(_echoRequest);
-
- var server = await io.serve(handler, _hostname, port);
- print('Serving at http://${server.address.host}:${server.port}');
+ var port = int.tryParse(Platform.environment['PORT'] ?? '8081');
}
Future<void> loadData() async {
@@ -35,78 +30,33 @@
final storage = Storage(client, 'dart-ci-staging');
final bucket = storage.bucket('dart-test-results');
- await for (final configuration
- in bucket.list(prefix: 'configuration/master/')) {
- if (configuration.isDirectory) {
- try {
- final revision = await bucket
- .read('${configuration.name}latest')
- .transform(ascii.decoder)
- .transform(LineSplitter())
- .single;
- final lines = await bucket
- .read('${configuration.name}$revision/results.json')
- .transform(utf8.decoder)
- .transform(LineSplitter());
- await for (final line in lines) {
- final result = Result()
- ..mergeFromProto3Json(json.decode(line),
- supportNamesWithUnderscores: true);
- data.add(CurrentResult.fromResult(result));
- }
- } catch (e) {
- print('Error reading results from ${configuration.name}:');
- print(e);
- }
+ final configurationDirectories = await bucket
+ .list(prefix: 'configuration/master/')
+ .where((entry) => entry.isDirectory)
+ .toList();
+ await Pool(10).forEach(configurationDirectories, (configuration) async {
+ print(configuration.name);
+ try {
+ final revision = await bucket
+ .read('${configuration.name}latest')
+ .transform(ascii.decoder)
+ .transform(LineSplitter())
+ .single;
+ final results = await bucket
+ .read('${configuration.name}$revision/results.json')
+ .transform(utf8.decoder)
+ .transform(LineSplitter())
+ .toList();
+ current.add(results);
+ } catch (e) {
+ print('Error reading results from ${configuration.name}:');
+ print(e);
}
- }
- print("Records ingested: ${data.length}");
-}
-
-class CurrentResult {
- final String name;
- final String configuration;
- final String commitHash;
- final String result;
- final bool flaky;
- final String expected;
- final Duration time;
-
- CurrentResult(this.name, this.configuration, this.commitHash, this.result,
- this.flaky, this.expected, this.time);
-
- CurrentResult.fromResult(Result other)
- : this(
- unique(other.name),
- unique(other.configuration),
- unique(other.commitHash),
- unique(other.result),
- other.flaky,
- unique(other.expected),
- Duration(milliseconds: other.timeMs));
-}
-
-final set = Set<String>();
-final data = <CurrentResult>[];
-
-String unique(String string) =>
- set.lookup(string) ?? (set.add(string) ? string : string);
-
-Map<String, dynamic> canonicalize(Map<String, dynamic> map) => {
- for (final entry in map.entries)
- unique(entry.key):
- (entry.value is String) ? unique(entry.value) : entry.value
- };
-
-Future<shelf.Response> _echoRequest(shelf.Request request) async {
- print("Request ${request.url} received");
- await initialized;
- return shelf.Response.ok('Number of results: ${data.length}\n'
- 'Number of unique strings ${set.length}');
+ }).drain();
+ print("Records ingested: ${current.size}");
}
Future<AuthClient> getAuthenticatedClient() async {
- AuthClient result;
final localCredentials =
Platform.environment['GOOGLE_APPLICATION_CREDENTIALS'];
if (localCredentials == null) {
diff --git a/current_results/gen/result.pb.dart b/current_results/gen/result.pb.dart
deleted file mode 100644
index 09efbf4..0000000
--- a/current_results/gen/result.pb.dart
+++ /dev/null
@@ -1,150 +0,0 @@
-///
-// Generated code. Do not modify.
-// source: result.proto
-///
-// ignore_for_file: camel_case_types,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name
-
-import 'dart:core' as $core show bool, Deprecated, double, int, List, Map, override, pragma, String;
-
-import 'package:protobuf/protobuf.dart' as $pb;
-
-class Result extends $pb.GeneratedMessage {
- static final $pb.BuilderInfo _i = $pb.BuilderInfo('Result', package: const $pb.PackageName('dart_ci'))
- ..aOS(1, 'name')
- ..aOS(2, 'configuration')
- ..a<$core.int>(3, 'timeMs', $pb.PbFieldType.O3)
- ..aOS(4, 'result')
- ..aOS(5, 'expected')
- ..aOB(6, 'matches')
- ..aOS(7, 'botName')
- ..aOS(8, 'commitHash')
- ..aOS(9, 'buildNumber')
- ..aOS(10, 'builderName')
- ..aOB(11, 'flaky')
- ..aOB(12, 'previousFlaky')
- ..aOS(13, 'previousCommitHash')
- ..a<$core.int>(14, 'previousCommitTime', $pb.PbFieldType.O3)
- ..aOS(15, 'previousBuildNumber')
- ..aOS(16, 'previousResult')
- ..aOB(17, 'changed')
- ..aOS(100, 'suite')
- ..aOS(101, 'testName')
- ..a<$core.int>(102, 'commitTime', $pb.PbFieldType.O3)
- ..hasRequiredFields = false
- ;
-
- Result._() : super();
- factory Result() => create();
- factory Result.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
- factory Result.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
- Result clone() => Result()..mergeFromMessage(this);
- Result copyWith(void Function(Result) updates) => super.copyWith((message) => updates(message as Result));
- $pb.BuilderInfo get info_ => _i;
- @$core.pragma('dart2js:noInline')
- static Result create() => Result._();
- Result createEmptyInstance() => create();
- static $pb.PbList<Result> createRepeated() => $pb.PbList<Result>();
- static Result getDefault() => _defaultInstance ??= create()..freeze();
- static Result _defaultInstance;
-
- $core.String get name => $_getS(0, '');
- set name($core.String v) { $_setString(0, v); }
- $core.bool hasName() => $_has(0);
- void clearName() => clearField(1);
-
- $core.String get configuration => $_getS(1, '');
- set configuration($core.String v) { $_setString(1, v); }
- $core.bool hasConfiguration() => $_has(1);
- void clearConfiguration() => clearField(2);
-
- $core.int get timeMs => $_get(2, 0);
- set timeMs($core.int v) { $_setSignedInt32(2, v); }
- $core.bool hasTimeMs() => $_has(2);
- void clearTimeMs() => clearField(3);
-
- $core.String get result => $_getS(3, '');
- set result($core.String v) { $_setString(3, v); }
- $core.bool hasResult() => $_has(3);
- void clearResult() => clearField(4);
-
- $core.String get expected => $_getS(4, '');
- set expected($core.String v) { $_setString(4, v); }
- $core.bool hasExpected() => $_has(4);
- void clearExpected() => clearField(5);
-
- $core.bool get matches => $_get(5, false);
- set matches($core.bool v) { $_setBool(5, v); }
- $core.bool hasMatches() => $_has(5);
- void clearMatches() => clearField(6);
-
- $core.String get botName => $_getS(6, '');
- set botName($core.String v) { $_setString(6, v); }
- $core.bool hasBotName() => $_has(6);
- void clearBotName() => clearField(7);
-
- $core.String get commitHash => $_getS(7, '');
- set commitHash($core.String v) { $_setString(7, v); }
- $core.bool hasCommitHash() => $_has(7);
- void clearCommitHash() => clearField(8);
-
- $core.String get buildNumber => $_getS(8, '');
- set buildNumber($core.String v) { $_setString(8, v); }
- $core.bool hasBuildNumber() => $_has(8);
- void clearBuildNumber() => clearField(9);
-
- $core.String get builderName => $_getS(9, '');
- set builderName($core.String v) { $_setString(9, v); }
- $core.bool hasBuilderName() => $_has(9);
- void clearBuilderName() => clearField(10);
-
- $core.bool get flaky => $_get(10, false);
- set flaky($core.bool v) { $_setBool(10, v); }
- $core.bool hasFlaky() => $_has(10);
- void clearFlaky() => clearField(11);
-
- $core.bool get previousFlaky => $_get(11, false);
- set previousFlaky($core.bool v) { $_setBool(11, v); }
- $core.bool hasPreviousFlaky() => $_has(11);
- void clearPreviousFlaky() => clearField(12);
-
- $core.String get previousCommitHash => $_getS(12, '');
- set previousCommitHash($core.String v) { $_setString(12, v); }
- $core.bool hasPreviousCommitHash() => $_has(12);
- void clearPreviousCommitHash() => clearField(13);
-
- $core.int get previousCommitTime => $_get(13, 0);
- set previousCommitTime($core.int v) { $_setSignedInt32(13, v); }
- $core.bool hasPreviousCommitTime() => $_has(13);
- void clearPreviousCommitTime() => clearField(14);
-
- $core.String get previousBuildNumber => $_getS(14, '');
- set previousBuildNumber($core.String v) { $_setString(14, v); }
- $core.bool hasPreviousBuildNumber() => $_has(14);
- void clearPreviousBuildNumber() => clearField(15);
-
- $core.String get previousResult => $_getS(15, '');
- set previousResult($core.String v) { $_setString(15, v); }
- $core.bool hasPreviousResult() => $_has(15);
- void clearPreviousResult() => clearField(16);
-
- $core.bool get changed => $_get(16, false);
- set changed($core.bool v) { $_setBool(16, v); }
- $core.bool hasChanged() => $_has(16);
- void clearChanged() => clearField(17);
-
- $core.String get suite => $_getS(17, '');
- set suite($core.String v) { $_setString(17, v); }
- $core.bool hasSuite() => $_has(17);
- void clearSuite() => clearField(100);
-
- $core.String get testName => $_getS(18, '');
- set testName($core.String v) { $_setString(18, v); }
- $core.bool hasTestName() => $_has(18);
- void clearTestName() => clearField(101);
-
- $core.int get commitTime => $_get(19, 0);
- set commitTime($core.int v) { $_setSignedInt32(19, v); }
- $core.bool hasCommitTime() => $_has(19);
- void clearCommitTime() => clearField(102);
-}
-
diff --git a/current_results/lib/src/generated/result.pb.dart b/current_results/lib/src/generated/result.pb.dart
new file mode 100644
index 0000000..7e3ec61
--- /dev/null
+++ b/current_results/lib/src/generated/result.pb.dart
@@ -0,0 +1,215 @@
+///
+// Generated code. Do not modify.
+// source: result.proto
+///
+// ignore_for_file: camel_case_types,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name
+
+import 'dart:core' as $core
+ show bool, Deprecated, double, int, List, Map, override, pragma, String;
+
+import 'package:protobuf/protobuf.dart' as $pb;
+
+class Result extends $pb.GeneratedMessage {
+ static final $pb.BuilderInfo _i =
+ $pb.BuilderInfo('Result', package: const $pb.PackageName('dart_ci'))
+ ..aOS(1, 'name')
+ ..aOS(2, 'configuration')
+ ..a<$core.int>(3, 'timeMs', $pb.PbFieldType.O3)
+ ..aOS(4, 'result')
+ ..aOS(5, 'expected')
+ ..aOB(6, 'matches')
+ ..aOS(7, 'botName')
+ ..aOS(8, 'commitHash')
+ ..aOS(9, 'buildNumber')
+ ..aOS(10, 'builderName')
+ ..aOB(11, 'flaky')
+ ..aOB(12, 'previousFlaky')
+ ..aOS(13, 'previousCommitHash')
+ ..a<$core.int>(14, 'previousCommitTime', $pb.PbFieldType.O3)
+ ..aOS(15, 'previousBuildNumber')
+ ..aOS(16, 'previousResult')
+ ..aOB(17, 'changed')
+ ..aOS(100, 'suite')
+ ..aOS(101, 'testName')
+ ..a<$core.int>(102, 'commitTime', $pb.PbFieldType.O3)
+ ..hasRequiredFields = false;
+
+ Result._() : super();
+ factory Result() => create();
+ factory Result.fromBuffer($core.List<$core.int> i,
+ [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) =>
+ create()..mergeFromBuffer(i, r);
+ factory Result.fromJson($core.String i,
+ [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) =>
+ create()..mergeFromJson(i, r);
+ Result clone() => Result()..mergeFromMessage(this);
+ Result copyWith(void Function(Result) updates) =>
+ super.copyWith((message) => updates(message as Result));
+ $pb.BuilderInfo get info_ => _i;
+ @$core.pragma('dart2js:noInline')
+ static Result create() => Result._();
+ Result createEmptyInstance() => create();
+ static $pb.PbList<Result> createRepeated() => $pb.PbList<Result>();
+ static Result getDefault() => _defaultInstance ??= create()..freeze();
+ static Result _defaultInstance;
+
+ $core.String get name => $_getS(0, '');
+ set name($core.String v) {
+ $_setString(0, v);
+ }
+
+ $core.bool hasName() => $_has(0);
+ void clearName() => clearField(1);
+
+ $core.String get configuration => $_getS(1, '');
+ set configuration($core.String v) {
+ $_setString(1, v);
+ }
+
+ $core.bool hasConfiguration() => $_has(1);
+ void clearConfiguration() => clearField(2);
+
+ $core.int get timeMs => $_get(2, 0);
+ set timeMs($core.int v) {
+ $_setSignedInt32(2, v);
+ }
+
+ $core.bool hasTimeMs() => $_has(2);
+ void clearTimeMs() => clearField(3);
+
+ $core.String get result => $_getS(3, '');
+ set result($core.String v) {
+ $_setString(3, v);
+ }
+
+ $core.bool hasResult() => $_has(3);
+ void clearResult() => clearField(4);
+
+ $core.String get expected => $_getS(4, '');
+ set expected($core.String v) {
+ $_setString(4, v);
+ }
+
+ $core.bool hasExpected() => $_has(4);
+ void clearExpected() => clearField(5);
+
+ $core.bool get matches => $_get(5, false);
+ set matches($core.bool v) {
+ $_setBool(5, v);
+ }
+
+ $core.bool hasMatches() => $_has(5);
+ void clearMatches() => clearField(6);
+
+ $core.String get botName => $_getS(6, '');
+ set botName($core.String v) {
+ $_setString(6, v);
+ }
+
+ $core.bool hasBotName() => $_has(6);
+ void clearBotName() => clearField(7);
+
+ $core.String get commitHash => $_getS(7, '');
+ set commitHash($core.String v) {
+ $_setString(7, v);
+ }
+
+ $core.bool hasCommitHash() => $_has(7);
+ void clearCommitHash() => clearField(8);
+
+ $core.String get buildNumber => $_getS(8, '');
+ set buildNumber($core.String v) {
+ $_setString(8, v);
+ }
+
+ $core.bool hasBuildNumber() => $_has(8);
+ void clearBuildNumber() => clearField(9);
+
+ $core.String get builderName => $_getS(9, '');
+ set builderName($core.String v) {
+ $_setString(9, v);
+ }
+
+ $core.bool hasBuilderName() => $_has(9);
+ void clearBuilderName() => clearField(10);
+
+ $core.bool get flaky => $_get(10, false);
+ set flaky($core.bool v) {
+ $_setBool(10, v);
+ }
+
+ $core.bool hasFlaky() => $_has(10);
+ void clearFlaky() => clearField(11);
+
+ $core.bool get previousFlaky => $_get(11, false);
+ set previousFlaky($core.bool v) {
+ $_setBool(11, v);
+ }
+
+ $core.bool hasPreviousFlaky() => $_has(11);
+ void clearPreviousFlaky() => clearField(12);
+
+ $core.String get previousCommitHash => $_getS(12, '');
+ set previousCommitHash($core.String v) {
+ $_setString(12, v);
+ }
+
+ $core.bool hasPreviousCommitHash() => $_has(12);
+ void clearPreviousCommitHash() => clearField(13);
+
+ $core.int get previousCommitTime => $_get(13, 0);
+ set previousCommitTime($core.int v) {
+ $_setSignedInt32(13, v);
+ }
+
+ $core.bool hasPreviousCommitTime() => $_has(13);
+ void clearPreviousCommitTime() => clearField(14);
+
+ $core.String get previousBuildNumber => $_getS(14, '');
+ set previousBuildNumber($core.String v) {
+ $_setString(14, v);
+ }
+
+ $core.bool hasPreviousBuildNumber() => $_has(14);
+ void clearPreviousBuildNumber() => clearField(15);
+
+ $core.String get previousResult => $_getS(15, '');
+ set previousResult($core.String v) {
+ $_setString(15, v);
+ }
+
+ $core.bool hasPreviousResult() => $_has(15);
+ void clearPreviousResult() => clearField(16);
+
+ $core.bool get changed => $_get(16, false);
+ set changed($core.bool v) {
+ $_setBool(16, v);
+ }
+
+ $core.bool hasChanged() => $_has(16);
+ void clearChanged() => clearField(17);
+
+ $core.String get suite => $_getS(17, '');
+ set suite($core.String v) {
+ $_setString(17, v);
+ }
+
+ $core.bool hasSuite() => $_has(17);
+ void clearSuite() => clearField(100);
+
+ $core.String get testName => $_getS(18, '');
+ set testName($core.String v) {
+ $_setString(18, v);
+ }
+
+ $core.bool hasTestName() => $_has(18);
+ void clearTestName() => clearField(101);
+
+ $core.int get commitTime => $_get(19, 0);
+ set commitTime($core.int v) {
+ $_setSignedInt32(19, v);
+ }
+
+ $core.bool hasCommitTime() => $_has(19);
+ void clearCommitTime() => clearField(102);
+}
diff --git a/current_results/gen/result.pbenum.dart b/current_results/lib/src/generated/result.pbenum.dart
similarity index 99%
rename from current_results/gen/result.pbenum.dart
rename to current_results/lib/src/generated/result.pbenum.dart
index 969d1be..2c06c6b 100644
--- a/current_results/gen/result.pbenum.dart
+++ b/current_results/lib/src/generated/result.pbenum.dart
@@ -3,4 +3,3 @@
// source: result.proto
///
// ignore_for_file: camel_case_types,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name
-
diff --git a/current_results/gen/result.pbjson.dart b/current_results/lib/src/generated/result.pbjson.dart
similarity index 67%
rename from current_results/gen/result.pbjson.dart
rename to current_results/lib/src/generated/result.pbjson.dart
index 8493cd1..34cbe82 100644
--- a/current_results/gen/result.pbjson.dart
+++ b/current_results/lib/src/generated/result.pbjson.dart
@@ -21,12 +21,41 @@
const {'1': 'build_number', '3': 9, '4': 1, '5': 9, '10': 'buildNumber'},
const {'1': 'builder_name', '3': 10, '4': 1, '5': 9, '10': 'builderName'},
const {'1': 'flaky', '3': 11, '4': 1, '5': 8, '10': 'flaky'},
- const {'1': 'previous_flaky', '3': 12, '4': 1, '5': 8, '10': 'previousFlaky'},
- const {'1': 'previous_commit_hash', '3': 13, '4': 1, '5': 9, '10': 'previousCommitHash'},
- const {'1': 'previous_commit_time', '3': 14, '4': 1, '5': 5, '10': 'previousCommitTime'},
- const {'1': 'previous_build_number', '3': 15, '4': 1, '5': 9, '10': 'previousBuildNumber'},
- const {'1': 'previous_result', '3': 16, '4': 1, '5': 9, '10': 'previousResult'},
+ const {
+ '1': 'previous_flaky',
+ '3': 12,
+ '4': 1,
+ '5': 8,
+ '10': 'previousFlaky'
+ },
+ const {
+ '1': 'previous_commit_hash',
+ '3': 13,
+ '4': 1,
+ '5': 9,
+ '10': 'previousCommitHash'
+ },
+ const {
+ '1': 'previous_commit_time',
+ '3': 14,
+ '4': 1,
+ '5': 5,
+ '10': 'previousCommitTime'
+ },
+ const {
+ '1': 'previous_build_number',
+ '3': 15,
+ '4': 1,
+ '5': 9,
+ '10': 'previousBuildNumber'
+ },
+ const {
+ '1': 'previous_result',
+ '3': 16,
+ '4': 1,
+ '5': 9,
+ '10': 'previousResult'
+ },
const {'1': 'changed', '3': 17, '4': 1, '5': 8, '10': 'changed'},
],
};
-
diff --git a/current_results/gen/result.pbserver.dart b/current_results/lib/src/generated/result.pbserver.dart
similarity index 99%
rename from current_results/gen/result.pbserver.dart
rename to current_results/lib/src/generated/result.pbserver.dart
index 41edfc1..08420c3 100644
--- a/current_results/gen/result.pbserver.dart
+++ b/current_results/lib/src/generated/result.pbserver.dart
@@ -5,4 +5,3 @@
// ignore_for_file: camel_case_types,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name
export 'result.pb.dart';
-
diff --git a/current_results/lib/src/result.dart b/current_results/lib/src/result.dart
new file mode 100644
index 0000000..eaf8be7
--- /dev/null
+++ b/current_results/lib/src/result.dart
@@ -0,0 +1,46 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:current_results/src/generated/result.pb.dart' as api;
+
+class Result {
+ final String name;
+ final String configuration;
+ final String commitHash;
+ final String result;
+ final bool flaky;
+ final String expected;
+ final Duration time;
+
+ Result(this.name, this.configuration, this.commitHash, this.result,
+ this.flaky, this.expected, this.time);
+
+ Result.fromApi(api.Result other)
+ : this(
+ unique(other.name),
+ unique(other.configuration),
+ unique(other.commitHash),
+ unique(other.result),
+ other.flaky,
+ unique(other.expected),
+ Duration(milliseconds: other.timeMs));
+
+ static final uniqueStrings = Set<String>();
+
+ static String unique(String string) =>
+ uniqueStrings.lookup(string) ??
+ (uniqueStrings.add(string) ? string : string);
+
+ Map<String, dynamic> toMap() => {
+ 'name': name,
+ 'configuration': configuration,
+ 'commitHash': commitHash,
+ 'result': result,
+ 'flaky': flaky,
+ 'expected': expected,
+ 'time': time,
+ };
+
+ String toString() => toMap().toString();
+}
diff --git a/current_results/lib/src/slice.dart b/current_results/lib/src/slice.dart
new file mode 100644
index 0000000..1174465
--- /dev/null
+++ b/current_results/lib/src/slice.dart
@@ -0,0 +1,82 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:convert';
+import 'package:collection/collection.dart';
+
+import 'package:current_results/src/result.dart';
+import 'package:current_results/src/generated/result.pb.dart' as api;
+
+class Slice {
+ /// The current results, stored separately for each configuration in a
+ /// list sorted by test name.
+ final _stored = <String, List<Result>>{};
+
+ /// A sorted list of all test names seen. Names are not removed from this list.
+ List<String> testNames = [];
+ int _size = 0;
+
+ int get size => _size;
+
+ void add(List<String> lines) {
+ if (lines.isEmpty) return;
+ final results = lines.map((line) => Result.fromApi(api.Result()
+ ..mergeFromProto3Json(json.decode(line),
+ supportNamesWithUnderscores: true)));
+ final configuration = results.first.configuration;
+ if (results.any((result) => result.configuration != configuration)) {
+ print('Loaded results list with multiple configurations: '
+ 'first result: ${results.first}');
+ return;
+ }
+ int compareNames(Result a, Result b) => a.name.compareTo(b.name);
+ final sorted = results.toList()..sort(compareNames);
+ _size -= _stored[configuration]?.length ?? 0;
+ _stored[configuration] = sorted;
+ _size += sorted.length;
+ if (!sorted.every(Scanner(testNames).found)) {
+ testNames = merge(testNames, sorted);
+ }
+ }
+
+ List<String> merge(List<String> names, List<Result> sorted) {
+ final result = <String>[];
+ var i = 0;
+ var j = 0;
+ while (i < names.length && j < sorted.length) {
+ final compare = names[i].compareTo(sorted[j].name);
+ if (compare <= 0) {
+ result.add(names[i++]);
+ if (compare == 0) j++;
+ } else {
+ result.add(sorted[j++].name);
+ }
+ }
+ while (i < names.length) {
+ result.add(names[i++]);
+ }
+ while (j < sorted.length) {
+ result.add(sorted[j++].name);
+ }
+ return result;
+ }
+}
+
+class Scanner {
+ List<String> names;
+ int position = 0;
+
+ Scanner(this.names);
+
+ bool found(Result a) {
+ while (position < names.length) {
+ if (names[position].compareTo(a.name) < 0) {
+ position++;
+ } else {
+ return names[position] == a.name;
+ }
+ }
+ return false;
+ }
+}
diff --git a/current_results/pubspec.lock b/current_results/pubspec.lock
index 2e1a23a..2fb970e 100644
--- a/current_results/pubspec.lock
+++ b/current_results/pubspec.lock
@@ -7,21 +7,21 @@
name: _discoveryapis_commons
url: "https://pub.dartlang.org"
source: hosted
- version: "0.1.9"
+ version: "0.2.0"
_fe_analyzer_shared:
dependency: transitive
description:
name: _fe_analyzer_shared
url: "https://pub.dartlang.org"
source: hosted
- version: "3.0.0"
+ version: "4.0.0"
analyzer:
dependency: transitive
description:
name: analyzer
url: "https://pub.dartlang.org"
source: hosted
- version: "0.39.8"
+ version: "0.39.10"
args:
dependency: transitive
description:
@@ -63,7 +63,7 @@
name: crypto
url: "https://pub.dartlang.org"
source: hosted
- version: "2.1.4"
+ version: "2.1.5"
csslib:
dependency: transitive
description:
@@ -91,7 +91,7 @@
name: gcloud
url: "https://pub.dartlang.org"
source: hosted
- version: "0.7.0+1"
+ version: "0.7.2"
glob:
dependency: transitive
description:
@@ -112,7 +112,7 @@
name: googleapis_auth
url: "https://pub.dartlang.org"
source: hosted
- version: "0.2.11+1"
+ version: "0.2.12"
grpc:
dependency: "direct main"
description:
@@ -154,7 +154,7 @@
name: js
url: "https://pub.dartlang.org"
source: hosted
- version: "0.6.1+1"
+ version: "0.6.2"
meta:
dependency: transitive
description:
@@ -197,6 +197,13 @@
url: "https://pub.dartlang.org"
source: hosted
version: "1.9.0"
+ pool:
+ dependency: "direct main"
+ description:
+ name: pool
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "1.4.0"
protobuf:
dependency: "direct main"
description:
diff --git a/current_results/pubspec.yaml b/current_results/pubspec.yaml
index 8acc9e9..df22a24 100644
--- a/current_results/pubspec.yaml
+++ b/current_results/pubspec.yaml
@@ -9,6 +9,7 @@
gcloud: ^0.7.0
googleapis_auth: ^0.2.11
grpc: ^2.1.3
+ pool: ^1.4.0
protobuf: ^1.0.0
dev_dependencies: