The Config Server
All of the environment's active configuration is hosted at httpl://config.env. It hosts the /apps collection, which provides the "Applications" interface and their JSON configs.
The only other environment server at this time is httpl://storage.env, a sessionStorage wrapper.The /apps collection also hosts an event-stream which emits an "update" event when applications are added, removed, or reloaded (which happens on every config change).
// listen for new applications
local.http.subscribe('httpl://config.env/apps')
.on('update', updateSources);
updateSources();
This is how the Search application becomes aware of new apps in the environment. If you're not familiar with Server-Sent Events, this post gives a brief introduction.
Finding the Data to Index
Every application defines a "startpage," which is the primary entry-point for its APIs. The Search application uses that URL to identify each source.
function updateSources() {
local.http.dispatch({
url:'httpl://config.env/apps',
headers:{ accept:'application/json' }
}).then(
function(res) {
var cfgs = res.body;
for (var appId in cfgs)
addSource(cfgs[appId].startpage); // <-- here
},
function(res) {
console.log('Failed to fetch active applications');
}
);
}
Grimwire defines a custom rel-type for exported searchable data: http://grimwire.com/rel/index. The Search app checks each application startpage for a link to that relation.
function resolveSourceIndex(startPage) {
return local.http.navigator(startPage)
.relation('http://grimwire.com/rel/index')
.resolve(); // just give me the URL
}
If you're not familiar with the navigator, there's a small introduction here. This function will generate one HEAD request to the startpage URL, then check the returned links for a rel="http://grimwire.com/rel/index".
Getting the Data
The next step is to get the docs and to watch them for updates in the future.
function addSource(sourceUrl) {
resolveSourceIndex(sourceUrl).succeed(function(indexUrl) {
getSourceDocuments(sourceUrl, indexUrl);
local.http.subscribe(indexUrl).on('update', function() {
getSourceDocuments(sourceUrl, indexUrl);
});
});
}
This allows applications to trigger re-indexing so they can maintain freshness.
getSourceDocuments() issues a GET request for json. It expects an object to be returned with the items attribute populated with an array of objects, according to this schema:
{
items: required array of {
href: required url (primary key),
title: required string,
desc: optional string,
category: optional string
}
}
This data will be used to populate the search dataset and to render results. The use of this schema is implied by the "http://grimwire.com/rel/index" relation, which is why the custom relation is used instead of the standard "index" relation.
Wrapping Up
The two tools in use here are Server-Sent Events for syncing and the navigator for discovery. By listening to the event-stream of the config server's applications, the Search app can react to new programs. Likewise, by listening to the indexes of the apps, Search can keep its data-set fresh. Meanwhile, by looking for the "http://grimwire.com/rel/index" relation in Link headers, Search can discover what data to index and expect a specific schema.
These techniques can be used in your applications, and are not restricted to Worker servers. Server-Sent Events and the Link response header are HTML5 standards, so any remote host can leverage the same tools.
Read more at github.com/grimwire/grimwire.
No comments:
Post a Comment