11import { Injectable } from '@angular/core' ;
22
3- import { Observable } from 'rxjs' ;
4- import { distinctUntilChanged , filter , map , mergeMap , tap } from 'rxjs/operators' ;
3+ import { Observable , skipWhile } from 'rxjs' ;
4+ import { distinctUntilChanged , filter , map , mergeMap , switchMap , tap } from 'rxjs/operators' ;
55
66import { RequestService } from '../data/request.service' ;
7- import { hasValue , isNotEmpty } from '../../shared/empty.util' ;
7+ import { hasValue , hasValueOperator , isNotEmpty } from '../../shared/empty.util' ;
88import {
99 DeleteRequest ,
1010 PostRequest ,
@@ -19,11 +19,25 @@ import { HALEndpointService } from '../shared/hal-endpoint.service';
1919import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service' ;
2020import { getFirstCompletedRemoteData } from '../shared/operators' ;
2121import { URLCombiner } from '../url-combiner/url-combiner' ;
22- import { ErrorResponse } from '../cache/response.models' ;
2322import { RemoteData } from '../data/remote-data' ;
2423import { SubmissionResponse } from './submission-response.model' ;
25- import { RequestError } from '../data/request-error.model' ;
26- import { RestRequest } from '../data/rest-request.model' ;
24+
25+ /**
26+ * Retrieve the first emitting payload's dataDefinition, or throw an error if the request failed
27+ */
28+ export const getFirstDataDefinition = ( ) =>
29+ ( source : Observable < RemoteData < SubmissionResponse > > ) : Observable < SubmitDataResponseDefinitionObject > =>
30+ source . pipe (
31+ getFirstCompletedRemoteData ( ) ,
32+ map ( ( response : RemoteData < SubmissionResponse > ) => {
33+ if ( response . hasFailed ) {
34+ throw new Error ( response . errorMessage ) ;
35+ } else {
36+ return hasValue ( response ?. payload ?. dataDefinition ) ? response . payload . dataDefinition : [ response . payload ] ;
37+ }
38+ } ) ,
39+ distinctUntilChanged ( ) ,
40+ ) ;
2741
2842/**
2943 * The service handling all submission REST requests
@@ -48,15 +62,7 @@ export class SubmissionRestService {
4862 */
4963 protected fetchRequest ( requestId : string ) : Observable < SubmitDataResponseDefinitionObject > {
5064 return this . rdbService . buildFromRequestUUID < SubmissionResponse > ( requestId ) . pipe (
51- getFirstCompletedRemoteData ( ) ,
52- map ( ( response : RemoteData < SubmissionResponse > ) => {
53- if ( response . hasFailed ) {
54- throw new ErrorResponse ( { statusText : response . errorMessage , statusCode : response . statusCode } as RequestError ) ;
55- } else {
56- return hasValue ( response . payload ) ? response . payload . dataDefinition : response . payload ;
57- }
58- } ) ,
59- distinctUntilChanged ( )
65+ getFirstDataDefinition ( ) ,
6066 ) ;
6167 }
6268
@@ -108,21 +114,52 @@ export class SubmissionRestService {
108114 * The endpoint link name
109115 * @param id
110116 * The submission Object to retrieve
117+ * @param useCachedVersionIfAvailable
118+ * If this is true, the request will only be sent if there's no valid & cached version. Defaults to false
111119 * @return Observable<SubmitDataResponseDefinitionObject>
112120 * server response
113121 */
114- public getDataById ( linkName : string , id : string ) : Observable < SubmitDataResponseDefinitionObject > {
115- const requestId = this . requestService . generateRequestId ( ) ;
122+ public getDataById ( linkName : string , id : string , useCachedVersionIfAvailable = false ) : Observable < SubmitDataResponseDefinitionObject > {
116123 return this . halService . getEndpoint ( linkName ) . pipe (
117124 map ( ( endpointURL : string ) => this . getEndpointByIDHref ( endpointURL , id ) ) ,
118125 filter ( ( href : string ) => isNotEmpty ( href ) ) ,
119126 distinctUntilChanged ( ) ,
120- map ( ( endpointURL : string ) => new SubmissionRequest ( requestId , endpointURL ) ) ,
121- tap ( ( request : RestRequest ) => {
122- this . requestService . send ( request ) ;
127+ mergeMap ( ( endpointURL : string ) => {
128+ this . sendGetDataRequest ( endpointURL , useCachedVersionIfAvailable ) ;
129+ const startTime : number = new Date ( ) . getTime ( ) ;
130+ return this . requestService . getByHref ( endpointURL ) . pipe (
131+ map ( ( requestEntry ) => requestEntry ?. request ?. uuid ) ,
132+ hasValueOperator ( ) ,
133+ distinctUntilChanged ( ) ,
134+ switchMap ( ( requestId ) => this . rdbService . buildFromRequestUUID < SubmissionResponse > ( requestId ) ) ,
135+ // This skip ensures that if a stale object is present in the cache when you do a
136+ // call it isn't immediately returned, but we wait until the remote data for the new request
137+ // is created. If useCachedVersionIfAvailable is false it also ensures you don't get a
138+ // cached completed object
139+ skipWhile ( ( rd : RemoteData < SubmissionResponse > ) => rd . isStale || ( ! useCachedVersionIfAvailable && rd . lastUpdated < startTime ) ) ,
140+ tap ( ( rd : RemoteData < SubmissionResponse > ) => {
141+ if ( hasValue ( rd ) && rd . isStale ) {
142+ this . sendGetDataRequest ( endpointURL , useCachedVersionIfAvailable ) ;
143+ }
144+ } )
145+ ) ;
123146 } ) ,
124- mergeMap ( ( ) => this . fetchRequest ( requestId ) ) ,
125- distinctUntilChanged ( ) ) ;
147+ getFirstDataDefinition ( ) ,
148+ ) ;
149+ }
150+
151+ /**
152+ * Send a GET SubmissionRequest
153+ *
154+ * @param href
155+ * Endpoint URL of the submission data
156+ * @param useCachedVersionIfAvailable
157+ * If this is true, the request will only be sent if there's no valid & cached version. Defaults to false
158+ */
159+ private sendGetDataRequest ( href : string , useCachedVersionIfAvailable = false ) {
160+ const requestId = this . requestService . generateRequestId ( ) ;
161+ const request = new SubmissionRequest ( requestId , href ) ;
162+ this . requestService . send ( request , useCachedVersionIfAvailable ) ;
126163 }
127164
128165 /**
0 commit comments