mirror of
https://github.com/ceph/ceph
synced 2025-03-07 00:40:00 +00:00
mgr/dashboard: Task wrapper service
Has a method to wrap an API call into a task. Fixes: https://tracker.ceph.com/issues/24134 Signed-off-by: Stephan Müller <smueller@suse.com>
This commit is contained in:
parent
d785010a35
commit
3201ba6f7d
@ -1,4 +1,8 @@
|
||||
export class Task {
|
||||
constructor(name?, metadata?) {
|
||||
this.name = name;
|
||||
this.metadata = metadata;
|
||||
}
|
||||
name: string;
|
||||
metadata: object;
|
||||
|
||||
|
@ -0,0 +1,92 @@
|
||||
import { HttpClientTestingModule } from '@angular/common/http/testing';
|
||||
import { inject, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { ToastModule } from 'ng2-toastr';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
|
||||
import { ExecutingTask } from '../models/executing-task';
|
||||
import { FinishedTask } from '../models/finished-task';
|
||||
import { SharedModule } from '../shared.module';
|
||||
import { configureTestBed } from '../unit-test-helper';
|
||||
import { NotificationService } from './notification.service';
|
||||
import { TaskManagerService } from './task-manager.service';
|
||||
import { TaskWrapperService } from './task-wrapper.service';
|
||||
|
||||
describe('TaskWrapperService', () => {
|
||||
let service: TaskWrapperService;
|
||||
|
||||
configureTestBed({
|
||||
imports: [HttpClientTestingModule, ToastModule.forRoot(), SharedModule],
|
||||
providers: [TaskWrapperService]
|
||||
});
|
||||
|
||||
beforeEach(inject([TaskWrapperService], (wrapper: TaskWrapperService) => {
|
||||
service = wrapper;
|
||||
}));
|
||||
|
||||
it('should be created', () => {
|
||||
expect(service).toBeTruthy();
|
||||
});
|
||||
|
||||
describe('wrapTaskAroundCall', () => {
|
||||
let notify: NotificationService;
|
||||
let tasks: ExecutingTask[];
|
||||
let passed: boolean;
|
||||
|
||||
const fakeCall = (status?) =>
|
||||
new Observable((observer) => {
|
||||
if (!status) {
|
||||
observer.error({ error: 'failed' });
|
||||
}
|
||||
observer.next({ status: status });
|
||||
observer.complete();
|
||||
});
|
||||
|
||||
const callWrapTaskAroundCall = (status, name) => {
|
||||
return service.wrapTaskAroundCall({
|
||||
task: new FinishedTask(name, { sth: 'else' }),
|
||||
call: fakeCall(status),
|
||||
tasks: tasks
|
||||
});
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
passed = false;
|
||||
tasks = [];
|
||||
notify = TestBed.get(NotificationService);
|
||||
spyOn(notify, 'show');
|
||||
spyOn(service, '_handleExecutingTasks').and.callThrough();
|
||||
});
|
||||
|
||||
it('should simulate a synchronous task', () => {
|
||||
callWrapTaskAroundCall(200, 'sync').subscribe(null, null, () => (passed = true));
|
||||
expect(service._handleExecutingTasks).not.toHaveBeenCalled();
|
||||
expect(passed).toBeTruthy();
|
||||
expect(tasks.length).toBe(0);
|
||||
});
|
||||
|
||||
it('should simulate a asynchronous task', () => {
|
||||
callWrapTaskAroundCall(202, 'async').subscribe(null, null, () => (passed = true));
|
||||
expect(service._handleExecutingTasks).toHaveBeenCalled();
|
||||
expect(passed).toBeTruthy();
|
||||
expect(tasks.length).toBe(1);
|
||||
});
|
||||
|
||||
it('should call notifyTask if asynchronous task would have been finished', () => {
|
||||
const taskManager = TestBed.get(TaskManagerService);
|
||||
spyOn(taskManager, 'subscribe').and.callFake((name, metadata, onTaskFinished) => {
|
||||
onTaskFinished();
|
||||
});
|
||||
spyOn(notify, 'notifyTask').and.stub();
|
||||
callWrapTaskAroundCall(202, 'async').subscribe(null, null, () => (passed = true));
|
||||
expect(notify.notifyTask).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should simulate a task failure', () => {
|
||||
callWrapTaskAroundCall(null, 'async').subscribe(null, () => (passed = true), null);
|
||||
expect(service._handleExecutingTasks).not.toHaveBeenCalled();
|
||||
expect(passed).toBeTruthy();
|
||||
expect(tasks.length).toBe(0);
|
||||
});
|
||||
});
|
||||
});
|
@ -0,0 +1,74 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
import { Subscriber } from 'rxjs/Subscriber';
|
||||
|
||||
import { NotificationType } from '../enum/notification-type.enum';
|
||||
import { ExecutingTask } from '../models/executing-task';
|
||||
import { FinishedTask } from '../models/finished-task';
|
||||
import { NotificationService } from './notification.service';
|
||||
import { ServicesModule } from './services.module';
|
||||
import { TaskManagerMessageService } from './task-manager-message.service';
|
||||
import { TaskManagerService } from './task-manager.service';
|
||||
|
||||
@Injectable({
|
||||
providedIn: ServicesModule
|
||||
})
|
||||
export class TaskWrapperService {
|
||||
constructor(
|
||||
private notificationService: NotificationService,
|
||||
private taskManagerMessageService: TaskManagerMessageService,
|
||||
private taskManagerService: TaskManagerService
|
||||
) {}
|
||||
|
||||
wrapTaskAroundCall({
|
||||
task,
|
||||
call,
|
||||
tasks
|
||||
}: {
|
||||
task: FinishedTask;
|
||||
call: Observable<any>;
|
||||
tasks?: ExecutingTask[];
|
||||
}) {
|
||||
return new Observable((observer: Subscriber<any>) => {
|
||||
call.subscribe(
|
||||
(resp) => {
|
||||
if (resp.status === 202) {
|
||||
this._handleExecutingTasks(task, tasks);
|
||||
} else {
|
||||
task.success = true;
|
||||
this.notificationService.notifyTask(task);
|
||||
}
|
||||
},
|
||||
(resp) => {
|
||||
task.success = false;
|
||||
task.exception = resp.error;
|
||||
this.notificationService.notifyTask(task);
|
||||
observer.error();
|
||||
},
|
||||
() => {
|
||||
observer.complete();
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
_handleExecutingTasks(task: FinishedTask, tasks?: ExecutingTask[]) {
|
||||
this.notificationService.show(
|
||||
NotificationType.info,
|
||||
task.name + ' in progress...',
|
||||
this.taskManagerMessageService.getDescription(task)
|
||||
);
|
||||
const executingTask = new ExecutingTask(task.name, task.metadata);
|
||||
if (tasks) {
|
||||
tasks.push(executingTask);
|
||||
}
|
||||
this.taskManagerService.subscribe(
|
||||
executingTask.name,
|
||||
executingTask.metadata,
|
||||
(asyncTask: FinishedTask) => {
|
||||
this.notificationService.notifyTask(asyncTask);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user