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

Client side compile for simulator - faster simulator #238

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
Open
24 changes: 24 additions & 0 deletions modules/devkit-simulator-client/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,30 @@ exports.onLaunch = function () {
GLOBAL.NATIVE.onBackButton && GLOBAL.NATIVE.onBackButton(evt);
});

/** Puts preserveCache on localStorage so that jsio knows to preserve (and then request)
suggestions next load. Optionally also sets partialLoad, which causes jsio to wait for
a partialLoadContinue signal to actually load the app, after preloading suggestions. */
channel.on('reload', function (data, req) {
localStorage.setItem(jsio.__env.getNamespace('preserveCache'), true);

if (data) {
if (data.partialLoad) {
localStorage.setItem(jsio.__env.getNamespace('partialLoad'), true);
}
}

req.send(true);
});

/** partialLoadContinue is to be used in conjunction with partialLoad */
channel.on('partialLoadContinue', function (data, req) {
var def = window._continueLoadDefer;
if (def) {
def.resolve();
}
req.send(true);
});

channel.on('screenshot', function (data, req) {
devkit.debugging.screenshot(function (err, res) {
if (err) {
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"bluebird": "^2.9.24",
"body-parser": "1.x",
"chalk": "^1.0.0",
"chokidar": "^1.0.5",
"compression": "^1.4.3",
"express": "4.x",
"ff": "^0.2.1",
Expand Down
3 changes: 1 addition & 2 deletions src/build/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,8 @@ exports.build = function (appPath, argv, cb) {
// ONLY print config to stdout
process.stdout.write(JSON.stringify(merge({title: app.manifest.title}, config)));
process.exit(0);
} else {
require('./steps/logConfig').log(app, config, f());
}
require('./steps/logConfig').log(app, config, f());
}, function () {
require('./steps/executeTargetBuild').build(app, config, f());
}, function () {
Expand Down
155 changes: 145 additions & 10 deletions src/serve/appRoutes.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,14 @@ var jvmtools = require('../jvmtools');
var logging = require('../util/logging');
var buildQueue = require('./buildQueue');

var chokidar = require('chokidar');

var logger = logging.get('routes');

var HOME = process.env.HOME
|| process.env.HOMEPATH
|| process.env.USERPROFILE;
var ROUTE_INACTIVE_TIME_LIMIT = 30 * 60 * 1000;

exports.addToAPI = function (opts, api) {

Expand Down Expand Up @@ -53,6 +56,7 @@ exports.addToAPI = function (opts, api) {
res.json(mountInfo);
})
.catch(function (e) {
logger.error('Error mounting app', e.stack);
res.status(500).send({
message: e.message,
stack: e.stack
Expand All @@ -70,13 +74,13 @@ exports.addToAPI = function (opts, api) {
return mountAppFromRequest(opts)
.then(function (mountInfo) {
var buildOpts = {
target: opts.target,
scheme: opts.scheme,
simulated: true,
simulateDeviceId: opts.deviceId,
simulateDeviceType: opts.deviceType,
output: mountInfo.buildPath
};
target: opts.target,
scheme: opts.scheme,
simulated: true,
simulateDeviceId: opts.deviceId,
simulateDeviceType: opts.deviceType,
output: mountInfo.buildPath
};

return buildQueue
.add(mountInfo.appPath, buildOpts)
Expand Down Expand Up @@ -133,24 +137,95 @@ exports.addToAPI = function (opts, api) {
});
}

// Promises that resolve with mount info once ready
var _mountedApps = {};
// Map of appId -> app
var _availableSimulatorApps = {};
var getAppByPath = function(appPath) {
for (var appId in _availableSimulatorApps) {
var app = _availableSimulatorApps[appId];
if (app.appPath === appPath) {
return app;
}
}
return null;
};

baseApp.use('/apps/:appId', function(req, res, next) {
var app = _availableSimulatorApps[req.params.appId];
if (app) {
app(req, res, next);
} else {
next();
}
});

baseApp.io.on('connection', function(socket) {
logger.info('socket connected');

socket.on('watch', function(appPath) {
// Add this socket to the app
var app = getAppByPath(appPath);
if (app) {
app.sockets.push(socket);
}
});

socket.on('disconnect', function() {
logger.info('socket disconnect');
});

});

function mountApp(appPath, buildPath) {
var routeId = generateRouteId(appPath);

if (!_mountedApps[appPath]) {
_mountedApps[appPath] = apps.get(appPath)
.then(function mountExtensions(app) {
var routeId = generateRouteId(appPath);
var simulatorApp = express();
baseApp.use('/apps/' + routeId, simulatorApp);

// Special case src directories
simulatorApp.use(
'/modules',
express.static(path.join(appPath, 'modules'))
);
simulatorApp.use(
'/src',
express.static(path.join(appPath, 'src'))
);
simulatorApp.use(
'/resources',
express.static(path.join(appPath, 'resources'))
);

// Static serve builds
simulatorApp.use('/', express.static(buildPath));

addSimulatorAPI(simulatorApp);

var modules = app.getModules();
var debuggerURLs = {};
var simulatorURLs = {};
var loadExtension = function (module) {
// All modules get a chance to add "resources" routes
var buildExtension = module.loadExtension('build');
if (buildExtension) {
var resources = buildExtension.getResourceDirectories();
if (resources) {
var prefix = '/modules/' + module.name;
resources.forEach(function(resource) {
simulatorApp.use(
path.join(prefix, resource.target),
express.static(resource.src)
);
});
}
}

var extension = module.loadExtension('debugger');
if (!extension || !extension.getMiddleware) { return; }

try {
var routes = extension.getMiddleware(require('../api'), app);
if (!routes) { return; }
Expand Down Expand Up @@ -181,6 +256,35 @@ exports.addToAPI = function (opts, api) {

baseModules.forEach(function (module) { loadExtension(module); });

// Add socket connection
simulatorApp.sockets = [];
simulatorApp.socketEmit = function(name, data) {
simulatorApp.sockets.forEach(function(socket) {
socket.emit(name, data);
});
};

// Everything is set, add some file watchers
simulatorApp.watchers = [];
simulatorApp.watchers.push(
chokidar.watch(
[
path.join(appPath, 'manifest.json'),
path.join(appPath, 'src'),
path.join(appPath, 'resources')
],
{ recursive: true, followSymLinks: false, persistent: true, ignoreInitial: true }
).on('all', function(event, path) {
logger.info(routeId + ': changed ' + path);
simulatorApp.socketEmit('watch:changed', path);
})
);

// Meta data
simulatorApp.appPath = appPath;

// Add to available routes, return info
_availableSimulatorApps[routeId] = simulatorApp;
return {
id: routeId,
url: '/apps/' + routeId + '/',
Expand All @@ -192,7 +296,38 @@ exports.addToAPI = function (opts, api) {
});
}

return Promise.resolve(_mountedApps[appPath]);
// Remove and clean up the routes after a bit of inactivity
var mountedApp = _mountedApps[appPath];
// remove the old timeout
if (mountedApp.cleanupTimeout) {
clearTimeout(mountedApp.cleanupTimeout);
}
mountedApp.cleanupTimeout = setTimeout(
unmountApp.bind(null, appPath, routeId),
ROUTE_INACTIVE_TIME_LIMIT
);

return Promise.resolve(mountedApp);
}

function unmountApp(appPath, routeId) {
logger.info('Shutting down route for: ' + appPath + ' (' + routeId + ')');

var app = _availableSimulatorApps[routeId];

// Close sockets
app.sockets.forEach(function(socket) {
socket.disconnect();
});

// Remove watchers
app.watchers.forEach(function(watcher) {
watcher.close();
});

// Remove app routes
delete _availableSimulatorApps[routeId];
delete _mountedApps[appPath];
}

// tracks used route uuids
Expand Down
6 changes: 2 additions & 4 deletions src/serve/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,11 @@ var Z_BEST_COMPRESSION = 9;
exports.serveWeb = function (opts, cb) {
var port = opts.port;

// common.track("BasilServe");
var app = express();
var server = http.Server(app);

app.io = require('socket.io')(server);

// var deviceManager = require('./deviceManager').get();
// deviceManager.init(app.io);

app.use(compression({level: Z_BEST_COMPRESSION}));

app.use(function noCacheControl(req, res, next) {
Expand All @@ -54,6 +50,8 @@ exports.serveWeb = function (opts, cb) {
app.use('/compile/', importMiddleware(getPath('static/')));

// serve static files
var devkitPath = path.resolve(__dirname, '..', '..');
app.use('/devkit/', express.static(devkitPath));
Copy link
Contributor

Choose a reason for hiding this comment

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

this feels a little excessive, do we need to serve the entire devkit directory?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Serving the entire thing because its part of the available path ingame, I
think. If we don't need devkit on the games path, we don't have to serve
the whole thing (or if there are specific subpaths)
On Jul 29, 2015 1:23 PM, "Martin Hunt" [email protected] wrote:

In src/serve/index.js
#238 (comment):

@@ -54,6 +50,8 @@ exports.serveWeb = function (opts, cb) {
app.use('/compile/', importMiddleware(getPath('static/')));

// serve static files

  • var devkitPath = path.resolve(__dirname, '..', '..');
  • app.use('/devkit/', express.static(devkitPath));

this feels a little excessive, do we need to serve the entire devkit
directory?


Reply to this email directly or view it on GitHub
https://github.com/gameclosure/devkit/pull/238/files#r35807066.

Copy link
Contributor

Choose a reason for hiding this comment

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

Is it really? I thought only module code was available, and then only the folders specified in a module's package config.

app.use('/', express.static(getPath('static')));

// Serve
Expand Down
Loading