annotate src/app/services/feature-extraction/feature-extraction.service.ts @ 324:e433a2da0ada

Refactor the import library logic slightly to waterfall the loading of the libraries and list requests, and send one response when all libraries have been loaded.
author Lucas Thompson <dev@lucas.im>
date Tue, 16 May 2017 16:16:57 +0100
parents 98490d0ceb77
children e401995304a7
rev   line source
dev@74 1 import {Injectable, Inject} from '@angular/core';
dev@47 2 import {
dev@226 3 ListResponse
dev@236 4 } from 'piper';
dev@64 5 import {
dev@226 6 SimpleRequest,
dev@226 7 SimpleResponse
dev@236 8 } from 'piper/HigherLevelUtilities';
dev@236 9 import {Subject} from 'rxjs/Subject';
dev@236 10 import {Observable} from 'rxjs/Observable';
dev@324 11 import {Http} from '@angular/http';
dev@226 12 import {
dev@226 13 countingIdProvider,
dev@226 14 WebWorkerStreamingClient
dev@236 15 } from 'piper/client-stubs/WebWorkerStreamingClient';
dev@236 16 import {RequestId} from 'piper/protocols/WebWorkerProtocol';
dev@316 17 import {collect, StreamingConfiguration} from 'piper/StreamingService';
dev@40 18
dev@74 19 type RepoUri = string;
dev@74 20 export interface AvailableLibraries {
dev@74 21 [libraryKey: string]: RepoUri;
dev@74 22 }
dev@74 23
dev@226 24 export interface Progress {
dev@226 25 id: RequestId;
dev@226 26 value: number; // between 0 and 100, for material-ui
dev@226 27 }
dev@226 28
dev@40 29 @Injectable()
dev@40 30 export class FeatureExtractionService {
dev@40 31
dev@40 32 private worker: Worker;
dev@64 33 private featuresExtracted: Subject<SimpleResponse>;
dev@64 34 featuresExtracted$: Observable<SimpleResponse>;
dev@74 35 private librariesUpdated: Subject<ListResponse>;
dev@74 36 librariesUpdated$: Observable<ListResponse>;
dev@226 37 private progressUpdated: Subject<Progress>;
dev@226 38 progressUpdated$: Observable<Progress>;
dev@226 39 private client: WebWorkerStreamingClient;
dev@44 40
dev@236 41 constructor(private http: Http,
dev@236 42 @Inject('PiperRepoUri') private repositoryUri: RepoUri) {
dev@40 43 this.worker = new Worker('bootstrap-feature-extraction-worker.js');
dev@64 44 this.featuresExtracted = new Subject<SimpleResponse>();
dev@51 45 this.featuresExtracted$ = this.featuresExtracted.asObservable();
dev@74 46 this.librariesUpdated = new Subject<ListResponse>();
dev@74 47 this.librariesUpdated$ = this.librariesUpdated.asObservable();
dev@226 48 this.progressUpdated = new Subject<Progress>();
dev@226 49 this.progressUpdated$ = this.progressUpdated.asObservable();
dev@74 50 this.worker.addEventListener('message', (ev: MessageEvent) => {
dev@74 51 const isValidResponse = ev.data.method === 'import'
dev@226 52 && ev.data.result && ev.data.result.available ;
dev@74 53 if (isValidResponse) {
dev@226 54 (ev as Event).stopImmediatePropagation();
dev@74 55 this.librariesUpdated.next(ev.data.result);
dev@74 56 }
dev@226 57 }, true);
dev@226 58
dev@226 59 this.client = new WebWorkerStreamingClient(
dev@226 60 this.worker,
dev@226 61 countingIdProvider(0)
dev@236 62 );
dev@40 63 }
dev@40 64
dev@47 65 list(): Promise<ListResponse> {
dev@324 66 return this.client.list({}).then(response => {
dev@324 67 this.librariesUpdated.next(response);
dev@324 68 return response;
dev@324 69 });
dev@40 70 }
dev@40 71
dev@226 72 extract(analysisItemId: string, request: SimpleRequest): Promise<void> {
dev@305 73 let config: StreamingConfiguration;
dev@305 74 return collect(this.client.process(request), val => {
dev@305 75 if (val.configuration) {
dev@305 76 config = val.configuration;
dev@305 77 }
dev@305 78 const progress = val.progress;
dev@305 79 if (progress.totalBlockCount > 0) {
dev@305 80 this.progressUpdated.next({
dev@305 81 id: analysisItemId,
dev@305 82 value: (progress.processedBlockCount / progress.totalBlockCount) * 100
dev@305 83 });
dev@305 84 }
dev@305 85 }).then(features => {
dev@305 86 this.featuresExtracted.next({
dev@305 87 features: features,
dev@305 88 outputDescriptor: config.outputDescriptor
dev@226 89 });
dev@305 90 });
dev@62 91 }
dev@62 92
dev@324 93 updateAvailableLibraries(): void {
dev@324 94 this.http.get(this.repositoryUri)
dev@324 95 .toPromise() // just turn into a promise for now to subscribe / execute
dev@324 96 .then(res => {
dev@74 97 this.worker.postMessage({
dev@74 98 method: 'addRemoteLibraries',
dev@324 99 params: res.json()
dev@324 100 })
dev@74 101 })
dev@324 102 .catch(console.error); // TODO Report error to user
dev@74 103 }
dev@74 104
dev@74 105 load(libraryKey: string): void {
dev@74 106 this.worker.postMessage({method: 'import', params: libraryKey});
dev@74 107 }
dev@40 108 }