Mercurial > hg > ugly-duckling
comparison src/app/services/feature-extraction/FeatureExtractionWorker.ts @ 226:4865567d9e43
Refactor feature extraction service to use piper streaming client/server.
Change FeatureExtractionWorker accordingly and calling code.
author | Lucas Thompson <dev@lucas.im> |
---|---|
date | Fri, 21 Apr 2017 12:59:41 +0100 |
parents | 4aa6b1266251 |
children | efa23f33393b |
comparison
equal
deleted
inserted
replaced
225:16d19c12e42f | 226:4865567d9e43 |
---|---|
2 * Created by lucas on 01/12/2016. | 2 * Created by lucas on 01/12/2016. |
3 */ | 3 */ |
4 | 4 |
5 import {PiperVampService, ListRequest, ListResponse} from 'piper'; | 5 import {PiperVampService, ListRequest, ListResponse} from 'piper'; |
6 import { | 6 import { |
7 PiperSimpleClient, SimpleRequest, | 7 SimpleRequest |
8 SimpleResponse | |
9 } from 'piper/HigherLevelUtilities'; | 8 } from 'piper/HigherLevelUtilities'; |
10 import { VampExamplePlugins } from 'piper/ext/VampExamplePluginsModule'; | 9 import { VampExamplePlugins } from 'piper/ext/VampExamplePluginsModule'; |
11 import {AvailableLibraries} from "./feature-extraction.service"; | 10 import {AvailableLibraries} from "./feature-extraction.service"; |
11 import { | |
12 DedicatedWorkerGlobalScope, | |
13 WebWorkerStreamingServer | |
14 } from "piper/servers/WebWorkerStreamingServer"; | |
15 import { | |
16 PiperStreamingService, | |
17 StreamingResponse, | |
18 StreamingService | |
19 } from "piper/StreamingService"; | |
20 import {Observable} from "rxjs/Observable"; | |
12 | 21 |
13 // TODO TypeScript has a .d.ts file for webworkers, but for some reason it clashes with the typings for dom and causes compiler errors | |
14 interface WorkerGlobalScope { | |
15 onmessage: (this: this, ev: MessageEvent) => any; | |
16 postMessage(data: any): void; | |
17 importScripts(uri: string): void; | |
18 } | |
19 | 22 |
20 interface MessageEvent { | 23 interface MessageEvent { |
21 readonly data: any; | 24 readonly data: any; |
22 } | 25 } |
23 | 26 |
24 type LibraryUri = string; | 27 type LibraryUri = string; |
25 type LibraryKey = string; | 28 type LibraryKey = string; |
26 | 29 |
27 type RequireJs = (libs: string[], callback: (...libs: any[]) => void) => void; | 30 type RequireJs = (libs: string[], callback: (...libs: any[]) => void) => void; |
28 | 31 |
32 class AggregateStreamingService implements StreamingService { | |
33 private services: Map<LibraryKey, PiperStreamingService>; | |
34 | |
35 constructor() { | |
36 this.services = new Map<LibraryKey, PiperStreamingService>(); | |
37 this.services.set( | |
38 'vamp-example-plugins', | |
39 new PiperStreamingService(new PiperVampService(VampExamplePlugins())) | |
40 ); | |
41 } | |
42 | |
43 addService(key: LibraryKey, service: PiperStreamingService): void { | |
44 this.services.set(key, service); | |
45 } | |
46 | |
47 list(request: ListRequest): Promise<ListResponse> { | |
48 return Promise.all( | |
49 [...this.services.values()].map(client => client.list({})) | |
50 ).then(allAvailable => ({ | |
51 available: allAvailable.reduce( | |
52 (all, current) => all.concat(current.available), | |
53 [] | |
54 ) | |
55 }) | |
56 ); | |
57 } | |
58 | |
59 process(request: SimpleRequest): Observable<StreamingResponse> { | |
60 return undefined; | |
61 } | |
62 | |
63 collect(request: SimpleRequest): Observable<StreamingResponse> { | |
64 const key = request.key.split(':')[0]; | |
65 return this.services.has(key) ? | |
66 this.services.get(key).collect(request) : Observable.throw("Invalid key"); | |
67 } | |
68 } | |
69 | |
29 export default class FeatureExtractionWorker { | 70 export default class FeatureExtractionWorker { |
30 private workerScope: WorkerGlobalScope; | 71 private workerScope: DedicatedWorkerGlobalScope; |
31 private clients: Map<LibraryKey, PiperSimpleClient>; | 72 private services: Map<LibraryKey, PiperStreamingService>; |
32 private remoteLibraries: Map<LibraryKey, LibraryUri>; | 73 private remoteLibraries: Map<LibraryKey, LibraryUri>; |
74 private server: WebWorkerStreamingServer; | |
75 private service: AggregateStreamingService; | |
33 | 76 |
34 constructor(workerScope: WorkerGlobalScope, private requireJs: RequireJs) { | 77 constructor(workerScope: DedicatedWorkerGlobalScope, |
78 private requireJs: RequireJs) { | |
35 this.workerScope = workerScope; | 79 this.workerScope = workerScope; |
36 this.clients = new Map<LibraryKey, PiperSimpleClient>(); | 80 this.services = new Map<LibraryKey, PiperStreamingService>(); |
37 this.remoteLibraries = new Map<LibraryKey, LibraryUri>(); | 81 this.remoteLibraries = new Map<LibraryKey, LibraryUri>(); |
38 this.clients.set( | 82 this.service = new AggregateStreamingService(); |
39 'vamp-example-plugins', | 83 this.setupImportLibraryListener(); |
40 new PiperSimpleClient(new PiperVampService(VampExamplePlugins())) | 84 this.server = new WebWorkerStreamingServer( |
85 this.workerScope, | |
86 this.service | |
41 ); | 87 ); |
88 } | |
42 | 89 |
90 private setupImportLibraryListener(): void { | |
43 this.workerScope.onmessage = (ev: MessageEvent) => { | 91 this.workerScope.onmessage = (ev: MessageEvent) => { |
44 const sendResponse = (result) => { | 92 const sendResponse = (result) => { |
45 this.workerScope.postMessage({ | 93 this.workerScope.postMessage({ |
46 method: ev.data.method, | 94 method: ev.data.method, |
47 result: result | 95 result: result |
48 }); | 96 }); |
49 }; | 97 }; |
50 switch (ev.data.method) { | 98 switch (ev.data.method) { |
51 case 'list': | |
52 this.list(ev.data.params) | |
53 .then(sendResponse) | |
54 .catch(err => console.error(err)); // TODO handle error | |
55 break; | |
56 case 'process': | |
57 this.process(ev.data.params) | |
58 .then(sendResponse) | |
59 .catch(err => console.error(err)); // TODO handle error | |
60 break; | |
61 case 'collect': | |
62 this.collect(ev.data.params) | |
63 .then(sendResponse) | |
64 .catch(err => console.error(err)); // TODO handle error | |
65 break; | |
66 case 'import': | 99 case 'import': |
67 // this.workerScope.importScripts(ev.data.params); | |
68 const key: LibraryKey = ev.data.params; | 100 const key: LibraryKey = ev.data.params; |
69 if (this.remoteLibraries.has(key)) { | 101 if (this.remoteLibraries.has(key)) { |
70 this.requireJs([this.remoteLibraries.get(key)], (plugin) => { | 102 this.requireJs([this.remoteLibraries.get(key)], (plugin) => { |
71 this.clients.set( | 103 this.services.set( |
72 key, | 104 key, |
73 new PiperSimpleClient(new PiperVampService(plugin.createLibrary())) | 105 new PiperStreamingService( |
106 new PiperVampService(plugin.createLibrary()) | |
107 ) | |
74 ); // TODO won't always be an emscripten module | 108 ); // TODO won't always be an emscripten module |
75 this.list({}).then(sendResponse); | 109 this.service.addService(key, this.services.get(key)); |
110 this.service.list({}).then(sendResponse); | |
76 }); | 111 }); |
77 } else { | 112 } else { |
78 console.error('Non registered library key.'); // TODO handle error | 113 console.error('Non registered library key.'); // TODO handle error |
79 } | 114 } |
80 break; | 115 break; |
84 this.remoteLibraries.set(key, available[key]); | 119 this.remoteLibraries.set(key, available[key]); |
85 }); | 120 }); |
86 } | 121 } |
87 }; | 122 }; |
88 } | 123 } |
89 | |
90 private list(request: ListRequest): Promise<ListResponse> { | |
91 // TODO actually pay attention to ListRequest | |
92 return Promise.all([...this.clients.values()].map(client => client.list({}))) | |
93 .then(allAvailable => { | |
94 return { | |
95 available: allAvailable.reduce( | |
96 (all, current) => all.concat(current.available), | |
97 [] | |
98 ) | |
99 }; | |
100 }); | |
101 } | |
102 | |
103 // TODO reduce dupe | |
104 private process(request: SimpleRequest): Promise<SimpleResponse> { | |
105 const key: LibraryKey = request.key.split(':')[0]; | |
106 const client: PiperSimpleClient = this.clients.get(key); | |
107 return client ? client.process(request) : Promise.reject("Invalid plugin library key."); | |
108 } | |
109 | |
110 private collect(request: SimpleRequest): Promise<SimpleResponse> { | |
111 const key: LibraryKey = request.key.split(':')[0]; | |
112 const client: PiperSimpleClient = this.clients.get(key); | |
113 return client ? client.collect(request) : Promise.reject("Invalid plugin library key."); | |
114 } | |
115 } | 124 } |