blob: 821da41c8d7eb16502d3cb1be5e3958d7ebd4039 [file] [log] [blame]
Matteo Scandolo968e7f22017-03-03 11:49:18 -08001import * as _ from 'lodash';
Matteo Scandoloa160eef2017-03-06 17:21:26 -08002import {Observable, BehaviorSubject, Subscription} from 'rxjs';
Matteo Scandoloa62adbc2017-03-02 15:37:34 -08003import {IXosModelStoreService} from '../../datasources/stores/model.store';
Matteo Scandolo968e7f22017-03-03 11:49:18 -08004import {
5 IXosServiceGraph, IXosServiceModel, IXosTenantModel, IXosCoarseGraphData,
6 IXosServiceGraphNode, IXosServiceGraphLink
7} from '../interfaces';
Matteo Scandoloa62adbc2017-03-02 15:37:34 -08008import {IXosDebouncer} from '../../core/services/helpers/debounce.helper';
9export interface IXosServiceGraphStore {
10 get(): Observable<IXosServiceGraph>;
Matteo Scandolo968e7f22017-03-03 11:49:18 -080011 getCoarse(): Observable<IXosServiceGraph>;
Matteo Scandoloa160eef2017-03-06 17:21:26 -080012 dispose(): void;
Matteo Scandoloa62adbc2017-03-02 15:37:34 -080013}
14
15export class XosServiceGraphStore implements IXosServiceGraphStore {
16 static $inject = [
17 '$log',
18 'XosModelStore',
19 'XosDebouncer'
20 ];
Matteo Scandolo968e7f22017-03-03 11:49:18 -080021
22 // graph data store
23 private graphData: BehaviorSubject<IXosCoarseGraphData> = new BehaviorSubject({
24 services: [],
25 tenants: []
26 });
27
28 // reprentations of the graph as D3 requires
29 private d3CoarseGraph = new BehaviorSubject({});
30 private d3FineGrainedGraph = new BehaviorSubject({});
Matteo Scandoloa62adbc2017-03-02 15:37:34 -080031
32 // storing locally reference to the data model
33 private services;
34 private tenants;
35
36 // debounced functions
37 private handleData;
38
39 // datastore
Matteo Scandoloa160eef2017-03-06 17:21:26 -080040 private ServiceSubscription: Subscription;
41 private TenantSubscription: Subscription;
Matteo Scandoloa62adbc2017-03-02 15:37:34 -080042
43 constructor (
44 private $log: ng.ILogService,
45 private XosModelStore: IXosModelStoreService,
46 private XosDebouncer: IXosDebouncer
47 ) {
48
Matteo Scandolo968e7f22017-03-03 11:49:18 -080049 this.$log.info(`[XosServiceGraphStore] Setup`);
50
Matteo Scandoloa62adbc2017-03-02 15:37:34 -080051 // we want to have a quiet period of 500ms from the last event before doing anything
Matteo Scandolo968e7f22017-03-03 11:49:18 -080052 this.handleData = this.XosDebouncer.debounce(this._handleData, 500, this, false);
Matteo Scandoloa62adbc2017-03-02 15:37:34 -080053
Matteo Scandoloa62adbc2017-03-02 15:37:34 -080054
Matteo Scandolo968e7f22017-03-03 11:49:18 -080055 // observe models and populate graphData
Matteo Scandoloa160eef2017-03-06 17:21:26 -080056 this.ServiceSubscription = this.XosModelStore.query('Service', '/core/services')
Matteo Scandoloa62adbc2017-03-02 15:37:34 -080057 .subscribe(
58 (res) => {
59 this.combineData(res, 'services');
60 },
61 (err) => {
Matteo Scandoloa160eef2017-03-06 17:21:26 -080062 this.$log.error(`[XosServiceGraphStore] graphData Observable: `, err);
Matteo Scandoloa62adbc2017-03-02 15:37:34 -080063 }
64 );
65
Matteo Scandoloa160eef2017-03-06 17:21:26 -080066 this.TenantSubscription = this.XosModelStore.query('Tenant', '/core/tenants')
Matteo Scandoloa62adbc2017-03-02 15:37:34 -080067 .subscribe(
68 (res) => {
69 this.combineData(res, 'tenants');
70 },
71 (err) => {
Matteo Scandoloa160eef2017-03-06 17:21:26 -080072 this.$log.error(`[XosServiceGraphStore] graphData Observable: `, err);
Matteo Scandoloa62adbc2017-03-02 15:37:34 -080073 }
74 );
Matteo Scandolo968e7f22017-03-03 11:49:18 -080075
76 // observe graphData and build Coarse or FineGrained graphs (based on who's subscribed)
77 this.graphData
78 .subscribe(
79 (res: IXosCoarseGraphData) => {
80 if (this.d3CoarseGraph.observers.length > 0) {
81 this.graphDataToCoarseGraph(res);
82 }
83 if (this.d3FineGrainedGraph.observers.length > 0) {
84 // TODO graphDataToFineGrainedGraph
85 }
86 },
87 (err) => {
88 this.$log.error(`[XosServiceGraphStore] graphData Observable: `, err);
89 }
90 );
Matteo Scandoloa62adbc2017-03-02 15:37:34 -080091 }
92
Matteo Scandoloa160eef2017-03-06 17:21:26 -080093 public dispose() {
94 // cancel subscriptions from observables
95 this.ServiceSubscription.unsubscribe();
96 this.TenantSubscription.unsubscribe();
97 }
98
Matteo Scandoloa62adbc2017-03-02 15:37:34 -080099 public get() {
Matteo Scandolo968e7f22017-03-03 11:49:18 -0800100 return this.d3FineGrainedGraph.asObservable();
101 }
102
103 public getCoarse() {
104 return this.d3CoarseGraph.asObservable();
Matteo Scandoloa62adbc2017-03-02 15:37:34 -0800105 }
106
107 private combineData(data: any, type: 'services'|'tenants') {
108 switch (type) {
109 case 'services':
110 this.services = data;
111 break;
112 case 'tenants':
113 this.tenants = data;
114 break;
115 }
116 this.handleData(this.services, this.tenants);
117 }
118
119 private _handleData(services: IXosServiceModel[], tenants: IXosTenantModel[]) {
Matteo Scandolo968e7f22017-03-03 11:49:18 -0800120 this.graphData.next({
121 services: this.services,
122 tenants: this.tenants
123 });
124 }
125
Matteo Scandoloa160eef2017-03-06 17:21:26 -0800126 private getCoarseNodeIndexById(id: number, nodes: IXosServiceModel[]) {
Matteo Scandolo0c61c9b2017-03-03 11:49:18 -0800127 return _.findIndex(nodes, {id: id});
128 }
129
Matteo Scandolo968e7f22017-03-03 11:49:18 -0800130 private graphDataToCoarseGraph(data: IXosCoarseGraphData) {
Matteo Scandolo0c61c9b2017-03-03 11:49:18 -0800131 // TODO find how to bind source/target by node ID and not by position in array (ask Simon?)
Matteo Scandolo968e7f22017-03-03 11:49:18 -0800132 const links: IXosServiceGraphLink[] = _.chain(data.tenants)
133 .filter((t: IXosTenantModel) => t.kind === 'coarse')
134 .map((t: IXosTenantModel) => {
135 return {
136 id: t.id,
Matteo Scandoloa160eef2017-03-06 17:21:26 -0800137 source: this.getCoarseNodeIndexById(t.provider_service_id, data.services),
138 target: this.getCoarseNodeIndexById(t.subscriber_service_id, data.services),
Matteo Scandolo968e7f22017-03-03 11:49:18 -0800139 model: t
140 };
141 })
142 .value();
143
Matteo Scandolo968e7f22017-03-03 11:49:18 -0800144 const nodes: IXosServiceGraphNode[] = _.map(data.services, (s: IXosServiceModel) => {
145 return {
146 id: s.id,
147 label: s.name,
148 model: s
149 };
150 });
151
Matteo Scandolo968e7f22017-03-03 11:49:18 -0800152 this.d3CoarseGraph.next({
153 nodes: nodes,
154 links: links
155 });
Matteo Scandoloa62adbc2017-03-02 15:37:34 -0800156 }
157
158}