etch/etch — pull request #19 by jaeheung90 (2013-10-11 03:39:34+00:00)
Title: Re-initialize global vars after excution of external sources

Changes made to some global variables by external sources can cause serious complications because Etch external scripts are executed via eval method, repeatedly in a single worker process.

1\. $LOAD_PATH ($:)

Many Etch scripts start with a line like this:

$: << @sitelibbase # or any other directory

It works fine in regular Ruby scripts, but not in Etch scripts.
Problems:
a. New values are appended at the end, and almost always they are hidden by the older ones, leaving the script with an old version of the module.
b. $LOAD_PATH grows indefinitely. I saw some workers with more than 300K entries, most of them are duplicates.
c. A lot of CPU cycles are wasted by every 'require' call to go through the long list of non-existent directories when the old tags are purged. In some instances I monitored, this waste reached over 50% of total CPU resource.

This can be avoided by doing something like this, instead of touching $LOAD_PATH:

require File.join(@sitelibbase, 'mymodule')

However I think Etch server shouldn't let it happen in the first place.
\
2\. $LOADED_FEATURES

'require' does not load a file that is already loaded. (Tracked by $LOADED_FEATURES)
For example, in a worker process, an external script calls:

require ''v1/myclass"

second one calls:

require "v2/myclass"

and third one requires the old version:

require ''v1/myclass"

The last require doesn't load "v1/myclass" since it's been previously loaded.
This behavior combined with multiple versions of sitelibs modules, makes the newest version always effective because new tags are available and being loaded periodically.

This defies the purpose of having multiple sets of sitelibs.
Moreover it can be dangerous when someone tests a new dev version of a sitelib module in a branch; probably he/she would test just once in a single test host with "--tag branches/mybranch", but it becomes the newest version and remains effective in the worker process, affecting subsequent requests from prod hosts served by the same worker process, until another new version is loaded.