Use Cloud Run for all Dart Services (#623)
diff --git a/example/pubspec.lock b/example/pubspec.lock
index 1a2ffbc..99b1034 100644
--- a/example/pubspec.lock
+++ b/example/pubspec.lock
@@ -49,14 +49,14 @@
name: build
url: "https://pub.dartlang.org"
source: hosted
- version: "1.5.1"
+ version: "1.6.0"
build_config:
dependency: transitive
description:
name: build_config
url: "https://pub.dartlang.org"
source: hosted
- version: "0.4.3"
+ version: "0.4.5"
build_daemon:
dependency: transitive
description:
@@ -70,28 +70,28 @@
name: build_modules
url: "https://pub.dartlang.org"
source: hosted
- version: "3.0.0"
+ version: "3.0.2"
build_resolvers:
dependency: transitive
description:
name: build_resolvers
url: "https://pub.dartlang.org"
source: hosted
- version: "1.4.3"
+ version: "1.5.1"
build_runner:
dependency: "direct dev"
description:
name: build_runner
url: "https://pub.dartlang.org"
source: hosted
- version: "1.10.6"
+ version: "1.10.11"
build_runner_core:
dependency: transitive
description:
name: build_runner_core
url: "https://pub.dartlang.org"
source: hosted
- version: "6.1.1"
+ version: "6.1.5"
build_web_compilers:
dependency: "direct dev"
description:
@@ -126,7 +126,7 @@
name: checked_yaml
url: "https://pub.dartlang.org"
source: hosted
- version: "1.0.2"
+ version: "1.0.4"
cli_util:
dependency: transitive
description:
@@ -147,7 +147,7 @@
name: codemirror
url: "https://pub.dartlang.org"
source: hosted
- version: "0.5.21+5.58.0"
+ version: "0.5.23+5.59.1"
collection:
dependency: transitive
description:
@@ -343,7 +343,7 @@
name: pubspec_parse
url: "https://pub.dartlang.org"
source: hosted
- version: "0.1.5"
+ version: "0.1.7"
quiver:
dependency: transitive
description:
@@ -427,7 +427,7 @@
name: timing
url: "https://pub.dartlang.org"
source: hosted
- version: "0.1.1+2"
+ version: "0.1.1+3"
typed_data:
dependency: transitive
description:
diff --git a/lib/services_dev.dart b/lib/services_dev.dart
index c535398..d1aeaf5 100644
--- a/lib/services_dev.dart
+++ b/lib/services_dev.dart
@@ -23,8 +23,11 @@
void main(List<String> args) {
final parser = ArgParser();
- parser.addOption('port', abbr: 'p', defaultsTo: '8080');
- parser.addOption('server-url', defaultsTo: 'http://localhost');
+ parser
+ ..addOption('port', abbr: 'p', defaultsTo: '8080')
+ ..addOption('server-url', defaultsTo: 'http://localhost')
+ ..addOption('proxy-target',
+ help: 'URL base to proxy compilation requests to');
final result = parser.parse(args);
final port = int.tryParse(result['port'] as String);
@@ -40,14 +43,15 @@
if (record.stackTrace != null) print(record.stackTrace);
});
- EndpointsServer.serve(port).then((EndpointsServer server) {
+ EndpointsServer.serve(port, result['proxy-target'].toString())
+ .then((EndpointsServer server) {
_logger.info('Listening on port ${server.port}');
});
}
class EndpointsServer {
- static Future<EndpointsServer> serve(int port) {
- final endpointsServer = EndpointsServer._(port);
+ static Future<EndpointsServer> serve(int port, String proxyTarget) {
+ final endpointsServer = EndpointsServer._(port, proxyTarget);
return shelf
.serve(endpointsServer.handler, InternetAddress.anyIPv4, port)
@@ -59,6 +63,7 @@
final int port;
HttpServer server;
+ final String proxyTarget;
Pipeline pipeline;
Handler handler;
@@ -66,11 +71,13 @@
CommonServerApi commonServerApi;
FlutterWebManager flutterWebManager;
- EndpointsServer._(this.port) {
- final commonServerImpl = CommonServerImpl(
- _ServerContainer(),
- _Cache(),
- );
+ EndpointsServer._(this.port, this.proxyTarget) {
+ final commonServerImpl = (proxyTarget != null && proxyTarget.isNotEmpty)
+ ? CommonServerImplProxy(proxyTarget)
+ : CommonServerImpl(
+ _ServerContainer(),
+ _Cache(),
+ );
commonServerApi = CommonServerApi(commonServerImpl);
commonServerImpl.init();
diff --git a/lib/services_gae.dart b/lib/services_gae.dart
index 8c234c5..9d59760 100644
--- a/lib/services_gae.dart
+++ b/lib/services_gae.dart
@@ -30,7 +30,6 @@
void main(List<String> args) {
final parser = ArgParser()
- ..addFlag('dark-launch', help: 'Dark launch proxied compilation requests')
..addOption('proxy-target',
help: 'URL base to proxy compilation requests to')
..addOption('port',
@@ -55,16 +54,13 @@
});
log.info('''Initializing dart-services:
--port: $gaePort
- --dark-launch: ${results['dark-launch']}
--proxy-target: ${results['proxy-target']}
sdkPath: ${SdkManager.sdk?.sdkPath}
\$REDIS_SERVER_URI: ${io.Platform.environment['REDIS_SERVER_URI']}
\$GAE_VERSION: ${io.Platform.environment['GAE_VERSION']}
''');
- final server = GaeServer(
- io.Platform.environment['REDIS_SERVER_URI'],
- results['dark-launch'].toString().toLowerCase() == 'true',
+ final server = GaeServer(io.Platform.environment['REDIS_SERVER_URI'],
results['proxy-target'].toString());
server.start(gaePort);
}
@@ -74,25 +70,27 @@
CommonServerImpl commonServerImpl;
CommonServerApi commonServerApi;
+ bool proxying = false;
- GaeServer(this.redisServerUri, bool darkLaunch, String proxyTarget) {
+ GaeServer(this.redisServerUri, String proxyTarget) {
hierarchicalLoggingEnabled = true;
recordStackTraceAtLevel = Level.SEVERE;
_logger.level = Level.ALL;
- commonServerImpl = CommonServerImpl(
- GaeServerContainer(),
- redisServerUri == null
- ? InMemoryCache()
- : RedisCache(
- redisServerUri,
- io.Platform.environment['GAE_VERSION'],
- ),
- );
if (proxyTarget != null && proxyTarget.isNotEmpty) {
- commonServerImpl =
- CommonServerImplProxy(commonServerImpl, darkLaunch, proxyTarget);
+ commonServerImpl = CommonServerImplProxy(proxyTarget);
+ proxying = true;
+ } else {
+ commonServerImpl = CommonServerImpl(
+ GaeServerContainer(),
+ redisServerUri == null
+ ? InMemoryCache()
+ : RedisCache(
+ redisServerUri,
+ io.Platform.environment['GAE_VERSION'],
+ ),
+ );
}
commonServerApi = CommonServerApi(commonServerImpl);
}
@@ -130,7 +128,9 @@
Future _processReadinessRequest(io.HttpRequest request) async {
_logger.info('Processing readiness check');
- if (!commonServerImpl.isRestarting &&
+ if (proxying) {
+ request.response.statusCode = io.HttpStatus.ok;
+ } else if (!commonServerImpl.isRestarting &&
DateTime.now().isBefore(_serveUntil)) {
request.response.statusCode = io.HttpStatus.ok;
} else {
@@ -143,7 +143,10 @@
Future _processLivenessRequest(io.HttpRequest request) async {
_logger.info('Processing liveness check');
- if (!commonServerImpl.isHealthy || DateTime.now().isAfter(_serveUntil)) {
+ if (proxying) {
+ request.response.statusCode = io.HttpStatus.ok;
+ } else if (!commonServerImpl.isHealthy ||
+ DateTime.now().isAfter(_serveUntil)) {
_logger.severe('CommonServer is no longer healthy.'
' Intentionally failing health check.');
request.response.statusCode = io.HttpStatus.serviceUnavailable;
diff --git a/lib/src/common_server_impl.dart b/lib/src/common_server_impl.dart
index 7b78e03..f55234c 100644
--- a/lib/src/common_server_impl.dart
+++ b/lib/src/common_server_impl.dart
@@ -11,6 +11,7 @@
import 'package:http/http.dart' as http;
import 'package:logging/logging.dart';
import 'package:pedantic/pedantic.dart';
+import 'package:protobuf/protobuf.dart' as $pb;
import '../version.dart';
import 'analysis_servers.dart';
@@ -34,141 +35,127 @@
}
class CommonServerImplProxy implements CommonServerImpl {
- const CommonServerImplProxy(
- this._wrapped, this._darkLaunch, this._proxyTarget);
- final CommonServerImpl _wrapped;
+ const CommonServerImplProxy(this._proxyTarget);
final String _proxyTarget;
- final bool _darkLaunch;
+
+ Future<R> _postToProxy<R extends $pb.GeneratedMessage>(
+ String url, $pb.GeneratedMessage request, R responseProto) async {
+ final proxyResponse = http.post(url,
+ headers: {'Content-Type': 'application/json; charset=utf-8'},
+ body: _jsonEncoder.convert(request.toProto3Json()));
+
+ return proxyResponse.then((response) async {
+ if (response.statusCode == 200) {
+ return responseProto
+ ..mergeFromProto3Json(JsonDecoder().convert(response.body));
+ } else {
+ final err = proto.BadRequest.create()
+ ..mergeFromProto3Json(JsonDecoder().convert(response.body));
+ throw BadRequest(err.error.message);
+ }
+ });
+ }
@override
- Future<String> _checkCache(String query) => _wrapped._checkCache(query);
+ Future<proto.AnalysisResults> analyze(proto.SourceRequest request) {
+ final url = '${_proxyTarget}api/dartservices/v2/analyze';
+ return _postToProxy(url, request, proto.AnalysisResults.create());
+ }
@override
- Future<proto.CompileDDCResponse> _compileDDC(String source) =>
- _wrapped._compileDDC(source);
-
- @override
- Future<proto.CompileResponse> _compileDart2js(String source,
- {bool returnSourceMap = false}) =>
- _wrapped._compileDart2js(source, returnSourceMap: returnSourceMap);
-
- @override
- Future<void> _setCache(String query, String result) =>
- _wrapped._setCache(query, result);
-
- @override
- bool get analysisServersRunning => _wrapped.analysisServersRunning;
-
- @override
- Future<proto.AnalysisResults> analyze(proto.SourceRequest request) =>
- _wrapped.analyze(request);
-
- @override
- Future<proto.AssistsResponse> assists(proto.SourceRequest request) =>
- _wrapped.assists(request);
+ Future<proto.AssistsResponse> assists(proto.SourceRequest request) {
+ final url = '${_proxyTarget}api/dartservices/v2/assists';
+ return _postToProxy(url, request, proto.AssistsResponse.create());
+ }
@override
Future<proto.CompileResponse> compile(proto.CompileRequest request) {
final url = '${_proxyTarget}api/dartservices/v2/compile';
- final proxyResponse = http.post(url,
- headers: {'Content-Type': 'application/json; charset=utf-8'},
- body: _jsonEncoder.convert(request.toProto3Json()));
- if (_darkLaunch) {
- proxyResponse.then((response) {
- log.info(
- 'compile: Proxied request returned status code: ${response.statusCode}');
- });
- return _wrapped.compile(request);
- } else {
- return proxyResponse.then((response) async {
- if (response.statusCode == 200) {
- return proto.CompileResponse.create()
- ..mergeFromProto3Json(JsonDecoder().convert(response.body));
- } else {
- final err = proto.BadRequest.create()
- ..mergeFromProto3Json(JsonDecoder().convert(response.body));
- throw BadRequest(err.error.message);
- }
- });
- }
+ return _postToProxy(url, request, proto.CompileResponse.create());
}
@override
Future<proto.CompileDDCResponse> compileDDC(proto.CompileDDCRequest request) {
final url = '${_proxyTarget}api/dartservices/v2/compileDDC';
- final proxyResponse = http.post(url,
- headers: {'Content-Type': 'application/json; charset=utf-8'},
- body: _jsonEncoder.convert(request.toProto3Json()));
- if (_darkLaunch) {
- proxyResponse.then((response) {
- log.info(
- 'compileDDC: Proxied request returned status code: ${response.statusCode}');
- });
- return _wrapped.compileDDC(request);
- } else {
- return proxyResponse.then((response) async {
- if (response.statusCode == 200) {
- return proto.CompileDDCResponse.create()
- ..mergeFromProto3Json(JsonDecoder().convert(response.body));
- } else {
- final err = proto.BadRequest.create()
- ..mergeFromProto3Json(JsonDecoder().convert(response.body));
- throw BadRequest(err.error.message);
- }
- });
- }
+ return _postToProxy(url, request, proto.CompileDDCResponse.create());
}
@override
- Future<proto.CompleteResponse> complete(proto.SourceRequest request) =>
- _wrapped.complete(request);
+ Future<proto.CompleteResponse> complete(proto.SourceRequest request) {
+ final url = '${_proxyTarget}api/dartservices/v2/complete';
+ return _postToProxy(url, request, proto.CompleteResponse.create());
+ }
@override
- Future<proto.DocumentResponse> document(proto.SourceRequest request) =>
- _wrapped.document(request);
+ Future<proto.DocumentResponse> document(proto.SourceRequest request) {
+ final url = '${_proxyTarget}api/dartservices/v2/document';
+ return _postToProxy(url, request, proto.DocumentResponse.create());
+ }
@override
- Future<proto.FixesResponse> fixes(proto.SourceRequest request) =>
- _wrapped.fixes(request);
+ Future<proto.FixesResponse> fixes(proto.SourceRequest request) {
+ final url = '${_proxyTarget}api/dartservices/v2/fixes';
+ return _postToProxy(url, request, proto.FixesResponse.create());
+ }
@override
- Future<proto.FormatResponse> format(proto.SourceRequest request) =>
- _wrapped.format(request);
+ Future<proto.FormatResponse> format(proto.SourceRequest request) {
+ final url = '${_proxyTarget}api/dartservices/v2/format';
+ return _postToProxy(url, request, proto.FormatResponse.create());
+ }
@override
- Future<void> init() => _wrapped.init();
+ Future<proto.VersionResponse> version(proto.VersionRequest request) {
+ final url = '${_proxyTarget}api/dartservices/v2/version';
+ return _postToProxy(url, request, proto.VersionResponse.create());
+ }
@override
- bool get isHealthy => _wrapped.isHealthy;
+ Future<String> _checkCache(String query) => null;
@override
- bool get isRestarting => _wrapped.isRestarting;
+ Future<proto.CompileDDCResponse> _compileDDC(String source) => null;
@override
- Future shutdown() => _wrapped.shutdown();
+ Future<proto.CompileResponse> _compileDart2js(String source,
+ {bool returnSourceMap = false}) =>
+ null;
@override
- Future<proto.VersionResponse> version(proto.VersionRequest request) =>
- _wrapped.version(request);
+ Future<void> _setCache(String query, String result) => null;
@override
- AnalysisServersWrapper get _analysisServers => _wrapped._analysisServers;
+ bool get analysisServersRunning => true;
@override
- Compiler get _compiler => _wrapped._compiler;
+ Future<void> init() => null;
@override
- ServerCache get _cache => _wrapped._cache;
+ bool get isHealthy => true;
@override
- ServerContainer get _container => _wrapped._container;
+ bool get isRestarting => false;
@override
- set _analysisServers(AnalysisServersWrapper __analysisServers) =>
- _wrapped._analysisServers = __analysisServers;
+ Future shutdown() => null;
@override
- set _compiler(Compiler __compiler) => _wrapped._compiler = __compiler;
+ AnalysisServersWrapper get _analysisServers => null;
+
+ @override
+ Compiler get _compiler => null;
+
+ @override
+ ServerCache get _cache => null;
+
+ @override
+ ServerContainer get _container => null;
+
+ @override
+ set _analysisServers(AnalysisServersWrapper analysisServers) => null;
+
+ @override
+ set _compiler(Compiler compiler) => null;
}
final JsonEncoder _jsonEncoder = const JsonEncoder.withIndent(' ');
diff --git a/tool/grind.dart b/tool/grind.dart
index cbc8060..ec825cd 100644
--- a/tool/grind.dart
+++ b/tool/grind.dart
@@ -41,6 +41,18 @@
arguments: ['bin/server_dev.dart', '--port', '8082']);
}
+@Task()
+@Depends(buildStorageArtifacts)
+Future<void> serveWithProxyTarget() async {
+ await runWithLogging(Platform.executable, arguments: [
+ 'bin/server_dev.dart',
+ '--port',
+ '8082',
+ '--proxy-target',
+ 'https://dart-service-cloud-run-hdjctvyqtq-uc.a.run.app/'
+ ]);
+}
+
final _dockerVersionMatcher = RegExp(r'^FROM google/dart-runtime:(.*)$');
@Task('Update the docker and SDK versions')