[Telemetry] Bring in telemetry bundle

Bring in initial state for the platform/telemetry
bundle, which provides general-purpose telemetry
conventions and infrastructure to support creating
domain objects which expose telemetry data.
WTD-575.
This commit is contained in:
Victor Woeltjen
2014-11-28 16:06:54 -08:00
parent 0bacc03e58
commit 51de44a3e5
7 changed files with 469 additions and 0 deletions

View File

@ -0,0 +1,209 @@
/*global define,Promise*/
/**
* Module defining TelemetryController. Created by vwoeltje on 11/12/14.
*/
define(
[],
function () {
"use strict";
/**
* Serves as a reusable controller for views (or parts of views)
* which need to issue, use telemetry controls.
*
* @constructor
*/
function TelemetryController($scope, $q, $timeout, $log) {
/*
Want a notion of "the data set": All the latest data.
It can look like:
{
"source": {
"key": {
...Telemetry object...
}
}
}
Then, telemetry controller should provide:
{
// Element for which there is telemetry data available
elements: [ { <-- the objects to view
name: ...human-readable
metadata: ...
object: ...the domain object
data: ...telemetry data for that element
} ]
}
*/
var self = {
ids: [],
response: {},
request: {},
pending: 0,
metadatas: [],
interval: 1000,
refreshing: false,
broadcasting: false
};
function doBroadcast() {
if (!self.broadcasting) {
self.broadcasting = true;
$timeout(function () {
self.broadcasting = false;
$scope.$broadcast("telemetryUpdate");
});
}
}
function requestTelemetryForId(id, trackPending) {
var responseObject = self.response[id],
domainObject = responseObject.domainObject,
telemetry = domainObject.getCapability('telemetry');
function storeData(data) {
self.pending -= trackPending ? 1 : 0;
responseObject.data = data;
doBroadcast();
}
self.pending += trackPending ? 1 : 0;
if (!telemetry) {
$log.warn([
"Expected telemetry capability for ",
id,
" but found none. Cannot request data."
].join(""));
return;
}
return $q.when(telemetry.requestData(self.request))
.then(storeData);
}
function requestTelemetry(trackPending) {
return $q.all(self.ids.map(function (id) {
return requestTelemetryForId(id, trackPending);
}));
}
function promiseRelevantDomainObjects() {
var domainObject = $scope.domainObject;
if (!domainObject) {
return $q.when([]);
}
return $q.when(domainObject.useCapability(
"delegation",
"telemetry"
)).then(function (result) {
var head = domainObject.hasCapability("telemetry") ?
[ domainObject ] : [],
tail = result || [];
return head.concat(tail);
});
}
function buildResponseContainer(domainObject) {
var telemetry = domainObject &&
domainObject.getCapability("telemetry"),
metadata;
if (telemetry) {
metadata = telemetry.getMetadata();
self.response[domainObject.getId()] = {
name: domainObject.getModel().name,
domainObject: domainObject,
metadata: metadata,
pending: 0,
data: {}
};
} else {
$log.warn([
"Expected telemetry capability for ",
domainObject.getId(),
" but none was found."
].join(""));
}
}
function buildResponseContainers(domainObjects) {
domainObjects.forEach(buildResponseContainer);
self.ids = domainObjects.map(function (obj) {
return obj.getId();
});
self.metadatas = self.ids.map(function (id) {
return self.response[id].metadata;
});
// Issue a request for the new objects, if we
// know what our request looks like
if (self.request) {
requestTelemetry(true);
}
}
function getTelemetryObjects() {
promiseRelevantDomainObjects().then(buildResponseContainers);
}
function startTimeout() {
if (!self.refreshing && self.interval !== undefined) {
self.refreshing = true;
$timeout(function () {
if (self.request) {
requestTelemetry(false);
}
self.refreshing = false;
startTimeout();
}, 1000);
}
}
$scope.$watch("domainObject", getTelemetryObjects);
startTimeout(); // Begin refreshing
return {
getMetadata: function () {
return self.metadatas;
},
getTelemetryObjects: function () {
return self.ids.map(function (id) {
return self.response[id].domainObject;
});
},
getResponse: function getResponse(arg) {
var id = arg && (typeof arg === 'string' ?
arg : arg.getId());
if (id) {
return (self.response[id] || {}).data;
}
return (self.ids || []).map(getResponse);
},
isRequestPending: function () {
return self.pending > 0;
},
requestData: function (request) {
self.request = request || {};
return requestTelemetry(true);
},
setRefreshInterval: function (durationMillis) {
self.interval = durationMillis;
startTimeout();
}
};
}
return TelemetryController;
}
);