| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 library appengine.internal; | 5 library appengine.internal; |
| 6 | 6 |
| 7 import 'dart:async'; | 7 import 'dart:async'; |
| 8 import 'dart:io'; | 8 import 'dart:io'; |
| 9 | 9 |
| 10 import 'package:gcloud/service_scope.dart' as ss; | 10 import 'package:gcloud/service_scope.dart' as ss; |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 90 return new Future.value(); | 90 return new Future.value(); |
| 91 } | 91 } |
| 92 } else { | 92 } else { |
| 93 return auth.clientViaMetadataServer().then((client) { | 93 return auth.clientViaMetadataServer().then((client) { |
| 94 _authClient = client; | 94 _authClient = client; |
| 95 return new storage.Storage(client, context.applicationID); | 95 return new storage.Storage(client, context.applicationID); |
| 96 }); | 96 }); |
| 97 } | 97 } |
| 98 } | 98 } |
| 99 | 99 |
| 100 var context = getDockerContext(); | 100 if (_contextRegistry != null) { |
| 101 var rpcService = initializeRPC(); | 101 return new Future.value(_contextRegistry); |
| 102 } else { |
| 103 var context = getDockerContext(); |
| 104 var rpcService = initializeRPC(); |
| 102 | 105 |
| 103 return getStorage(context).then((storage) { | 106 return getStorage(context).then((storage) { |
| 104 return new ContextRegistry(rpcService, storage, context); | 107 _contextRegistry = new ContextRegistry(rpcService, storage, context); |
| 105 }); | 108 return _contextRegistry; |
| 109 }); |
| 110 } |
| 106 } | 111 } |
| 107 | 112 |
| 108 void initializeContext(Services services) { | 113 void initializeContext(Services services) { |
| 109 db.registerDbService(services.db); | 114 db.registerDbService(services.db); |
| 110 datastore.registerDatastoreService(services.db.datastore); | 115 datastore.registerDatastoreService(services.db.datastore); |
| 111 storage.registerStorageService(services.storage); | 116 storage.registerStorageService(services.storage); |
| 112 logging.registerLoggingService(services.logging); | 117 logging.registerLoggingService(services.logging); |
| 113 modules.registerModulesService(services.modules); | 118 modules.registerModulesService(services.modules); |
| 114 memcache.registerMemcacheService(services.memcache); | 119 memcache.registerMemcacheService(services.memcache); |
| 115 | 120 |
| 116 if (_authClient != null) { | 121 if (_authClient != null) { |
| 117 gcloud_http.registerAuthClientService(_authClient); | 122 gcloud_http.registerAuthClientService(_authClient); |
| 118 | 123 |
| 119 // This will automatically close the authenticated HTTP client when the | 124 // This will automatically close the authenticated HTTP client when the |
| 120 // HTTP server shuts down. | 125 // HTTP server shuts down. |
| 121 ss.registerScopeExitCallback(() => _authClient.close()); | 126 ss.registerScopeExitCallback(() => _authClient.close()); |
| 122 } | 127 } |
| 123 } | 128 } |
| 124 | 129 |
| 125 void initializeRequestSpecificServices(Services services) { | 130 void initializeRequestSpecificServices(Services services) { |
| 126 logging.registerLoggingService(services.logging); | 131 logging.registerLoggingService(services.logging); |
| 127 users.registerUserService(services.users); | 132 users.registerUserService(services.users); |
| 128 } | 133 } |
| 129 | 134 |
| 135 Future withAppEngineServices(Future callback()) { |
| 136 return initializeAppEngine().then((ContextRegistry contextRegistry) { |
| 137 return ss.fork(() { |
| 138 var backgroundServices = _contextRegistry.newBackgroundServices(); |
| 139 initializeContext(backgroundServices); |
| 140 return callback(); |
| 141 }); |
| 142 }); |
| 143 } |
| 144 |
| 130 Future runAppEngine(void handler(request, context), void onError(e, s)) { | 145 Future runAppEngine(void handler(request, context), void onError(e, s)) { |
| 131 return initializeAppEngine().then((ContextRegistry contextRegistry) { | 146 return withAppEngineServices(() { |
| 132 _contextRegistry = contextRegistry; | |
| 133 var appengineServer = new AppEngineHttpServer(_contextRegistry); | 147 var appengineServer = new AppEngineHttpServer(_contextRegistry); |
| 134 var backgroundServices = _contextRegistry.newBackgroundServices(); | 148 appengineServer.run((request, context) { |
| 149 ss.fork(() { |
| 150 initializeRequestSpecificServices(context.services); |
| 151 handler(request, context); |
| 152 return request.response.done; |
| 153 }, onError: (error, stack) { |
| 154 var context = _contextRegistry.lookup(request); |
| 155 if (context != null) { |
| 156 try { |
| 157 context.services.logging.error( |
| 158 'Uncaught error in request handler: $error\n$stack'); |
| 159 } catch (e) { |
| 160 print('Error while logging uncaught error: $e'); |
| 161 } |
| 162 } else { |
| 163 // TODO: We could log on the background ticket here. |
| 164 print('Unable to log error, since response has already been sent.'); |
| 165 } |
| 166 onError('Uncaught error in request handler zone: $error', stack); |
| 135 | 167 |
| 136 ss.fork(() { | 168 // In many cases errors happen during request processing or response |
| 137 initializeContext(backgroundServices); | 169 // preparation. In such cases we want to close the connection, since |
| 138 appengineServer.run((request, context) { | 170 // user code might not be able to. |
| 139 ss.fork(() { | 171 try { |
| 140 initializeRequestSpecificServices(context.services); | 172 request.response.statusCode = HttpStatus.INTERNAL_SERVER_ERROR; |
| 141 handler(request, context); | 173 } on StateError catch (_) {} |
| 142 return request.response.done; | 174 request.response.close().catchError((closeError, closeErrorStack) { |
| 143 }, onError: (error, stack) { | 175 onError('Forcefully closing response, due to error in request ' |
| 144 var context = _contextRegistry.lookup(request); | 176 'handler zone, resulted in an error: $closeError', |
| 145 if (context != null) { | 177 closeErrorStack); |
| 146 try { | |
| 147 context.services.logging.error( | |
| 148 'Uncaught error in request handler: $error\n$stack'); | |
| 149 } catch (e) { | |
| 150 print('Error while logging uncaught error: $e'); | |
| 151 } | |
| 152 } else { | |
| 153 // TODO: We could log on the background ticket here. | |
| 154 print('Unable to log error, since response has already been sent.'); | |
| 155 } | |
| 156 onError('Uncaught error in request handler zone: $error', stack); | |
| 157 | |
| 158 // In many cases errors happen during request processing or response | |
| 159 // preparation. In such cases we want to close the connection, since | |
| 160 // user code might not be able to. | |
| 161 try { | |
| 162 request.response.statusCode = HttpStatus.INTERNAL_SERVER_ERROR; | |
| 163 } on StateError catch (_) {} | |
| 164 request.response.close().catchError((closeError, closeErrorStack) { | |
| 165 onError('Forcefully closing response, due to error in request ' | |
| 166 'handler zone, resulted in an error: $closeError', | |
| 167 closeErrorStack); | |
| 168 }); | |
| 169 }); | 178 }); |
| 170 }); | 179 }); |
| 171 return appengineServer.done; | |
| 172 }); | 180 }); |
| 173 | 181 return appengineServer.done; |
| 174 return new Future.value(); | |
| 175 }); | 182 }); |
| 176 } | 183 } |
| OLD | NEW |