Skip to content

Instantly share code, notes, and snippets.

@shama
Created December 19, 2012 19:11
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save shama/4339559 to your computer and use it in GitHub Desktop.
Save shama/4339559 to your computer and use it in GitHub Desktop.

Problem

Some tasks utilize the watch to trigger an event, ie: live reload. With Grunt v0.3, those tasks on first run would create a variable, ie servers. Then subsequently ran by the watch task would check if the variable exists and then use it. Since the new watch spawns tasks, this is no longer possible.

Solutions Proposed

A) Have watch trigger a grunt.event

Pros

  • Tasks would only have to be ran once (less configuration)
  • Could also solve the common request for a task to know which files have been modified
  • Simple to implement

Cons

  • Watch task isn't as generalized as tasks now rely directly on the watch task

B) Create a socket for child to communicate with parent

A demo of this is here albeit not exactly what @cowboy proposed. When the watch runs the child, the child can inform the parent, ie: okay now reload.

Pros

  • Operates very similiarly to previous functionality (requiring minimal changes from tasks authors)
  • Keeps the watch generalized. Only relies on the watch to run the child task

Cons

  • Relies on opening another port
  • A bit complicated and could lead to unforseen issues
  • Not that speedy on Windows

C) watch task option to run tasks under current context rather than spawn

Pros

  • Allows the watch task to run like Grunt@0.3 requiring 0 changes from plugin authors
  • Could get a list of impacted files

Cons

  • Tasks rely on a user setting a watch config to work
  • Tasks fail in ways Grunt can't stop. One task failure can kill the entire watch
  • Tasks step on each other as they are in the same context. For test runners this is bad.

D) Specify parent and child targets

First runs the parent and the watch runs the child. The child communicates with the parent by writing to a file or database.

Pros

  • Task only relies on the watch to run tasks

Cons

  • A lot of configuration required

E) Have the watch append a cli arg to child tasks

So tasks could know they've been spawned by the watch by checking, ie: grunt.option('spawned-by-watch');

Pros

  • Easy to implement

Cons

  • Watch task isnt as generalized as tasks now rely on this being done by the watch
  • Child task still doesn't have access to communicate with parent

F) Mix C and A

Emit events and allow watch to be configured to run under the same context

@sleeper
Copy link

sleeper commented Dec 19, 2012

Some comments:
A - Cons: not sure of what you meant. Actually watch task is generalized: the tasks depending on watch are potentially not generalized

B- I'm not a Windows expert, but older version of Windows were not really speedy when you had to spawn processes ... Could also be a cons.

C - Pros: could also allow to get the list of impacted files

What about doing a mix of the solutions (e.g. solution G):

  1. Allow to chose on a per target basis to spawn or not spawn
  2. Always emit events

@shama
Copy link
Author

shama commented Dec 19, 2012

Updated the gist, thanks @sleeper.

@manuel-woelker
Copy link

Concerning A: How would the inter process communication work in that scenario? I assume there still are two processes, which would mean that the grunt.event would need to be propagated from the watch process to the spawned process.

Regarding coupling these tasks to watch: How about emitting generalized events like e.g. "changedFiles". This would allow this to work even with alternative watch implementations.

Another option might be to let the plugin handle this itself, but provide a standard library that allows communication with spawned processes (via sockets, pipes, files, http, etc.), to make it as easy as possible for plugin authors.

Personally, I think triggered tasks should be run in their own process. It is always quite annoying when you make some code changes that all don't seem to work, only to find out that the background compilation job hasn't been running the last 10 minutes, since some task failed and took down the whole process.

@manuel-woelker
Copy link

Besides reload, what are some other use cases that require running a stateful process in the background, which is triggered by watch?

I couldn't think of any of the top of my head, and for reload there might a relatively simple solution (cf. manuel-woelker/grunt-reload@f438be5). So maybe this isn't a problem after all.

@shama
Copy link
Author

shama commented Jan 4, 2013

Sorry @manuel-woelker, I didn't get a notification of your comments.

Concering A: The task and the watch would be in the same context. Ran like: grunt reload watch. The reload task would listen for the events to reload the server (the watch would never run the reload task).

AFAIK, the reload task is the only task that needs this. I'll give you solution a try... if it works as needed without doing any of the above you'll be my hero :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment