Skip to content

Instantly share code, notes, and snippets.

@AndreasBaumgart
Created January 31, 2018 12:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save AndreasBaumgart/ca40f2ba0cafa170d9406a9da9e14e5b to your computer and use it in GitHub Desktop.
Save AndreasBaumgart/ca40f2ba0cafa170d9406a9da9e14e5b to your computer and use it in GitHub Desktop.
import 'rxjs/add/observable/interval';
import {Injectable} from '@angular/core';
import {Headers, Http, Response as HttpResponse} from '@angular/http';
import {Observable} from 'rxjs/Observable';
import {Observer} from 'rxjs/Observer';
import {Store} from '@ngrx/store';
import {getIdentity, State} from '../../store/reducers';
import {Identity} from '../auth/identity';
import {I18nService} from '../i18n/service';
type UserJobStatusStatus = 'pending' | 'processing' | 'ready' | 'fail' | 'internal_fail';
interface UserJobStatus {
href: string,
status: UserJobStatusStatus,
resultUrl: null | string
}
const POLL_INTERVAL = 2000;
@Injectable()
export class MpsDownloadService {
public static buildHeaders(identity: Identity, currentLocale: string) {
return new Headers({
'Content-Type': 'application/json',
'Accept': 'application/json',
'Authorization': identity.token,
'Accept-Language': `${currentLocale}; q=1.0`,
});
}
constructor(private http: Http,
private store$: Store<State>,
private i18n: I18nService) {
}
public downloadDelayed(url: string): Observable<void> {
return this.getDelayedDownloadUrl(url)
.map(resultUrl => {
window.open(resultUrl);
});
}
public getDelayedDownloadUrl(url: string): Observable<string> {
return Observable.create((o: Observer<string>) => {
const requirements$ = this.store$.select(getIdentity).take(1).withLatestFrom(this.i18n.getCurrentLocale());
requirements$.subscribe(([identity, currentLocale]: [Identity, string]) => {
const headers = MpsDownloadService.buildHeaders(identity, currentLocale);
this.http.post(url, {}, {headers}).subscribe((response: HttpResponse) => {
const status: UserJobStatus = response.json().data;
if (status.status === 'fail') {
console.error('Failed to fetch download URL', status);
o.error('Failed to fetch download URL');
} else if (status.status === 'ready') {
o.next(status.resultUrl);
o.complete();
} else {
this.pollResult(status.href)
.subscribe(resultUrl => {
o.next(resultUrl);
o.complete();
});
}
});
});
});
}
public pollResult(jobUrl): Observable<string> {
// TODO: Timeout!
return Observable
.interval(POLL_INTERVAL)
.withLatestFrom(this.store$.select(getIdentity), this.i18n.getCurrentLocale())
.map(([_, identity, currentLocale]) => MpsDownloadService.buildHeaders(identity, currentLocale))
.flatMap((headers: Headers) => this.http.get(jobUrl, {headers}).map((response: HttpResponse) => response.json()))
.map((data: any) => data.data)
.do(status => {
if (status.status === 'fail' || status.status === 'internal_fail') {
console.error('Download failed', status);
throw new Error('Download failed');
}
})
.map((status: any) => status.resultUrl)
.filter(resultUrl => null !== resultUrl)
.take(1)
;
}
public createDelayedDownloadPerformer(url: string): () => Promise<void> {
return () => {
return new Promise((resolve: () => void) => {
this
.downloadDelayed(url)
.subscribe(resolve);
});
};
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment