Feat: Use backend sub topology to replace the front end traversal (#268)

* Update: change getId => getIds

* reback env
diff --git a/src/graph/fragments/topology.ts b/src/graph/fragments/topology.ts
index 7ea364e..89f6b86 100644
--- a/src/graph/fragments/topology.ts
+++ b/src/graph/fragments/topology.ts
@@ -211,6 +211,24 @@
     }
   }`,
 };
+export const ServicesTopo = {
+  variable: '$duration: Duration!, $serviceIds: [ID!]!',
+  query: `
+  topo: getServicesTopology(duration: $duration, serviceIds: $serviceIds) {
+    nodes {
+      id
+      name
+      type
+      isReal
+    }
+    calls {
+      id
+      source
+      detectPoints
+      target
+    }
+  }`,
+};
 export const TopoMetric = {
   variable: '$ids: [ID!]!',
   query: `
diff --git a/src/graph/query/topology.ts b/src/graph/query/topology.ts
index ba6cf2d..79ae12e 100644
--- a/src/graph/query/topology.ts
+++ b/src/graph/query/topology.ts
@@ -18,6 +18,7 @@
 import {
   Topo,
   ServiceTopo,
+  ServicesTopo,
   TopoMetric,
   TopoInstanceDependency,
   TopoInstanceClientInfo,
@@ -34,7 +35,9 @@
 
 export const queryServiceTopo = `query queryServiceTopo(${ServiceTopo.variable}) {${ServiceTopo.query}}`;
 
-export const queryTopoInfo = `query queryTrace(
+export const queryServicesTopo = `query queryServiceTopo(${ServicesTopo.variable}) {${ServicesTopo.query}}`;
+
+export const queryTopoInfo = `query queryTopoInfo(
     ${Topo.variable},
     ${TopoMetric.variable},
     ${TopoServiceMetric.variable},
diff --git a/src/store/modules/global/index.ts b/src/store/modules/global/index.ts
index 75ca20d..d77cc7c 100644
--- a/src/store/modules/global/index.ts
+++ b/src/store/modules/global/index.ts
@@ -216,6 +216,12 @@
   },
   SET_DURATION(context: { commit: Commit }, data: Duration): void {
     context.commit(types.SET_DURATION, data);
+    if (window.axiosCancel.length !== 0) {
+      for (const event of window.axiosCancel) {
+        setTimeout(event(), 0);
+      }
+      window.axiosCancel = [];
+    }
     context.commit(types.RUN_EVENTS);
   },
   RESET_DURATION(context: { commit: Commit }): void {
diff --git a/src/store/modules/topology/group/index.ts b/src/store/modules/topology/group/index.ts
index 8246ecd..cdd627a 100644
--- a/src/store/modules/topology/group/index.ts
+++ b/src/store/modules/topology/group/index.ts
@@ -72,6 +72,11 @@
   },
   [types.SELECT_GROUP](state: State, id: string): void {
     state.groupId = id;
+    localStorage.setItem('topology-group-history', id);
+  },
+  [types.UNSELECT_GROUP](state: State): void {
+    state.groupId = 'all';
+    localStorage.removeItem('topology-group-history');
   },
   [types.ADD_GROUP_SERVICE](state: State, data: {id: string, serviceId: string}): void {
     const groupIndex = state.groups.findIndex((i: Group) => i.id === data.id);
diff --git a/src/store/modules/topology/group/mutation-types.ts b/src/store/modules/topology/group/mutation-types.ts
index 3dde160..2243914 100644
--- a/src/store/modules/topology/group/mutation-types.ts
+++ b/src/store/modules/topology/group/mutation-types.ts
@@ -20,6 +20,7 @@
 export const CREATE_GROUP = 'CREATE_GROUP';
 export const DELETE_GROUP = 'DELETE_GROUP';
 export const SELECT_GROUP = 'SELECT_GROUP';
+export const UNSELECT_GROUP = 'UNSELECT_GROUP';
 export const ADD_GROUP_SERVICE = 'ADD_GROUP_SERVICE';
 export const DELETE_GROUP_SERVICE = 'DELETE_GROUP_SERVICE';
 export const GET_GROUPS = 'GET_GROUPS';
diff --git a/src/store/modules/topology/index.ts b/src/store/modules/topology/index.ts
index 07f6af6..96dbd4a 100644
--- a/src/store/modules/topology/index.ts
+++ b/src/store/modules/topology/index.ts
@@ -263,21 +263,26 @@
     if (params.serviceId) {
       query = 'queryServiceTopo';
     }
+    if (params.serviceIds) {
+      query = 'queryServicesTopo';
+    }
     return graph
       .query(query)
       .params(params)
       .then((res: AxiosResponse) => {
+        if (res.data.errors) {
+          context.commit(types.SET_TOPO, { calls: [], nodes: [] });
+          return;
+        }
         const calls = res.data.data.topo.calls;
         const nodes = res.data.data.topo.nodes;
         const ids = nodes.map((i: any) => i.id);
-        const idsS = calls
-          .filter((i: any) => i.detectPoints.indexOf('CLIENT') === -1)
-          .map((b: any) => b.id);
         const idsC = calls
           .filter((i: any) => i.detectPoints.indexOf('CLIENT') !== -1)
           .map((b: any) => b.id);
-        context.commit(types.SET_TOPO_COPY, { calls: [], nodes: [] });
-        context.commit(types.SET_TOPO, { calls: [], nodes: [] });
+        const idsS = calls
+          .filter((i: any) => i.detectPoints.indexOf('CLIENT') === -1)
+          .map((b: any) => b.id);
         return graph
           .query('queryTopoInfo')
           .params({ ...params, ids, idsC, idsS })
diff --git a/src/views/components/topology/topo-aside.vue b/src/views/components/topology/topo-aside.vue
index 130baf2..39cd553 100644
--- a/src/views/components/topology/topo-aside.vue
+++ b/src/views/components/topology/topo-aside.vue
@@ -103,7 +103,6 @@
     @Getter('intervalTime') private intervalTime: any;
     @Getter('durationTime') private durationTime: any;
     @Action('SELECT_SERVICE') private SELECT_SERVICE: any;
-    @Action('rocketTopo/GET_TOPO') private GET_TOPO: any;
     @Action('rocketTopo/CLEAR_TOPO') private CLEAR_TOPO: any;
     @Action('rocketTopo/CLEAR_TOPO_INFO') private CLEAR_TOPO_INFO: any;
     @Mutation('SET_COMPS_TREE') private SET_COMPS_TREE: any;
@@ -135,10 +134,6 @@
       window.addEventListener('resize', this.resize);
     }
 
-    private getTopo() {
-      this.GET_TOPO({ duration: this.durationTime });
-    }
-
     private beforeDestroy() {
       window.removeEventListener('resize', this.resize);
       this.CLEAR_TOPO_INFO();
@@ -157,11 +152,6 @@
       return result;
     }
 
-    @Watch('durationTime')
-    private watchDurationTime() {
-      this.getTopo();
-    }
-
     private showRadial() {
       this.radioStatus = !this.radioStatus;
     }
diff --git a/src/views/components/topology/topo-group/group-item.vue b/src/views/components/topology/topo-group/group-item.vue
index 1a98dbc..758afd1 100644
--- a/src/views/components/topology/topo-group/group-item.vue
+++ b/src/views/components/topology/topo-group/group-item.vue
@@ -21,13 +21,13 @@
       <span class="mr-5">{{data.name}}</span>
     </div>
     <div class="group-services">
-      <div class="ell" v-for="i in servicesMap" :key="i.key">
+      <div class="ell mb-10" v-for="i in servicesMap" :key="i.key">
         <input type="checkbox" @click="(e) => {
-          !e.target.checked ? DELETE_GROUP_SERVICE({id: data.id, serviceId:i.key}) : ADD_GROUP_SERVICE({id: data.id, serviceId:i.key})
-          $emit('select', data.id)
+          !e.target.checked ? DELETE_GROUP_SERVICE({id: data.id, serviceId:i.key}) : ADD_GROUP_SERVICE({id: data.id, serviceId:i.key});
         }" :checked="data.services.some(service => service === i.key)">
         <span>{{i.label}}</span>
       </div>
+       <RkButton size="sm" class="mr-5"  @click="$emit('select', data.id)">Render</RkButton>
     </div>
   </div>
 </template>
diff --git a/src/views/components/topology/topo-group/index.vue b/src/views/components/topology/topo-group/index.vue
index c0052ac..2a35719 100644
--- a/src/views/components/topology/topo-group/index.vue
+++ b/src/views/components/topology/topo-group/index.vue
@@ -25,9 +25,6 @@
       @select="handleSelectGroup"
       :data="i"/>
     </div>
-    <div>
-      <div class="group-item default mb-10" @click="handleSelectGroup('all')" :class="{'active': rocketTopoGroup.groupId === 'all'}"><span>Default</span></div>
-    </div>
     <CreateGroup/>
   </div>
 </template>
@@ -54,8 +51,9 @@
     @Mutation('rocketTopoGroup/INIT_GROUPS') private INIT_GROUPS: any;
     @Mutation('rocketTopoGroup/DELETE_GROUP') private DELETE_GROUP: any;
     @Mutation('rocketTopoGroup/SELECT_GROUP') private SELECT_GROUP: any;
+    @Mutation('SET_EVENTS') private SET_EVENTS: any;
     @Action('rocketTopo/FILTER_TOPO') private FILTER_TOPO: any;
-  
+    @Action('rocketTopo/GET_TOPO') private GET_TOPO: any;
     private servicesMap = [];
     private handleDeleteGroup(id: string) {
       const r = confirm('Do you want to delete this group!');
@@ -65,10 +63,10 @@
     }
     private handleSelectGroup(id: string) {
       this.SELECT_GROUP(id);
-      this.FILTER_TOPO({ services: this.services, group: id });
+      this.GET_TOPO({ duration: this.durationTime , serviceIds: this.services});
     }
     private fetchData() {
-      Axios.post('/graphql', {
+      return Axios.post('/graphql', {
         query: `
       query queryServices($duration: Duration!) {
         services: getAllServices(duration: $duration) {
@@ -85,9 +83,24 @@
           : [];
       });
     }
+    private initGroupTopo() {
+      let serviceOld = localStorage.getItem('topology-group-history') || '';
+      if (!this.rocketTopoGroup.groups.length) {
+        return;
+      }
+      if (!this.rocketTopoGroup.groups.some((i: {id: string, name: string, services: string[]}) => i.id === serviceOld)) {
+        serviceOld = this.rocketTopoGroup.groups[0].id;
+        this.handleSelectGroup(serviceOld);
+      } else {
+        this.handleSelectGroup(serviceOld);
+      }
+    }
     private created() {
       this.INIT_GROUPS();
-      this.fetchData();
+      this.fetchData().then(() => {
+        this.initGroupTopo();
+        this.SET_EVENTS([this.initGroupTopo]);
+      });
     }
   }
 </script>
diff --git a/src/views/components/topology/topo-services.vue b/src/views/components/topology/topo-services.vue
index 351567a..f7b23e3 100644
--- a/src/views/components/topology/topo-services.vue
+++ b/src/views/components/topology/topo-services.vue
@@ -24,13 +24,14 @@
   import compareObj from '@/utils/comparison';
   import Axios, { AxiosResponse } from 'axios';
   import { Component, Vue, Watch } from 'vue-property-decorator';
-  import { Action, Getter } from 'vuex-class';
+  import { Action, Getter, Mutation } from 'vuex-class';
   import TopoSelect from './topo-select.vue';
 
   @Component({ components: { TopoSelect } })
   export default class TopoServices extends Vue {
     @Getter('durationTime') public durationTime: any;
     @Action('rocketTopo/GET_TOPO') public GET_TOPO: any;
+    @Mutation('rocketTopoGroup/UNSELECT_GROUP') private UNSELECT_GROUP: any;
     private services = [{ key: 0, label: 'All services' }];
     private service = { key: 0, label: 'All services' };
 
@@ -63,6 +64,7 @@
 
     private handleChange(i: any) {
       this.service = i;
+      this.UNSELECT_GROUP();
       this.GET_TOPO({
         serviceId: this.service.key,
         duration: this.durationTime,
diff --git a/src/views/containers/topology/topology.vue b/src/views/containers/topology/topology.vue
index 53b6ff0..237ab83 100644
--- a/src/views/containers/topology/topology.vue
+++ b/src/views/containers/topology/topology.vue
@@ -67,7 +67,6 @@
     @State('rocketTopo') private stateTopo!: topoState;
     @State('rocketOption') private stateDashboardOption!: any;
     @Mutation('SET_EVENTS') private SET_EVENTS: any;
-    @Action('rocketTopo/GET_TOPO') private GET_TOPO: any;
     @Action('rocketTopo/CLEAR_TOPO') private CLEAR_TOPO: any;
     @Action('rocketTopo/CLEAR_TOPO_INFO') private CLEAR_TOPO_INFO: any;
     @Getter('durationTime') private durationTime: any;
@@ -77,15 +76,6 @@
     private setCurrent(d: any): void {
       this.current = d;
     }
-    private beforeMount(): void {
-      this.SET_EVENTS([this.getTopo]);
-    }
-    private mounted() {
-      this.getTopo();
-    }
-    private getTopo() {
-      this.GET_TOPO({ duration: this.durationTime });
-    }
     private beforeDestroy() {
       this.CLEAR_TOPO_INFO();
       this.CLEAR_TOPO();