blob: 402bea0a5a4274ee2772a982fc638dfd39a14fc5 [file] [log] [blame]
Matteo Scandolofb46ae62017-08-08 09:10:50 -07001
2/*
3 * Copyright 2017-present Open Networking Foundation
4
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8
9 * http://www.apache.org/licenses/LICENSE-2.0
10
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18
Matteo Scandolo72181592017-07-25 14:49:40 -070019import * as _ from 'lodash';
20import {Observable, BehaviorSubject, Subscription} from 'rxjs';
21import {IXosModelStoreService} from '../../datasources/stores/model.store';
22import {
23 IXosServiceGraph, IXosServiceModel, IXosTenantModel, IXosCoarseGraphData,
24 IXosServiceGraphNode, IXosServiceGraphLink, IXosFineGrainedGraphData
25} from '../interfaces';
26import {IXosDebouncer} from '../../core/services/helpers/debounce.helper';
27export interface IXosServiceGraphStore {
28 // TODO remove, moved in a new service
29 get(): Observable<IXosServiceGraph>;
30 // TODO rename in get()
31 getCoarse(): Observable<IXosServiceGraph>;
32}
33
34export class XosServiceGraphStore implements IXosServiceGraphStore {
35 static $inject = [
36 '$log',
37 'XosModelStore',
38 'XosDebouncer'
39 ];
40
41 // graph data store
42 private graphData: BehaviorSubject<IXosFineGrainedGraphData> = new BehaviorSubject({
43 services: [],
44 tenants: [],
45 networks: [],
46 subscribers: [],
47 servicedependencies: []
48 });
49
50 private emptyGraph: IXosServiceGraph = {
51 nodes: [],
52 links: []
53 };
54
55 // representation of the graph as D3 requires
56 private d3CoarseGraph = new BehaviorSubject(this.emptyGraph);
57 private d3FineGrainedGraph = new BehaviorSubject(this.emptyGraph);
58
59 // storing locally reference to the data model
60 private services;
61 private tenants;
62 private subscribers;
63 private networks;
64 private servicedependencys;
65
66 // debounced functions
67 private handleData;
68
69 // datastore
70 private ServiceSubscription: Subscription;
71 private TenantSubscription: Subscription;
72 private SubscriberSubscription: Subscription;
73 private NetworkSubscription: Subscription;
74 private ServiceDependencySubscription: Subscription;
75
76 constructor (
77 private $log: ng.ILogService,
78 private XosModelStore: IXosModelStoreService,
79 private XosDebouncer: IXosDebouncer
80 ) {
81
82 this.$log.info(`[XosServiceGraphStore] Setup`);
83
84 // we want to have a quiet period of 500ms from the last event before doing anything
85 this.handleData = this.XosDebouncer.debounce(this._handleData, 500, this, false);
86
87 // observe models and populate graphData
88 this.ServiceSubscription = this.XosModelStore.query('Service', '/core/services')
89 .subscribe(
90 (res) => {
91 this.combineData(res, 'services');
92 },
93 (err) => {
94 this.$log.error(`[XosServiceGraphStore] Service Observable: `, err);
95 }
96 );
97
98 this.ServiceDependencySubscription = this.XosModelStore.query('ServiceDependency', '/core/servicedependencys')
99 .subscribe(
100 (res) => {
101 this.combineData(res, 'servicedependencies');
102 },
103 (err) => {
104 this.$log.error(`[XosServiceGraphStore] Service Observable: `, err);
105 }
106 );
107
108 this.TenantSubscription = this.XosModelStore.query('Tenant', '/core/tenants')
109 .subscribe(
110 (res) => {
111 this.combineData(res, 'tenants');
112 },
113 (err) => {
114 this.$log.error(`[XosServiceGraphStore] Tenant Observable: `, err);
115 }
116 );
117
118 this.SubscriberSubscription = this.XosModelStore.query('Tenantroot', '/core/tenantroots')
119 .subscribe(
120 (res) => {
121 this.combineData(res, 'subscribers');
122 },
123 (err) => {
124 this.$log.error(`[XosServiceGraphStore] Subscriber Observable: `, err);
125 }
126 );
127
128 this.NetworkSubscription = this.XosModelStore.query('Network', '/core/networks')
129 .subscribe(
130 (res) => {
131 this.combineData(res, 'networks');
132 },
133 (err) => {
134 this.$log.error(`[XosServiceGraphStore] graphData Observable: `, err);
135 }
136 );
137
138 // observe graphData and build Coarse and FineGrained graphs
139 this.graphData
140 .subscribe(
141 (res: IXosFineGrainedGraphData) => {
142 this.$log.debug(`[XosServiceGraphStore] New graph data received`, res);
143 this.graphDataToCoarseGraph(res);
144 // this.graphDataToFineGrainedGraph(res);
145 },
146 (err) => {
147 this.$log.error(`[XosServiceGraphStore] graphData Observable: `, err);
148 }
149 );
150 }
151
152 public get() {
153 return this.d3FineGrainedGraph.asObservable();
154 }
155
156 public getCoarse() {
157 return this.d3CoarseGraph.asObservable();
158 }
159
160 private combineData(data: any, type: 'services'|'tenants'|'subscribers'|'networks'|'servicedependencies') {
161 switch (type) {
162 case 'services':
163 this.services = data;
164 break;
165 case 'tenants':
166 this.tenants = data;
167 break;
168 case 'subscribers':
169 this.subscribers = data;
170 break;
171 case 'networks':
172 this.networks = data;
173 break;
174 case 'servicedependencies':
175 this.servicedependencys = data;
176 break;
177 }
178 this.handleData(this.services, this.tenants);
179 }
180
181 private _handleData(services: IXosServiceModel[], tenants: IXosTenantModel[]) {
182 this.graphData.next({
183 services: this.services,
184 tenants: this.tenants,
185 subscribers: this.subscribers,
186 networks: this.networks,
187 servicedependencies: this.servicedependencys
188 });
189 }
190
191 private getNodeIndexById(id: number | string, nodes: IXosServiceModel[]) {
192 return _.findIndex(nodes, {id: id});
193 }
194
195 private graphDataToCoarseGraph(data: IXosCoarseGraphData) {
196
197 try {
198 const links: IXosServiceGraphLink[] = _.chain(data.servicedependencies)
199 .map((t: IXosTenantModel) => {
200 return {
201 id: t.id,
202 source: this.getNodeIndexById(t.provider_service_id, data.services),
203 target: this.getNodeIndexById(t.subscriber_service_id, data.services),
204 model: t
205 };
206 })
207 .value();
208
209 const nodes: IXosServiceGraphNode[] = _.map(data.services, (s: IXosServiceModel) => {
210 return {
211 id: s.id,
212 label: s.name,
213 model: s
214 };
215 });
216
217 let graph: IXosServiceGraph = {
218 nodes,
219 links
220 };
221
222 this.d3CoarseGraph.next(graph);
223 } catch (e) {
224 this.d3CoarseGraph.error(e);
225 }
226 }
227}