WIP: Add support for dependencies between startup modules

See StartupMechanism for details.
This commit is contained in:
Jermolene 2014-05-03 16:32:18 +01:00
parent 2f32621024
commit b96aade28a
5 changed files with 93 additions and 4 deletions

View File

@ -1726,12 +1726,62 @@ $tw.boot.startup = function(options) {
if($tw.crypto) {
$tw.crypto.updateCryptoStateTiddler();
}
// Run any startup modules
// Gather up any startup modules
$tw.boot.remainingStartupModules = []; // Array of startup modules
$tw.modules.forEachModuleOfType("startup",function(title,module) {
if(module.startup) {
module.startup();
$tw.boot.remainingStartupModules.push(module);
}
});
// Keep track of the startup tasks that have been executed
$tw.boot.executedStartupModules = Object.create(null);
// Repeatedly execute the next eligible task
$tw.boot.executeNextStartupTask();
};
/*
Execute the remaining eligible startup tasks
*/
$tw.boot.executeNextStartupTask = function() {
// Find the next eligible task
var taskIndex = 0;
while(taskIndex < $tw.boot.remainingStartupModules.length) {
var task = $tw.boot.remainingStartupModules[taskIndex];
if($tw.boot.isStartupTaskEligible(task)) {
// Remove this task from the list
$tw.boot.remainingStartupModules.splice(taskIndex,1);
// Execute it
if(!$tw.utils.hop(task,"synchronous") || task.synchronous) {
task.startup();
if(task.name) {
$tw.boot.executedStartupModules[task.name] = true;
}
return $tw.boot.executeNextStartupTask();
} else {
task.startup(function() {
if(task.name) {
$tw.boot.executedStartupModules[task.name] = true;
}
return $tw.boot.executeNextStartupTask();
});
return true;
}
}
taskIndex++;
}
return false;
};
$tw.boot.isStartupTaskEligible = function(taskModule) {
var dependencies = taskModule.dependencies;
if(dependencies) {
for(var t=0; t<dependencies.length; t++) {
if(!$tw.boot.executedStartupModules[dependencies[t]]) {
return false;
}
}
}
return true;
};
/////////////////////////// Main boot function to decrypt tiddlers and then startup

View File

@ -12,6 +12,10 @@ This is the main application logic for both the client and server
/*global $tw: false */
"use strict";
// Export name and synchronous status
exports.name = "startup";
exports.synchronous = true;
// Set to `true` to enable performance instrumentation
var PERFORMANCE_INSTRUMENTATION = false;
@ -322,6 +326,7 @@ function updateLocationHash() {
targetTiddler = historyList[historyList.length-1].title;
}
$tw.locationHash = "#" + encodeURIComponent(targetTiddler) + ":" + encodeURIComponent($tw.utils.stringifyList(storyList));
// Only change the location hash if we must, thus avoiding unnecessary onhashchange events
if(window.location.hash !== $tw.locationHash) {
window.location.hash = $tw.locationHash;
}

View File

@ -1,6 +1,6 @@
created: 20130825142900000
modified: 20131214093453953
tags: mechanism
modified: 20140502142900000
tags: mechanism dev
title: BootMechanism
type: text/vnd.tiddlywiki
@ -39,3 +39,5 @@ In the browser, `core/boot.js` is packed into a template HTML file that contains
On the server, `core/boot.js` is executed directly. It uses the `Node.js` local file API to load plugins directly from the file system in the `core/modules` directory. The code loading is performed synchronously for brevity (and because the system is in any case inherently blocked until plugins are loaded).
The boot process sets up the `$tw` global variable that is used to store all the state data of the system.
At the end of the boot process the StartupMechanism schedules the execution of startup modules to bring up the rest of TiddlyWiki.

View File

@ -0,0 +1,28 @@
created: 20140502142900000
modified: 20140502142900000
tags: mechanism dev
title: StartupMechanism
type: text/vnd.tiddlywiki
The startup mechanism runs the installed startup modules at the end of the [[boot process|BootMechanism]].
! Startup Modules
Modules with their ''module-type'' field set to `startup`:
* Must expose a `startup` function
** For synchronous startup modules the startup function is called as `startup()`, asynchronous modules are passed a callback they must invoke on completion: `startup(callback)`
* May expose a `name` property that is used to identify the task
* May expose a `dependencies` property containing an array of names of dependent tasks that must be run before this one
! Startup Processing
The startup mechanism begins by sequentially executing the tasks that have no dependencies. It then continues executing tasks as they are unlocked by the completion of their dependencies.
There is no guarantee of the execution order of tasks that share the same dependencies.
! Startup Tasks
The core defines the following sequence of named startup tasks:
|!Task Name |!Description |

View File

@ -12,6 +12,10 @@ Runs Google Analytics with the account number in the tiddler `$:/GoogleAnalytics
/*global $tw: false */
"use strict";
// Export name and synchronous status
exports.name = "google-analytics";
exports.synchronous = true;
var GOOGLE_ANALYTICS_ACCOUNT = "$:/GoogleAnalyticsAccount",
GOOGLE_ANALYTICS_DOMAIN = "$:/GoogleAnalyticsDomain";