Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: move compile step to first run of server #2889

Conversation

EzraBrooks
Copy link
Collaborator

Fixes #2884 in a less npm-dependent manner than my previous PR.
@dignifiedquire How do you feel about this solution?

@EzraBrooks EzraBrooks changed the title refactor: move compile step to first run of server [WIP] refactor: move compile step to first run of server Nov 24, 2017
@EzraBrooks
Copy link
Collaborator Author

Looks like this works, unless the CI jobs cache the static resources between builds. I assume I should squash these commits?

lib/server.js Outdated
var bundler = browserify(path.join(__dirname, '/../client/main.js'))
bundler.bundle().pipe(fs.createWriteStream(karmaJsPath)).once('finish', () => {
bundler = browserify(path.join(__dirname, '/../context/main.js'))
bundler.bundle().pipe(fs.createWriteStream(contextJsPath))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This creates a race condition, if the bundle is not generated fast enough, it will be missing when trying to be served. Need to make sure things are blocked to move on until it is finished.

Copy link
Member

@dignifiedquire dignifiedquire left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you, see comments for things that need adjusment

@@ -329,6 +329,7 @@
"dependencies": {
"bluebird": "^3.3.0",
"body-parser": "^1.16.1",
"browserify": "^14.5.0",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be able to drop grunt-browserify as a depency now

@EzraBrooks
Copy link
Collaborator Author

Going to have to modify the server unit tests to handle the way it's now calling back to webServer.listen.

lib/server.js Outdated
bundler.bundle().pipe(fs.createWriteStream(karmaJsPath)).once('finish', () => {
bundler = browserify(path.join(__dirname, '/../context/main.js'))
// Start the web server once the last file has been browserified
bundler.bundle().pipe(fs.createWriteStream(contextJsPath)).once('finish', () => { startWebServer() })
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no need to wrap into an arrow function

lib/server.js Outdated
self.log.info('Front-end scripts not present. Compiling...')
// Browserify the files asynchronously
var bundler = browserify(path.join(__dirname, '/../client/main.js'))
bundler.bundle().pipe(fs.createWriteStream(karmaJsPath)).once('finish', () => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the two bundles should be created in parallel no need to wait for one or the other I think. Best you wrap bundle gen into a function that returns a promise and then use promise.all for the two invocations

lib/server.js Outdated
}

const karmaJsPath = path.join(__dirname, '/../static/karma.js')
const contextJsPath = path.join(__dirname, '/../static/context.js')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these can be pulled to the top of the file

lib/server.js Outdated
const karmaJsPath = path.join(__dirname, '/../static/karma.js')
const contextJsPath = path.join(__dirname, '/../static/context.js')
// Check if the static files haven't been compiled
if (!(fs.existsSync(karmaJsPath) && fs.existsSync(contextJsPath))) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please use the async versions

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fs.exists is deprecated, fs.existsSync is not. And it seems like it would be an unnecessary complication to use fs.stat on two separate files and make callbacks that && the results together.

lib/server.js Outdated
Promise.all([mainPromise, contextPromise]).then(() => {
startWebServer()
}, (error) => {
self.log.error(error)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • please use catch to handle the errors
  • this needs to abort on error because if this fails it means we are unable to start properly

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should it just throw the error? Not sure what the correct way to trigger program exit is here.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think exiting like it is done here: https://github.com/EzraBrooks/karma/blob/ba3da6824371c8824c6b5976b55048e54f0a9924/lib/server.js#L210-L212 should be the right course of action

@EzraBrooks
Copy link
Collaborator Author

What's the best course of action for making a test for this? File I/O has unpredictable execution times, so we should use a flag or event to detect - are we doing something similar elsewhere in the tests that could be mimicked?
Also, it seems like the set timeout on a single test is 2000ms, which might not necessarily be long enough to bundle & write the files.

@dignifiedquire
Copy link
Member

You can increase the timeout by doing

it('is slow', function mytest () {
  this.timeout(5000)
})

For filesystem, we use a mock file system in other unit tests, e.g.

_mocks['graceful-fs'] = mocks.fs.create({

@EzraBrooks EzraBrooks force-pushed the compile-static-resources-on-first-launch branch from 352c4df to e51aca1 Compare November 26, 2017 16:42
@EzraBrooks EzraBrooks force-pushed the compile-static-resources-on-first-launch branch from e51aca1 to e7433fc Compare November 26, 2017 16:45
@EzraBrooks
Copy link
Collaborator Author

Correct me if I'm wrong, but it seems like using a filesystem call makes more sense here than using a mock filesystem since we're looking for the actual existence of these files.

@EzraBrooks
Copy link
Collaborator Author

The Node 6 and 8 jobs on Travis crashed during their package installs for some reason.

@EzraBrooks EzraBrooks changed the title [WIP] refactor: move compile step to first run of server refactor: move compile step to first run of server Nov 26, 2017
@EzraBrooks
Copy link
Collaborator Author

@dignifiedquire Does this look good to you? Travis failed on conditions unrelated to the PR.

@johnjbarton
Copy link
Contributor

The travis build fails with

That's pretty alarming ;-)

@EzraBrooks
Copy link
Collaborator Author

Ah, it failed differently this time.

@Florian-R
Copy link

Florian-R commented Nov 27, 2017

@EzraBrooks Couldn't this be done in a way that don't slow down the first run everytime? Putting the burden of compiling client-side like this to every users for a niche use-case doesn't seems a very nice idea to me.

Also adding browserify as a deps mean adding a gigantic tree to node_modules, slowing further more the CI for consumers of Karma.

@EzraBrooks
Copy link
Collaborator Author

I don't think it's a niche use case to not have a private npm registry and want to work with a fork of a major repository like this. Additionally, it's not going to slow down your CI if you properly cache the static resources on your CI job. It checks for existence of the files - it doesn't just assume they don't exist.

@EzraBrooks
Copy link
Collaborator Author

I queued the Travis job back up and it ran fine. It had errored on an apt install previously for some reason.

@dignifiedquire dignifiedquire merged commit 78ad12f into karma-runner:master Dec 5, 2017
@dignifiedquire
Copy link
Member

Thank you :octocat:

@johnjbarton
Copy link
Contributor

If I understand correctly, this change was made to move a build step from post install to every run? Why? As was pointed out on #2884

NPM has a post-install step for this reason.

@johnjbarton
Copy link
Contributor

Do we know specifically what problems occur with post install?

I think this PR optimizes for a less-used use-case, pull master from github, at the expense of the core use-case, npm install. Building master after pull is extremely common; yes it's an inconvenience but direct pull is not the common case.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants