summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/lib/utils/socket
diff options
context:
space:
mode:
authorLuke "Jared" Bennett <lbennett@gitlab.com>2017-05-20 20:05:31 +0100
committerLuke "Jared" Bennett <lbennett@gitlab.com>2017-05-20 20:56:10 +0100
commit71c859616524a5af903d3c736e93d7655e8a144d (patch)
treeb09dbfcf20fe8230fb5e9b38e206ce0a5abb7623 /app/assets/javascripts/lib/utils/socket
parentf5f99c9037e52392ca388b6e839d93df88421c31 (diff)
downloadgitlab-ce-sockets-frontend.tar.gz
Added SocketManager, SubscriptionStore, Subscription, VisibilitySocketManager and refactored currently instances of Pollsockets-frontend
Diffstat (limited to 'app/assets/javascripts/lib/utils/socket')
-rw-r--r--app/assets/javascripts/lib/utils/socket/socket_manager.js108
-rw-r--r--app/assets/javascripts/lib/utils/socket/subscription.js68
-rw-r--r--app/assets/javascripts/lib/utils/socket/subscription_store.js27
-rw-r--r--app/assets/javascripts/lib/utils/socket/visibility_socket_manager.js24
4 files changed, 227 insertions, 0 deletions
diff --git a/app/assets/javascripts/lib/utils/socket/socket_manager.js b/app/assets/javascripts/lib/utils/socket/socket_manager.js
new file mode 100644
index 00000000000..2f4f428ebee
--- /dev/null
+++ b/app/assets/javascripts/lib/utils/socket/socket_manager.js
@@ -0,0 +1,108 @@
+import socketIO from 'socket.io-client';
+import Socket from 'socket.io-client/lib/socket';
+import Subscription from './subscription';
+import SubscriptionStore from './subscription_store';
+
+const SocketManager = {
+ socketPath: '',
+ socket: {},
+ store: SubscriptionStore,
+ subscriptionsCount: 0,
+
+ init(socketPath) {
+ this.socketPath = socketPath;
+
+ this.removeAll();
+ },
+
+ connect() {
+ if (this.socket instanceof Socket) return Promise.resolve();
+
+ return new Promise((resolve, reject) => {
+ this.socket = socketIO(this.socketPath);
+
+ this.socket.on('connect', resolve);
+ this.socket.on('connect_error', reject);
+ this.socket.on('connect_timeout', reject);
+ });
+ },
+
+ subscribe(endpointOrSubscription, data, callbacks) {
+ this.connect().then(() => {
+ const subscription = this.getSubscription(endpointOrSubscription, data, callbacks);
+
+ subscription.subscribe();
+
+ return subscription;
+ }).catch((error) => {
+ // temporary
+ // eslint-disable-next-line no-console
+ console.log('connect error', error);
+ });
+ },
+
+ remove(subscription) {
+ subscription.unsubscribe();
+
+ this.store.remove(subscription);
+ },
+
+ unsubscribeAll() {
+ const subscriptions = this.store.getAll();
+
+ if (!subscriptions) return;
+
+ subscriptions.forEach(subscription => subscription.unsubscribe());
+ },
+
+ subscribeAll() {
+ const subscriptions = this.store.getAll();
+
+ if (!subscriptions) return;
+
+ subscriptions.forEach(subscription => subscription.subscribe());
+ },
+
+ removeAll() {
+ this.unsubscribeAll();
+ this.store.removeAll();
+ },
+
+ getSubscription(endpointOrSubscription, data, callbacks) {
+ let subscription;
+
+ if (endpointOrSubscription instanceof Subscription) {
+ subscription = endpointOrSubscription;
+ } else {
+ subscription = this.createSubscription({
+ endpoint: endpointOrSubscription,
+ data,
+ callbacks,
+ });
+ }
+
+ return subscription;
+ },
+
+ createSubscription({
+ endpoint,
+ data,
+ callbacks,
+ }) {
+ this.subscriptionsCount += 1;
+
+ const subscription = new Subscription({
+ endpoint,
+ data,
+ callbacks,
+ socket: this.socket,
+ id: this.subscriptionsCount,
+ });
+
+ this.store.add(subscription);
+
+ return subscription;
+ },
+};
+
+export default SocketManager;
diff --git a/app/assets/javascripts/lib/utils/socket/subscription.js b/app/assets/javascripts/lib/utils/socket/subscription.js
new file mode 100644
index 00000000000..46373a78acb
--- /dev/null
+++ b/app/assets/javascripts/lib/utils/socket/subscription.js
@@ -0,0 +1,68 @@
+class Subscription {
+ constructor({
+ id,
+ endpoint,
+ data,
+ socket,
+ callbacks,
+ }) {
+ this.id = id;
+ this.endpoint = endpoint;
+ this.data = data;
+ this.socket = socket;
+ this.updateCallback = callbacks.updateCallback;
+ this.errorCallback = callbacks.errorCallback;
+
+ this.setPayload();
+ this.setEventNames();
+ }
+
+ subscribe() {
+ this.socket.emit(this.eventNames.subscribe, this.payload, this.acknowledge);
+
+ this.bindListeners();
+ }
+
+ unsubscribe() {
+ this.socket.emit(this.eventNames.unsubscribe, this.payload, this.acknowledge);
+
+ this.unbindListeners();
+ }
+
+ bindListeners() {
+ this.socket.on(this.eventNames.update, this.updateCallback);
+ this.socket.on(this.eventNames.error, this.errorCallback);
+ }
+
+ unbindListeners() {
+ this.socket.removeListener(this.eventNames.update, this.updateCallback);
+ this.socket.removeListener(this.eventNames.error, this.errorCallback);
+ }
+
+ setPayload() {
+ this.payload = {
+ id: this.id,
+ endpoint: this.endpoint,
+ data: this.data,
+ };
+ }
+
+ setEventNames() {
+ this.eventNames = {
+ subscribe: `subscribe:${this.endpoint}`,
+ unsubscribe: `unsubscribe:${this.endpoint}`,
+ update: `update:${this.id}`,
+ error: `error:${this.id}`,
+ };
+ }
+
+ acknowledge(response, ...args) {
+ if (response.error) this.errorCallback(response.error, ...args);
+
+ // temporary
+ // eslint-disable-next-line no-console
+ console.log('ACK', ...args);
+ }
+}
+
+export default Subscription;
diff --git a/app/assets/javascripts/lib/utils/socket/subscription_store.js b/app/assets/javascripts/lib/utils/socket/subscription_store.js
new file mode 100644
index 00000000000..06b43da1360
--- /dev/null
+++ b/app/assets/javascripts/lib/utils/socket/subscription_store.js
@@ -0,0 +1,27 @@
+const SocketStore = {
+ subscriptions: {},
+
+ add(subscription) {
+ this.subscriptions[subscription.id] = subscription;
+
+ return subscription;
+ },
+
+ remove(subscription) {
+ delete this.subscriptions[subscription.id];
+ },
+
+ get(subscriptionID) {
+ return this.subscriptions[subscriptionID];
+ },
+
+ getAll() {
+ Object.values(this.subscriptions);
+ },
+
+ removeAll() {
+ this.subscriptions = {};
+ },
+};
+
+export default SocketStore;
diff --git a/app/assets/javascripts/lib/utils/socket/visibility_socket_manager.js b/app/assets/javascripts/lib/utils/socket/visibility_socket_manager.js
new file mode 100644
index 00000000000..d363ae4bd44
--- /dev/null
+++ b/app/assets/javascripts/lib/utils/socket/visibility_socket_manager.js
@@ -0,0 +1,24 @@
+import SocketManager from './socket_manager';
+
+const VisibilitySocketManager = {
+ init(socketPath) {
+ super.init(socketPath);
+
+ document.addEventListener('visibilitychange', () => this.toggleAllSockets());
+ },
+
+ toggleAllSockets() {
+ if (document.hidden) {
+ super.unsubscribeAll();
+ } else {
+ super.subscribeAll();
+ }
+ },
+};
+
+Object.setPrototypeOf(VisibilitySocketManager, SocketManager);
+
+// temporary
+VisibilitySocketManager.init('/broker');
+
+export default VisibilitySocketManager;