blob: 2baae1e4371c9b6e9078d11969e742b292fcc60a [file] [log] [blame]
/*
* Copyright (c) 2013 DataTorrent, Inc. ALL Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*global settings, console, angular, jQuery, _*/
(function () {
'use strict';
angular.module('socket', [])
.factory('visibly', function ($window) {
return $window.visibly;
})
.provider('socket', function () {
var webSocketURL;
var webSocketObject; // for testing only
return {
$get: function ($q, $rootScope, $timeout, visibly) {
if (!webSocketURL && !webSocketObject) {
throw 'WebSocket URL is not defined';
}
var socket = !webSocketObject ? new WebSocket(webSocketURL) : webSocketObject;
var deferred = $q.defer();
socket.onopen = function () {
deferred.resolve();
$rootScope.$apply();
jQuery.pnotify({
title: 'WebSocket',
text: 'WebSocket connection established.',
type: 'success',
delay: 2000,
icon: false,
history: false
});
};
var webSocketError = false;
socket.onclose = function () {
if (!webSocketError) {
jQuery.pnotify({
title: 'WebSocket Closed',
text: 'WebSocket connection has been closed. Try refreshing the page.',
type: 'error',
icon: false,
hide: false,
history: false
});
}
};
//TODO
socket.onerror = function () {
webSocketError = true;
jQuery.pnotify({
title: 'WebSocket Error',
text: 'WebSocket error. Try refreshing the page.',
type: 'error',
icon: false,
hide: false,
history: false
});
};
var topicMap = {}; // topic -> [callbacks] mapping
var stopUpdates = false;
socket.onmessage = function (event) {
if (stopUpdates) { // stop updates if page is inactive
return;
}
var message = JSON.parse(event.data);
var topic = message.topic;
if (topicMap.hasOwnProperty(topic)) {
topicMap[topic].fire(message);
}
};
var timeoutPromise;
visibly.onHidden(function () {
timeoutPromise = $timeout(function () {
stopUpdates = true;
timeoutPromise = null;
}, 60000);
});
visibly.onVisible(function () {
/*
if (stopUpdates && !webSocketError) {
jQuery.pnotify({
title: 'Warning',
text: 'Page has not been visible for more than 60 seconds. WebSocket real-time updates have been suspended to conserve system resources. ' +
'Refreshing the page is recommended.',
type: 'warning',
icon: false,
hide: false,
history: false
});
}
*/
stopUpdates = false;
if (timeoutPromise) {
$timeout.cancel(timeoutPromise);
}
});
return {
send: function (message) {
var msg = JSON.stringify(message);
deferred.promise.then(function () {
console.log('send ' + msg);
socket.send(msg);
});
},
publish: function(topic, data) {
var message = { "type": "publish", "topic": topic, "data": data };
this.send(message);
},
subscribe: function (topic, callback, $scope) {
var callbacks = topicMap[topic];
if (!callbacks) {
var message = { type: 'subscribe', topic: topic }; // subscribe message
this.send(message);
callbacks = jQuery.Callbacks();
topicMap[topic] = callbacks;
}
callbacks.add(callback);
if ($scope) {
$scope.$on('$destroy', function () {
this.unsubscribe(topic, callback);
}.bind(this));
}
},
unsubscribe: function (topic, callback) {
if (topicMap.hasOwnProperty(topic)) {
var callbacks = topicMap[topic];
callbacks.remove(callback); //TODO remove topic from topicMap if callbacks is empty
}
}
};
},
setWebSocketURL: function (wsURL) {
webSocketURL = wsURL;
},
setWebSocketObject: function (wsObject) {
webSocketObject = wsObject;
}
};
});
})();