Skip to content

Commit 0bdb1a9

Browse files
committed
Build new sandbox after request is done
This is basic PR to build a new sandbox per visit after current request is complete. Specifically making sure the creation of sandbox is not tied to the request timeline itself but is done as an after effect. This is so that we do not build sandbox at the start of the request which is slow. Not specifically adding tests as this is just an internal implementation change. When we add queue management, I'll add more test cases of requests more than queue size or less than to cover those usecases.
1 parent 31b8a5b commit 0bdb1a9

File tree

1 file changed

+42
-8
lines changed

1 file changed

+42
-8
lines changed

src/ember-app.js

Lines changed: 42 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,16 @@ class EmberApp {
188188
}
189189
}
190190

191+
/**
192+
* Builds a new application instance sandbox as a micro-task.
193+
*/
194+
buildNewApplicationInstance() {
195+
return Promise.resolve().then(() => {
196+
let app = this.buildApp();
197+
return app;
198+
});
199+
}
200+
191201
/**
192202
* @private
193203
*
@@ -227,6 +237,29 @@ class EmberApp {
227237
return app;
228238
}
229239

240+
/**
241+
* @private
242+
*
243+
* Get the new sandbox off if it is being created, otherwise create a new one on demand.
244+
* The later is needed when the current request hasn't finished or wasn't build with sandbox
245+
* per request turned on and a new request comes in.
246+
*
247+
*/
248+
async _getNewApplicationInstance() {
249+
let app;
250+
251+
if (this._pendingNewApplicationInstance) {
252+
let pendingAppInstancePromise = this._pendingNewApplicationInstance;
253+
this._pendingNewApplicationInstance = undefined;
254+
app = await pendingAppInstancePromise;
255+
} else {
256+
// if there is no current pending application instance, create a new one on-demand.
257+
app = await this.buildApp();
258+
}
259+
260+
return app;
261+
}
262+
230263
/**
231264
* @private
232265
*
@@ -252,7 +285,7 @@ class EmberApp {
252285
async _visit(path, fastbootInfo, bootOptions, result, buildSandboxPerVisit) {
253286
let shouldBuildApp = buildSandboxPerVisit || this._applicationInstance === undefined;
254287

255-
let app = shouldBuildApp ? await this.buildApp() : this._applicationInstance;
288+
let app = shouldBuildApp ? await this._getNewApplicationInstance() : this._applicationInstance;
256289

257290
if (buildSandboxPerVisit) {
258291
// entangle the specific application instance to the result, so it can be
@@ -305,6 +338,7 @@ class EmberApp {
305338
let html = options.html || this.html;
306339
let disableShoebox = options.disableShoebox || false;
307340
let destroyAppInstanceInMs = parseInt(options.destroyAppInstanceInMs, 10);
341+
let buildSandboxPerVisit = options.buildSandboxPerVisit || false;
308342

309343
let shouldRender = options.shouldRender !== undefined ? options.shouldRender : true;
310344
let bootOptions = buildBootOptions(shouldRender);
@@ -331,13 +365,7 @@ class EmberApp {
331365
}
332366

333367
try {
334-
await this._visit(
335-
path,
336-
fastbootInfo,
337-
bootOptions,
338-
result,
339-
options.buildSandboxPerVisit === true
340-
);
368+
await this._visit(path, fastbootInfo, bootOptions, result, buildSandboxPerVisit);
341369

342370
if (!disableShoebox) {
343371
// if shoebox is not disabled, then create the shoebox and send API data
@@ -355,6 +383,12 @@ class EmberApp {
355383
result._destroy();
356384

357385
clearTimeout(destroyAppInstanceTimer);
386+
387+
if (buildSandboxPerVisit) {
388+
// if sandbox was built for this visit, then build a new sandbox for the next incoming request
389+
// which is invoked using buildSandboxPerVisit
390+
this._pendingNewApplicationInstance = this.buildNewApplicationInstance();
391+
}
358392
}
359393

360394
return result;

0 commit comments

Comments
 (0)