Comparing version 3.0.1 to 3.0.2
@@ -0,1 +1,11 @@ | ||
Must provide GITHUB_AUTH | ||
## v3.0.2 (2020-03-24) | ||
#### :rocket: Enhancement | ||
* [#262](https://github.com/ember-fastboot/fastboot/pull/264) Add sandbox queue management when using `buildSandboxPerVisit` ([@kratiahuja](https://github.com/kratiahuja)) | ||
#### Committers: 1 | ||
- Krati Ahuja ([@kratiahuja](https://github.com/kratiahuja)) | ||
## v3.0.1 (2020-03-12) | ||
@@ -6,2 +16,5 @@ | ||
#### Committers: 1 | ||
- Krati Ahuja ([@kratiahuja](https://github.com/kratiahuja)) | ||
## v3.0.0 (2020-01-31) | ||
@@ -8,0 +21,0 @@ |
{ | ||
"name": "fastboot", | ||
"version": "3.0.1", | ||
"version": "3.0.2", | ||
"description": "Library for rendering Ember apps in node.js", | ||
@@ -5,0 +5,0 @@ "keywords": [ |
@@ -39,2 +39,6 @@ # FastBoot | ||
}, | ||
// optional number to be provided when using `buildSandboxPerVisit` which defines the queue size for sandboxes. | ||
// This number should represent your QPS of your service | ||
maxSandboxQueueSize: <Number> // defaults to 1 if not provided | ||
}); | ||
@@ -72,3 +76,3 @@ | ||
- `destroyAppInstanceInMs`: whether to destroy the instance in the given number of ms. This is a failure mechanism to not wedge the Node process | ||
- `buildSandboxPerVisit`: whether to create a new sandbox context per-visit (slows down each visit, but guarantees no prototype leakages can occur), or reuse the existing sandbox (faster per-request, but each request shares the same set of prototypes). Defaults to false. | ||
- `buildSandboxPerVisit`: whether to create a new sandbox context per-visit (slows down each visit, but guarantees no prototype leakages can occur), or reuse the existing sandbox (faster per-request, but each request shares the same set of prototypes). Defaults to false. When using this flag, also set `maxSandboxQueue` to represent the QPS of your application so that sandboxes can be queued for next requests. When not provided, it defaults to storing only one sandbox | ||
@@ -112,2 +116,39 @@ ### Build Your App | ||
### Result | ||
The result from `fastboot` is a `Result` object that has the following API: | ||
``` | ||
type DOMContents = () => { | ||
/** | ||
The `<head>` contents generated by the visit. | ||
*/ | ||
head: string; | ||
/** | ||
The `<body>` contents generated by the visit. | ||
*/ | ||
body: string; | ||
} | ||
interface FastBootVisitResult { | ||
/** | ||
The serialized DOM contents after completing the `visit` request. | ||
Note: this combines the `domContents.head` and `domContents.body`. | ||
*/ | ||
html(): string; | ||
domContents(): DOMContents | ||
analytics: { | ||
/** | ||
* Boolean to know if the request used a prebuilt sandbox | ||
*/ | ||
usedPrebuiltSandbox: <Boolean> | ||
} | ||
} | ||
``` | ||
### The Shoebox | ||
@@ -114,0 +155,0 @@ |
@@ -17,2 +17,3 @@ 'use strict'; | ||
const getPackageName = require('./utils/get-package-name'); | ||
const Queue = require('./utils/queue'); | ||
@@ -33,2 +34,3 @@ /** | ||
* @param {Function} [options.buildSandboxGlobals] - the function used to build the final set of global properties accesible within the sandbox | ||
* @param {Number} [options.maxSandboxQueueSize] - maximum sandbox queue size when using buildSandboxPerRequest flag. | ||
*/ | ||
@@ -69,5 +71,7 @@ constructor(options) { | ||
// default to 1 if maxSandboxQueueSize is not defined so the sandbox is pre-warmed when process comes up | ||
const maxSandboxQueueSize = options.maxSandboxQueueSize || 1; | ||
// Ensure that the dist files can be evaluated and the `Ember.Application` | ||
// instance created. | ||
this.buildApp(); | ||
this.buildSandboxQueue(maxSandboxQueueSize); | ||
} | ||
@@ -78,2 +82,21 @@ | ||
* | ||
* Function to build queue of sandboxes which is later leveraged if application is using `buildSandboxPerRequest` | ||
* flag. This is an optimization to help with performance. | ||
* | ||
* @param {Number} maxSandboxQueueSize - maximum size of queue (this is should be a derivative of your QPS) | ||
*/ | ||
buildSandboxQueue(maxSandboxQueueSize) { | ||
this._sandboxApplicationInstanceQueue = new Queue( | ||
() => this.buildNewApplicationInstance(), | ||
maxSandboxQueueSize | ||
); | ||
for (let i = 0; i < maxSandboxQueueSize; i++) { | ||
this._sandboxApplicationInstanceQueue.enqueue(); | ||
} | ||
} | ||
/** | ||
* @private | ||
* | ||
* Builds and initializes a new sandbox to run the Ember application in. | ||
@@ -247,2 +270,14 @@ */ | ||
* | ||
* @param {Promise<instance>} appInstance - the instance that is pre-warmed or built on demand | ||
* @param {Boolean} isAppInstancePreBuilt - boolean representing how the instance was built | ||
* | ||
* @returns {Object} | ||
*/ | ||
getAppInstanceInfo(appInstance, isAppInstancePreBuilt = true) { | ||
return { app: appInstance, isSandboxPreBuilt: isAppInstancePreBuilt }; | ||
} | ||
/** | ||
* @private | ||
* | ||
* Get the new sandbox off if it is being created, otherwise create a new one on demand. | ||
@@ -252,16 +287,12 @@ * The later is needed when the current request hasn't finished or wasn't build with sandbox | ||
* | ||
* @param {Boolean} buildSandboxPerVisit if true, a new sandbox will | ||
* **always** be created, otherwise one | ||
* is created for the first request | ||
* only | ||
*/ | ||
async _getNewApplicationInstance() { | ||
let app; | ||
async getNewApplicationInstance() { | ||
const queueObject = this._sandboxApplicationInstanceQueue.dequeue(); | ||
const app = await queueObject.item; | ||
if (this._pendingNewApplicationInstance) { | ||
let pendingAppInstancePromise = this._pendingNewApplicationInstance; | ||
this._pendingNewApplicationInstance = undefined; | ||
app = await pendingAppInstancePromise; | ||
} else { | ||
// if there is no current pending application instance, create a new one on-demand. | ||
app = await this.buildApp(); | ||
} | ||
return app; | ||
return this.getAppInstanceInfo(app, queueObject.isItemPreBuilt); | ||
} | ||
@@ -294,3 +325,5 @@ | ||
let app = shouldBuildApp ? await this._getNewApplicationInstance() : this._applicationInstance; | ||
let { app, isSandboxPreBuilt } = shouldBuildApp | ||
? await this.getNewApplicationInstance() | ||
: this.getAppInstanceInfo(this._applicationInstance); | ||
@@ -302,2 +335,6 @@ if (buildSandboxPerVisit) { | ||
result.applicationInstance = app; | ||
// we add analytics information about the current request to know | ||
// whether it used sandbox from the pre-built queue or built on demand. | ||
result.analytics.usedPrebuiltSandbox = isSandboxPreBuilt; | ||
} else { | ||
@@ -398,3 +435,3 @@ // save the created application instance so that we can clean it up when | ||
// which is invoked using buildSandboxPerVisit | ||
this._pendingNewApplicationInstance = this.buildNewApplicationInstance(); | ||
this._sandboxApplicationInstanceQueue.enqueue(); | ||
} | ||
@@ -401,0 +438,0 @@ } |
@@ -44,5 +44,6 @@ 'use strict'; | ||
* @param {Function} [options.buildSandboxGlobals] a function used to build the final set of global properties setup within the sandbox | ||
* @param {Number} [options.maxSandboxQueueSize] - maximum sandbox queue size when using buildSandboxPerRequest flag. | ||
*/ | ||
constructor(options = {}) { | ||
let { distPath, buildSandboxGlobals } = options; | ||
let { distPath, buildSandboxGlobals, maxSandboxQueueSize } = options; | ||
@@ -62,4 +63,5 @@ this.resilient = 'resilient' in options ? Boolean(options.resilient) : false; | ||
this.buildSandboxGlobals = buildSandboxGlobals; | ||
this.maxSandboxQueueSize = maxSandboxQueueSize; | ||
this._buildEmberApp(this.distPath, this.buildSandboxGlobals); | ||
this._buildEmberApp(this.distPath, this.buildSandboxGlobals, maxSandboxQueueSize); | ||
} | ||
@@ -111,3 +113,7 @@ | ||
_buildEmberApp(distPath = this.distPath, buildSandboxGlobals = this.buildSandboxGlobals) { | ||
_buildEmberApp( | ||
distPath = this.distPath, | ||
buildSandboxGlobals = this.buildSandboxGlobals, | ||
maxSandboxQueueSize = this.maxSandboxQueueSize | ||
) { | ||
if (!distPath) { | ||
@@ -130,2 +136,3 @@ throw new Error( | ||
buildSandboxGlobals, | ||
maxSandboxQueueSize, | ||
}); | ||
@@ -132,0 +139,0 @@ } |
@@ -23,2 +23,3 @@ 'use strict'; | ||
this.applicationInstanceInstance = undefined; | ||
this.analytics = {}; | ||
} | ||
@@ -25,0 +26,0 @@ |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
79468
23
1318
185