mirror of
https://github.com/ceph/ceph
synced 2025-01-20 01:51:34 +00:00
Merge pull request #22906 from tspmelo/wip-improve-summary
mgr/dashboard: Improve SummaryService and TaskWrapperService Reviewed-by: Ricardo Marques <rimarques@suse.com> Reviewed-by: Stephan Müller <smueller@suse.com>
This commit is contained in:
commit
c57d90f181
@ -2,6 +2,7 @@ import { Component, OnDestroy, OnInit, TemplateRef, ViewChild } from '@angular/c
|
|||||||
|
|
||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
import { BsModalRef, BsModalService } from 'ngx-bootstrap';
|
import { BsModalRef, BsModalService } from 'ngx-bootstrap';
|
||||||
|
import { Subscription } from 'rxjs';
|
||||||
|
|
||||||
import { RbdService } from '../../../shared/api/rbd.service';
|
import { RbdService } from '../../../shared/api/rbd.service';
|
||||||
import { ConfirmationModalComponent } from '../../../shared/components/confirmation-modal/confirmation-modal.component';
|
import { ConfirmationModalComponent } from '../../../shared/components/confirmation-modal/confirmation-modal.component';
|
||||||
@ -36,13 +37,12 @@ export class RbdListComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
permission: Permission;
|
permission: Permission;
|
||||||
images: any;
|
images: any;
|
||||||
executingTasks: ExecutingTask[] = [];
|
|
||||||
columns: CdTableColumn[];
|
columns: CdTableColumn[];
|
||||||
retries: number;
|
retries: number;
|
||||||
viewCacheStatusList: any[];
|
viewCacheStatusList: any[];
|
||||||
selection = new CdTableSelection();
|
selection = new CdTableSelection();
|
||||||
|
|
||||||
summaryDataSubscription = null;
|
summaryDataSubscription: Subscription;
|
||||||
|
|
||||||
modalRef: BsModalRef;
|
modalRef: BsModalRef;
|
||||||
|
|
||||||
@ -53,7 +53,8 @@ export class RbdListComponent implements OnInit, OnDestroy {
|
|||||||
private dimlessPipe: DimlessPipe,
|
private dimlessPipe: DimlessPipe,
|
||||||
private summaryService: SummaryService,
|
private summaryService: SummaryService,
|
||||||
private modalService: BsModalService,
|
private modalService: BsModalService,
|
||||||
private taskWrapper: TaskWrapperService) {
|
private taskWrapper: TaskWrapperService
|
||||||
|
) {
|
||||||
this.permission = this.authStorageService.getPermissions().rbdImage;
|
this.permission = this.authStorageService.getPermissions().rbdImage;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -113,18 +114,13 @@ export class RbdListComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
this.summaryService.get().subscribe((resp: any) => {
|
this.summaryDataSubscription = this.summaryService.subscribe((data: any) => {
|
||||||
if (!resp) {
|
if (!data) {
|
||||||
|
this.table.reset(); // Disable loading indicator.
|
||||||
|
this.viewCacheStatusList = [{ status: ViewCacheStatus.ValueException }];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.loadImages(resp.executing_tasks);
|
this.loadImages(data.executing_tasks);
|
||||||
this.summaryDataSubscription = this.summaryService.summaryData$.subscribe((data: any) => {
|
|
||||||
this.loadImages(data.executing_tasks);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
() => {
|
|
||||||
this.table.reset(); // Disable loading indicator.
|
|
||||||
this.viewCacheStatusList = [{ status: ViewCacheStatus.ValueException }];
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,9 +131,6 @@ export class RbdListComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
loadImages(executingTasks) {
|
loadImages(executingTasks) {
|
||||||
if (executingTasks === null) {
|
|
||||||
executingTasks = this.executingTasks;
|
|
||||||
}
|
|
||||||
this.rbdService.list().subscribe(
|
this.rbdService.list().subscribe(
|
||||||
(resp: any[]) => {
|
(resp: any[]) => {
|
||||||
let images = [];
|
let images = [];
|
||||||
@ -150,7 +143,7 @@ export class RbdListComponent implements OnInit, OnDestroy {
|
|||||||
images = images.concat(pool.value);
|
images = images.concat(pool.value);
|
||||||
});
|
});
|
||||||
const viewCacheStatusList = [];
|
const viewCacheStatusList = [];
|
||||||
_.forEach(viewCacheStatusMap, (value, key) => {
|
_.forEach(viewCacheStatusMap, (value: any, key) => {
|
||||||
viewCacheStatusList.push({
|
viewCacheStatusList.push({
|
||||||
status: parseInt(key, 10),
|
status: parseInt(key, 10),
|
||||||
statusFor:
|
statusFor:
|
||||||
@ -169,7 +162,6 @@ export class RbdListComponent implements OnInit, OnDestroy {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
this.images = this.merge(images, executingTasks);
|
this.images = this.merge(images, executingTasks);
|
||||||
this.executingTasks = executingTasks;
|
|
||||||
},
|
},
|
||||||
() => {
|
() => {
|
||||||
this.table.reset(); // Disable loading indicator.
|
this.table.reset(); // Disable loading indicator.
|
||||||
@ -264,7 +256,6 @@ export class RbdListComponent implements OnInit, OnDestroy {
|
|||||||
pool_name: poolName,
|
pool_name: poolName,
|
||||||
image_name: imageName
|
image_name: imageName
|
||||||
}),
|
}),
|
||||||
tasks: this.executingTasks,
|
|
||||||
call: this.rbdService.delete(poolName, imageName)
|
call: this.rbdService.delete(poolName, imageName)
|
||||||
}),
|
}),
|
||||||
modalRef: this.modalRef
|
modalRef: this.modalRef
|
||||||
@ -278,12 +269,10 @@ export class RbdListComponent implements OnInit, OnDestroy {
|
|||||||
pool_name: poolName,
|
pool_name: poolName,
|
||||||
image_name: imageName
|
image_name: imageName
|
||||||
}),
|
}),
|
||||||
tasks: this.executingTasks,
|
|
||||||
call: this.rbdService.flatten(poolName, imageName)
|
call: this.rbdService.flatten(poolName, imageName)
|
||||||
})
|
})
|
||||||
.subscribe(undefined, undefined, () => {
|
.subscribe(undefined, undefined, () => {
|
||||||
this.modalRef.hide();
|
this.modalRef.hide();
|
||||||
this.loadImages(null);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,20 +2,24 @@ import { HttpClientTestingModule } from '@angular/common/http/testing';
|
|||||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
import { BsModalRef } from 'ngx-bootstrap';
|
import { BsModalRef } from 'ngx-bootstrap';
|
||||||
import 'rxjs/add/observable/of';
|
import { BehaviorSubject } from 'rxjs';
|
||||||
import { Observable } from 'rxjs/Observable';
|
|
||||||
|
|
||||||
import { configureTestBed } from '../../../../testing/unit-test-helper';
|
import { configureTestBed } from '../../../../testing/unit-test-helper';
|
||||||
import { SummaryService } from '../../../shared/services/summary.service';
|
import { SummaryService } from '../../../shared/services/summary.service';
|
||||||
import { SharedModule } from '../../../shared/shared.module';
|
import { SharedModule } from '../../../shared/shared.module';
|
||||||
import { AboutComponent } from './about.component';
|
import { AboutComponent } from './about.component';
|
||||||
|
|
||||||
class SummaryServiceMock {
|
export class SummaryServiceMock {
|
||||||
summaryData$ = Observable.of({
|
summaryDataSource = new BehaviorSubject({
|
||||||
version:
|
version:
|
||||||
'ceph version 14.0.0-855-gb8193bb4cd ' +
|
'ceph version 14.0.0-855-gb8193bb4cd ' +
|
||||||
'(b8193bb4cda16ccc5b028c3e1df62bc72350a15d) nautilus (dev)'
|
'(b8193bb4cda16ccc5b028c3e1df62bc72350a15d) nautilus (dev)'
|
||||||
});
|
});
|
||||||
|
summaryData$ = this.summaryDataSource.asObservable();
|
||||||
|
|
||||||
|
subscribe(call) {
|
||||||
|
return this.summaryData$.subscribe(call);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
describe('AboutComponent', () => {
|
describe('AboutComponent', () => {
|
||||||
|
@ -19,7 +19,7 @@ export class AboutComponent implements OnInit, OnDestroy {
|
|||||||
constructor(public modalRef: BsModalRef, private summaryService: SummaryService) {}
|
constructor(public modalRef: BsModalRef, private summaryService: SummaryService) {}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.subs = this.summaryService.summaryData$.subscribe((summary: any) => {
|
this.subs = this.summaryService.subscribe((summary: any) => {
|
||||||
if (!summary) {
|
if (!summary) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -22,13 +22,17 @@ export class DashboardHelpComponent implements OnInit {
|
|||||||
) {}
|
) {}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
const subs = this.summaryService.summaryData$.subscribe((summary: any) => {
|
const subs = this.summaryService.subscribe((summary: any) => {
|
||||||
if (!summary) {
|
if (!summary) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const releaseName = this.cephReleaseNamePipe.transform(summary.version);
|
const releaseName = this.cephReleaseNamePipe.transform(summary.version);
|
||||||
this.docsUrl = `http://docs.ceph.com/docs/${releaseName}/mgr/dashboard/`;
|
this.docsUrl = `http://docs.ceph.com/docs/${releaseName}/mgr/dashboard/`;
|
||||||
subs.unsubscribe();
|
|
||||||
|
setTimeout(() => {
|
||||||
|
subs.unsubscribe();
|
||||||
|
}, 0);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ export class NavigationComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.summaryService.summaryData$.subscribe((data: any) => {
|
this.summaryService.subscribe((data: any) => {
|
||||||
if (!data) {
|
if (!data) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ export class TaskManagerComponent implements OnInit {
|
|||||||
) {}
|
) {}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.summaryService.summaryData$.subscribe((data: any) => {
|
this.summaryService.subscribe((data: any) => {
|
||||||
if (!data) {
|
if (!data) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
import { HttpClient } from '@angular/common/http';
|
import { HttpClient } from '@angular/common/http';
|
||||||
import { fakeAsync, TestBed, tick } from '@angular/core/testing';
|
import { fakeAsync, TestBed, tick } from '@angular/core/testing';
|
||||||
|
|
||||||
import { of as observableOf } from 'rxjs';
|
import { of as observableOf, Subscriber } from 'rxjs';
|
||||||
|
|
||||||
import { configureTestBed } from '../../../testing/unit-test-helper';
|
import { configureTestBed } from '../../../testing/unit-test-helper';
|
||||||
|
import { ExecutingTask } from '../models/executing-task';
|
||||||
import { AuthStorageService } from './auth-storage.service';
|
import { AuthStorageService } from './auth-storage.service';
|
||||||
import { SummaryService } from './summary.service';
|
import { SummaryService } from './summary.service';
|
||||||
|
|
||||||
@ -11,18 +12,19 @@ describe('SummaryService', () => {
|
|||||||
let summaryService: SummaryService;
|
let summaryService: SummaryService;
|
||||||
let authStorageService: AuthStorageService;
|
let authStorageService: AuthStorageService;
|
||||||
|
|
||||||
|
const summary = {
|
||||||
|
executing_tasks: [],
|
||||||
|
health_status: 'HEALTH_OK',
|
||||||
|
mgr_id: 'x',
|
||||||
|
rbd_mirroring: { errors: 0, warnings: 0 },
|
||||||
|
rbd_pools: [],
|
||||||
|
have_mon_connection: true,
|
||||||
|
finished_tasks: [],
|
||||||
|
filesystems: [{ id: 1, name: 'cephfs_a' }]
|
||||||
|
};
|
||||||
|
|
||||||
const httpClientSpy = {
|
const httpClientSpy = {
|
||||||
get: () =>
|
get: () => observableOf(summary)
|
||||||
observableOf({
|
|
||||||
executing_tasks: [],
|
|
||||||
health_status: 'HEALTH_OK',
|
|
||||||
mgr_id: 'x',
|
|
||||||
rbd_mirroring: { errors: 0, warnings: 0 },
|
|
||||||
rbd_pools: [],
|
|
||||||
have_mon_connection: true,
|
|
||||||
finished_tasks: [],
|
|
||||||
filesystems: [{ id: 1, name: 'cephfs_a' }]
|
|
||||||
})
|
|
||||||
};
|
};
|
||||||
|
|
||||||
configureTestBed({
|
configureTestBed({
|
||||||
@ -48,7 +50,7 @@ describe('SummaryService', () => {
|
|||||||
authStorageService.set('foobar');
|
authStorageService.set('foobar');
|
||||||
let result = false;
|
let result = false;
|
||||||
summaryService.refresh();
|
summaryService.refresh();
|
||||||
summaryService.summaryData$.subscribe((res) => {
|
summaryService.subscribe(() => {
|
||||||
result = true;
|
result = true;
|
||||||
});
|
});
|
||||||
tick(5000);
|
tick(5000);
|
||||||
@ -58,7 +60,38 @@ describe('SummaryService', () => {
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
it('should get summary', () => {
|
describe('Should test methods after first refresh', () => {
|
||||||
expect(summaryService.get()).toEqual(jasmine.any(Object));
|
beforeEach(() => {
|
||||||
|
authStorageService.set('foobar');
|
||||||
|
summaryService.refresh();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call getCurrentSummary', () => {
|
||||||
|
expect(summaryService.getCurrentSummary ()).toEqual(summary);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call subscribe', () => {
|
||||||
|
let result;
|
||||||
|
const subscriber = summaryService.subscribe((data) => {
|
||||||
|
result = data;
|
||||||
|
});
|
||||||
|
expect(subscriber).toEqual(jasmine.any(Subscriber));
|
||||||
|
expect(result).toEqual(summary);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call addRunningTask', () => {
|
||||||
|
summaryService.addRunningTask(
|
||||||
|
new ExecutingTask('rbd/delete', {
|
||||||
|
pool_name: 'somePool',
|
||||||
|
image_name: 'someImage'
|
||||||
|
})
|
||||||
|
);
|
||||||
|
const result = summaryService.getCurrentSummary ();
|
||||||
|
expect(result.executing_tasks.length).toBe(1);
|
||||||
|
expect(result.executing_tasks[0]).toEqual({
|
||||||
|
metadata: { image_name: 'someImage', pool_name: 'somePool' },
|
||||||
|
name: 'rbd/delete'
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
import { HttpClient } from '@angular/common/http';
|
import { HttpClient } from '@angular/common/http';
|
||||||
import { Injectable, NgZone } from '@angular/core';
|
import { Injectable, NgZone } from '@angular/core';
|
||||||
|
|
||||||
import { BehaviorSubject } from 'rxjs';
|
import * as _ from 'lodash';
|
||||||
|
import { BehaviorSubject, Subscription } from 'rxjs';
|
||||||
|
|
||||||
|
import { ExecutingTask } from '../models/executing-task';
|
||||||
import { AuthStorageService } from './auth-storage.service';
|
import { AuthStorageService } from './auth-storage.service';
|
||||||
import { ServicesModule } from './services.module';
|
import { ServicesModule } from './services.module';
|
||||||
|
|
||||||
@ -26,7 +28,7 @@ export class SummaryService {
|
|||||||
|
|
||||||
refresh() {
|
refresh() {
|
||||||
if (this.authStorageService.isLoggedIn()) {
|
if (this.authStorageService.isLoggedIn()) {
|
||||||
this.http.get('api/summary').subscribe(data => {
|
this.http.get('api/summary').subscribe((data) => {
|
||||||
this.summaryDataSource.next(data);
|
this.summaryDataSource.next(data);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -40,7 +42,48 @@ export class SummaryService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
get() {
|
/**
|
||||||
return this.http.get('api/summary');
|
* Returns the current value of summaryData
|
||||||
|
*
|
||||||
|
* @returns {object}
|
||||||
|
* @memberof SummaryService
|
||||||
|
*/
|
||||||
|
getCurrentSummary () {
|
||||||
|
return this.summaryDataSource.getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subscribes to the summaryData,
|
||||||
|
* which is updated once every 5 seconds or when a new task is created.
|
||||||
|
*
|
||||||
|
* @param {(summary: any) => void} call
|
||||||
|
* @returns {Subscription}
|
||||||
|
* @memberof SummaryService
|
||||||
|
*/
|
||||||
|
subscribe(call: (summary: any) => void): Subscription {
|
||||||
|
return this.summaryData$.subscribe(call);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inserts a newly created task to the local list of executing tasks.
|
||||||
|
* After that, it will automatically push that new information
|
||||||
|
* to all subscribers.
|
||||||
|
*
|
||||||
|
* @param {ExecutingTask} task
|
||||||
|
* @memberof SummaryService
|
||||||
|
*/
|
||||||
|
addRunningTask(task: ExecutingTask) {
|
||||||
|
const current = this.summaryDataSource.getValue();
|
||||||
|
if (!current) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_.isArray(current.executing_tasks)) {
|
||||||
|
current.executing_tasks.push(task);
|
||||||
|
} else {
|
||||||
|
current.executing_tasks = [task];
|
||||||
|
}
|
||||||
|
|
||||||
|
this.summaryDataSource.next(current);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,41 +1,50 @@
|
|||||||
import { fakeAsync, TestBed, tick } from '@angular/core/testing';
|
import { fakeAsync, TestBed, tick } from '@angular/core/testing';
|
||||||
|
|
||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
import { Subject } from 'rxjs';
|
import { BehaviorSubject } from 'rxjs';
|
||||||
|
|
||||||
import { configureTestBed } from '../../../testing/unit-test-helper';
|
import { configureTestBed } from '../../../testing/unit-test-helper';
|
||||||
import { SummaryService } from './summary.service';
|
import { SummaryService } from './summary.service';
|
||||||
import { TaskManagerService } from './task-manager.service';
|
import { TaskManagerService } from './task-manager.service';
|
||||||
|
|
||||||
|
const summary = {
|
||||||
|
executing_tasks: [],
|
||||||
|
health_status: 'HEALTH_OK',
|
||||||
|
mgr_id: 'x',
|
||||||
|
rbd_mirroring: { errors: 0, warnings: 0 },
|
||||||
|
rbd_pools: [],
|
||||||
|
have_mon_connection: true,
|
||||||
|
finished_tasks: [{ name: 'foo', metadata: {} }],
|
||||||
|
filesystems: [{ id: 1, name: 'cephfs_a' }]
|
||||||
|
};
|
||||||
|
|
||||||
|
export class SummaryServiceMock {
|
||||||
|
summaryDataSource = new BehaviorSubject(summary);
|
||||||
|
summaryData$ = this.summaryDataSource.asObservable();
|
||||||
|
|
||||||
|
refresh() {
|
||||||
|
this.summaryDataSource.next(summary);
|
||||||
|
}
|
||||||
|
subscribe(call) {
|
||||||
|
return this.summaryData$.subscribe(call);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
describe('TaskManagerService', () => {
|
describe('TaskManagerService', () => {
|
||||||
let taskManagerService: TaskManagerService;
|
let taskManagerService: TaskManagerService;
|
||||||
|
let summaryService: any;
|
||||||
let called: boolean;
|
let called: boolean;
|
||||||
|
|
||||||
const summaryDataSource = new Subject();
|
|
||||||
const fakeService = {
|
|
||||||
summaryData$: summaryDataSource.asObservable()
|
|
||||||
};
|
|
||||||
|
|
||||||
const summary = {
|
|
||||||
executing_tasks: [],
|
|
||||||
health_status: 'HEALTH_OK',
|
|
||||||
mgr_id: 'x',
|
|
||||||
rbd_mirroring: { errors: 0, warnings: 0 },
|
|
||||||
rbd_pools: [],
|
|
||||||
have_mon_connection: true,
|
|
||||||
finished_tasks: [{ name: 'foo', metadata: {} }],
|
|
||||||
filesystems: [{ id: 1, name: 'cephfs_a' }]
|
|
||||||
};
|
|
||||||
|
|
||||||
configureTestBed(
|
configureTestBed(
|
||||||
{
|
{
|
||||||
providers: [TaskManagerService, { provide: SummaryService, useValue: fakeService }]
|
providers: [TaskManagerService, { provide: SummaryService, useClass: SummaryServiceMock }]
|
||||||
},
|
},
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
taskManagerService = TestBed.get(TaskManagerService);
|
taskManagerService = TestBed.get(TaskManagerService);
|
||||||
|
summaryService = TestBed.get(SummaryService);
|
||||||
called = false;
|
called = false;
|
||||||
taskManagerService.subscribe('foo', {}, () => (called = true));
|
taskManagerService.subscribe('foo', {}, () => (called = true));
|
||||||
});
|
});
|
||||||
@ -48,7 +57,7 @@ describe('TaskManagerService', () => {
|
|||||||
'should subscribe and be notified when task is finished',
|
'should subscribe and be notified when task is finished',
|
||||||
fakeAsync(() => {
|
fakeAsync(() => {
|
||||||
expect(taskManagerService.subscriptions.length).toBe(1);
|
expect(taskManagerService.subscriptions.length).toBe(1);
|
||||||
summaryDataSource.next(summary);
|
summaryService.refresh();
|
||||||
tick();
|
tick();
|
||||||
expect(called).toEqual(true);
|
expect(called).toEqual(true);
|
||||||
expect(taskManagerService.subscriptions).toEqual([]);
|
expect(taskManagerService.subscriptions).toEqual([]);
|
||||||
@ -63,7 +72,7 @@ describe('TaskManagerService', () => {
|
|||||||
executing_tasks: [{ name: 'foo', metadata: {} }],
|
executing_tasks: [{ name: 'foo', metadata: {} }],
|
||||||
finished_tasks: []
|
finished_tasks: []
|
||||||
});
|
});
|
||||||
summaryDataSource.next(summary);
|
summaryService.refresh();
|
||||||
tick();
|
tick();
|
||||||
expect(taskManagerService.subscriptions).toEqual(original_subscriptions);
|
expect(taskManagerService.subscriptions).toEqual(original_subscriptions);
|
||||||
})
|
})
|
||||||
|
@ -27,7 +27,7 @@ export class TaskManagerService {
|
|||||||
subscriptions: Array<TaskSubscription> = [];
|
subscriptions: Array<TaskSubscription> = [];
|
||||||
|
|
||||||
constructor(summaryService: SummaryService) {
|
constructor(summaryService: SummaryService) {
|
||||||
summaryService.summaryData$.subscribe((data: any) => {
|
summaryService.subscribe((data: any) => {
|
||||||
if (!data) {
|
if (!data) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -5,10 +5,10 @@ import { ToastModule } from 'ng2-toastr';
|
|||||||
import { Observable } from 'rxjs/Observable';
|
import { Observable } from 'rxjs/Observable';
|
||||||
|
|
||||||
import { configureTestBed } from '../../../testing/unit-test-helper';
|
import { configureTestBed } from '../../../testing/unit-test-helper';
|
||||||
import { ExecutingTask } from '../models/executing-task';
|
|
||||||
import { FinishedTask } from '../models/finished-task';
|
import { FinishedTask } from '../models/finished-task';
|
||||||
import { SharedModule } from '../shared.module';
|
import { SharedModule } from '../shared.module';
|
||||||
import { NotificationService } from './notification.service';
|
import { NotificationService } from './notification.service';
|
||||||
|
import { SummaryService } from './summary.service';
|
||||||
import { TaskManagerService } from './task-manager.service';
|
import { TaskManagerService } from './task-manager.service';
|
||||||
import { TaskWrapperService } from './task-wrapper.service';
|
import { TaskWrapperService } from './task-wrapper.service';
|
||||||
|
|
||||||
@ -30,8 +30,8 @@ describe('TaskWrapperService', () => {
|
|||||||
|
|
||||||
describe('wrapTaskAroundCall', () => {
|
describe('wrapTaskAroundCall', () => {
|
||||||
let notify: NotificationService;
|
let notify: NotificationService;
|
||||||
let tasks: ExecutingTask[];
|
|
||||||
let passed: boolean;
|
let passed: boolean;
|
||||||
|
let summaryService: SummaryService;
|
||||||
|
|
||||||
const fakeCall = (status?) =>
|
const fakeCall = (status?) =>
|
||||||
new Observable((observer) => {
|
new Observable((observer) => {
|
||||||
@ -45,31 +45,31 @@ describe('TaskWrapperService', () => {
|
|||||||
const callWrapTaskAroundCall = (status, name) => {
|
const callWrapTaskAroundCall = (status, name) => {
|
||||||
return service.wrapTaskAroundCall({
|
return service.wrapTaskAroundCall({
|
||||||
task: new FinishedTask(name, { sth: 'else' }),
|
task: new FinishedTask(name, { sth: 'else' }),
|
||||||
call: fakeCall(status),
|
call: fakeCall(status)
|
||||||
tasks: tasks
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
passed = false;
|
passed = false;
|
||||||
tasks = [];
|
|
||||||
notify = TestBed.get(NotificationService);
|
notify = TestBed.get(NotificationService);
|
||||||
|
summaryService = TestBed.get(SummaryService);
|
||||||
spyOn(notify, 'show');
|
spyOn(notify, 'show');
|
||||||
spyOn(service, '_handleExecutingTasks').and.callThrough();
|
spyOn(service, '_handleExecutingTasks').and.callThrough();
|
||||||
|
spyOn(summaryService, 'addRunningTask').and.callThrough();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should simulate a synchronous task', () => {
|
it('should simulate a synchronous task', () => {
|
||||||
callWrapTaskAroundCall(200, 'sync').subscribe(null, null, () => (passed = true));
|
callWrapTaskAroundCall(200, 'sync').subscribe(null, null, () => (passed = true));
|
||||||
expect(service._handleExecutingTasks).not.toHaveBeenCalled();
|
expect(service._handleExecutingTasks).not.toHaveBeenCalled();
|
||||||
expect(passed).toBeTruthy();
|
expect(passed).toBeTruthy();
|
||||||
expect(tasks.length).toBe(0);
|
expect(summaryService.addRunningTask).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should simulate a asynchronous task', () => {
|
it('should simulate a asynchronous task', () => {
|
||||||
callWrapTaskAroundCall(202, 'async').subscribe(null, null, () => (passed = true));
|
callWrapTaskAroundCall(202, 'async').subscribe(null, null, () => (passed = true));
|
||||||
expect(service._handleExecutingTasks).toHaveBeenCalled();
|
expect(service._handleExecutingTasks).toHaveBeenCalled();
|
||||||
expect(passed).toBeTruthy();
|
expect(passed).toBeTruthy();
|
||||||
expect(tasks.length).toBe(1);
|
expect(summaryService.addRunningTask).toHaveBeenCalledTimes(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should call notifyTask if asynchronous task would have been finished', () => {
|
it('should call notifyTask if asynchronous task would have been finished', () => {
|
||||||
@ -86,7 +86,7 @@ describe('TaskWrapperService', () => {
|
|||||||
callWrapTaskAroundCall(null, 'async').subscribe(null, () => (passed = true), null);
|
callWrapTaskAroundCall(null, 'async').subscribe(null, () => (passed = true), null);
|
||||||
expect(service._handleExecutingTasks).not.toHaveBeenCalled();
|
expect(service._handleExecutingTasks).not.toHaveBeenCalled();
|
||||||
expect(passed).toBeTruthy();
|
expect(passed).toBeTruthy();
|
||||||
expect(tasks.length).toBe(0);
|
expect(summaryService.addRunningTask).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -8,6 +8,7 @@ import { ExecutingTask } from '../models/executing-task';
|
|||||||
import { FinishedTask } from '../models/finished-task';
|
import { FinishedTask } from '../models/finished-task';
|
||||||
import { NotificationService } from './notification.service';
|
import { NotificationService } from './notification.service';
|
||||||
import { ServicesModule } from './services.module';
|
import { ServicesModule } from './services.module';
|
||||||
|
import { SummaryService } from './summary.service';
|
||||||
import { TaskManagerMessageService } from './task-manager-message.service';
|
import { TaskManagerMessageService } from './task-manager-message.service';
|
||||||
import { TaskManagerService } from './task-manager.service';
|
import { TaskManagerService } from './task-manager.service';
|
||||||
|
|
||||||
@ -17,25 +18,19 @@ import { TaskManagerService } from './task-manager.service';
|
|||||||
export class TaskWrapperService {
|
export class TaskWrapperService {
|
||||||
constructor(
|
constructor(
|
||||||
private notificationService: NotificationService,
|
private notificationService: NotificationService,
|
||||||
|
private summaryService: SummaryService,
|
||||||
private taskManagerMessageService: TaskManagerMessageService,
|
private taskManagerMessageService: TaskManagerMessageService,
|
||||||
private taskManagerService: TaskManagerService
|
private taskManagerService: TaskManagerService
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
wrapTaskAroundCall({
|
wrapTaskAroundCall({ task, call }: { task: FinishedTask; call: Observable<any> }) {
|
||||||
task,
|
|
||||||
call,
|
|
||||||
tasks
|
|
||||||
}: {
|
|
||||||
task: FinishedTask;
|
|
||||||
call: Observable<any>;
|
|
||||||
tasks?: ExecutingTask[];
|
|
||||||
}) {
|
|
||||||
return new Observable((observer: Subscriber<any>) => {
|
return new Observable((observer: Subscriber<any>) => {
|
||||||
call.subscribe(
|
call.subscribe(
|
||||||
(resp) => {
|
(resp) => {
|
||||||
if (resp.status === 202) {
|
if (resp.status === 202) {
|
||||||
this._handleExecutingTasks(task, tasks);
|
this._handleExecutingTasks(task);
|
||||||
} else {
|
} else {
|
||||||
|
this.summaryService.refresh();
|
||||||
task.success = true;
|
task.success = true;
|
||||||
this.notificationService.notifyTask(task);
|
this.notificationService.notifyTask(task);
|
||||||
}
|
}
|
||||||
@ -53,16 +48,16 @@ export class TaskWrapperService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
_handleExecutingTasks(task: FinishedTask, tasks?: ExecutingTask[]) {
|
_handleExecutingTasks(task: FinishedTask) {
|
||||||
this.notificationService.show(
|
this.notificationService.show(
|
||||||
NotificationType.info,
|
NotificationType.info,
|
||||||
this.taskManagerMessageService.getRunningMessage(task),
|
this.taskManagerMessageService.getRunningMessage(task),
|
||||||
this.taskManagerMessageService.getDescription(task)
|
this.taskManagerMessageService.getDescription(task)
|
||||||
);
|
);
|
||||||
|
|
||||||
const executingTask = new ExecutingTask(task.name, task.metadata);
|
const executingTask = new ExecutingTask(task.name, task.metadata);
|
||||||
if (tasks) {
|
this.summaryService.addRunningTask(executingTask);
|
||||||
tasks.push(executingTask);
|
|
||||||
}
|
|
||||||
this.taskManagerService.subscribe(
|
this.taskManagerService.subscribe(
|
||||||
executingTask.name,
|
executingTask.name,
|
||||||
executingTask.metadata,
|
executingTask.metadata,
|
||||||
|
Loading…
Reference in New Issue
Block a user