blob: d2e1cdbe804258370dd99e4c06f2e5dc9d7c77d9 [file] [log] [blame]
// Copyright (c) 2017, 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:async';
import 'dart:io' hide HttpException;
import 'buildbot_data.dart';
import 'buildbot_loading.dart';
import 'buildbot_structures.dart';
import 'util.dart';
/// Interface for pulling build bot results.
abstract class BuildbotClient {
/// Reads the [BuildResult] for the [buildUri].
Future<BuildResult> readResult(BuildUri buildUri);
int get mostRecentBuildNumber;
/// Closes the client and cleans up its state.
void close();
}
/// Buildbot client that pulls build bot results through http.
class HttpBuildbotClient implements BuildbotClient {
final HttpClient _client = new HttpClient();
static const int maxSkips = 3;
@override
Future<BuildResult> readResult(BuildUri buildUri) async {
int skips = 0;
Duration timeout;
timeout = new Duration(seconds: 1);
void skipToPreviousBuildNumber() {
BuildUri prevBuildUri = buildUri.prev();
String message =
'Skip build number on ${buildUri} -> ${prevBuildUri.buildNumber}';
// Skipping is more serious with an absolute than a relative build.
if (buildUri.buildNumber < 0) {
log(message);
} else {
print(message);
}
buildUri = buildUri.prev();
}
while (true) {
try {
return await readBuildResultFromHttp(_client, buildUri, timeout);
} on TimeoutException {
if (timeout != null && skips < maxSkips) {
skips++;
skipToPreviousBuildNumber();
continue;
}
return null;
} on HttpException {
if (timeout != null && skips < maxSkips) {
skips++;
skipToPreviousBuildNumber();
continue;
}
return null;
} on SocketException {
return null;
}
}
}
int get mostRecentBuildNumber => -1;
@override
void close() {
_client.close();
}
}
/// Buildbot client that pulls build bot results through logdog.
class LogdogBuildbotClient implements BuildbotClient {
Map<String, List<int>> _botBuildNumberCache = <String, List<int>>{};
int get mostRecentBuildNumber => -1;
Future<List<int>> _getAbsoluteBuildNumbers(BuildUri buildUri) async {
List<int> absoluteBuildNumbers = _botBuildNumberCache[buildUri.botName];
if (absoluteBuildNumbers == null) {
absoluteBuildNumbers = await lookupBotBuildNumbers(buildUri.botName);
_botBuildNumberCache[buildUri.botName] = absoluteBuildNumbers;
}
return absoluteBuildNumbers;
}
@override
Future<BuildResult> readResult(BuildUri buildUri) async {
List<int> absoluteBuildNumbers;
int buildNumberIndex;
if (buildUri.buildNumber < 0) {
absoluteBuildNumbers = await _getAbsoluteBuildNumbers(buildUri);
int buildNumberIndex =
getBuildNumberIndex(absoluteBuildNumbers, buildUri.buildNumber);
if (buildNumberIndex == null) return null;
buildUri =
buildUri.withBuildNumber(absoluteBuildNumbers[buildNumberIndex]);
}
while (true) {
try {
return await readBuildResultFromLogDog(buildUri);
} catch (e) {
absoluteBuildNumbers ??= await _getAbsoluteBuildNumbers(buildUri);
buildNumberIndex =
getBuildNumberIndex(absoluteBuildNumbers, buildUri.buildNumber);
if (buildNumberIndex == null) return null;
buildNumberIndex++;
if (buildNumberIndex >= absoluteBuildNumbers.length) return null;
int buildNumber = absoluteBuildNumbers[buildNumberIndex];
log('Skip build number ${buildUri.buildNumber} -> ${buildNumber}');
buildUri = buildUri.withBuildNumber(buildNumber);
}
}
}
@override
void close() {
// Nothing to do.
}
}