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 |