blob: 92b9e6d5e000f3b052f75f3140f43a6115b554cc [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;
Matteo Scandolo72181592017-07-25 14:49:40 -070071 private NetworkSubscription: Subscription;
72 private ServiceDependencySubscription: Subscription;
73
74 constructor (
75 private $log: ng.ILogService,
76 private XosModelStore: IXosModelStoreService,
77 private XosDebouncer: IXosDebouncer
78 ) {
79
80 this.$log.info(`[XosServiceGraphStore] Setup`);
81
82 // we want to have a quiet period of 500ms from the last event before doing anything
83 this.handleData = this.XosDebouncer.debounce(this._handleData, 500, this, false);
84
85 // observe models and populate graphData
86 this.ServiceSubscription = this.XosModelStore.query('Service', '/core/services')
87 .subscribe(
88 (res) => {
89 this.combineData(res, 'services');
90 },
91 (err) => {
92 this.$log.error(`[XosServiceGraphStore] Service Observable: `, err);
93 }
94 );
95
96 this.ServiceDependencySubscription = this.XosModelStore.query('ServiceDependency', '/core/servicedependencys')
97 .subscribe(
98 (res) => {
99 this.combineData(res, 'servicedependencies');
100 },
101 (err) => {
102 this.$log.error(`[XosServiceGraphStore] Service Observable: `, err);
103 }
104 );
105
Matteo Scandolo72181592017-07-25 14:49:40 -0700106 this.NetworkSubscription = this.XosModelStore.query('Network', '/core/networks')
107 .subscribe(
108 (res) => {
109 this.combineData(res, 'networks');
110 },
111 (err) => {
112 this.$log.error(`[XosServiceGraphStore] graphData Observable: `, err);
113 }
114 );
115
116 // observe graphData and build Coarse and FineGrained graphs
117 this.graphData
118 .subscribe(
119 (res: IXosFineGrainedGraphData) => {
120 this.$log.debug(`[XosServiceGraphStore] New graph data received`, res);
121 this.graphDataToCoarseGraph(res);
122 // this.graphDataToFineGrainedGraph(res);
123 },
124 (err) => {
125 this.$log.error(`[XosServiceGraphStore] graphData Observable: `, err);
126 }
127 );
128 }
129
130 public get() {
131 return this.d3FineGrainedGraph.asObservable();
132 }
133
134 public getCoarse() {
135 return this.d3CoarseGraph.asObservable();
136 }
137
138 private combineData(data: any, type: 'services'|'tenants'|'subscribers'|'networks'|'servicedependencies') {
139 switch (type) {
140 case 'services':
141 this.services = data;
142 break;
143 case 'tenants':
144 this.tenants = data;
145 break;
146 case 'subscribers':
147 this.subscribers = data;
148 break;
149 case 'networks':
150 this.networks = data;
151 break;
152 case 'servicedependencies':
153 this.servicedependencys = data;
154 break;
155 }
156 this.handleData(this.services, this.tenants);
157 }
158
159 private _handleData(services: IXosServiceModel[], tenants: IXosTenantModel[]) {
160 this.graphData.next({
161 services: this.services,
162 tenants: this.tenants,
163 subscribers: this.subscribers,
164 networks: this.networks,
165 servicedependencies: this.servicedependencys
166 });
167 }
168
169 private getNodeIndexById(id: number | string, nodes: IXosServiceModel[]) {
170 return _.findIndex(nodes, {id: id});
171 }
172
173 private graphDataToCoarseGraph(data: IXosCoarseGraphData) {
174
175 try {
176 const links: IXosServiceGraphLink[] = _.chain(data.servicedependencies)
177 .map((t: IXosTenantModel) => {
178 return {
179 id: t.id,
180 source: this.getNodeIndexById(t.provider_service_id, data.services),
181 target: this.getNodeIndexById(t.subscriber_service_id, data.services),
182 model: t
183 };
184 })
185 .value();
186
187 const nodes: IXosServiceGraphNode[] = _.map(data.services, (s: IXosServiceModel) => {
188 return {
189 id: s.id,
190 label: s.name,
191 model: s
192 };
193 });
194
195 let graph: IXosServiceGraph = {
196 nodes,
197 links
198 };
199
200 this.d3CoarseGraph.next(graph);
201 } catch (e) {
202 this.d3CoarseGraph.error(e);
203 }
204 }
205}