11import { Injectable } from '@angular/core' ;
2- import { Observable } from 'rxjs' ;
2+ import {
3+ Observable ,
4+ skipWhile ,
5+ } from 'rxjs' ;
36import {
47 distinctUntilChanged ,
58 filter ,
69 map ,
710 mergeMap ,
11+ switchMap ,
812 tap ,
913} from 'rxjs/operators' ;
1014
1115import {
1216 hasValue ,
17+ hasValueOperator ,
1318 isNotEmpty ,
1419} from '../../shared/empty.util' ;
1520import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service' ;
16- import { ErrorResponse } from '../cache/response.models' ;
1721import { RemoteData } from '../data/remote-data' ;
1822import {
1923 DeleteRequest ,
@@ -24,15 +28,30 @@ import {
2428 SubmissionRequest ,
2529} from '../data/request.models' ;
2630import { RequestService } from '../data/request.service' ;
27- import { RequestError } from '../data/request-error.model' ;
28- import { RestRequest } from '../data/rest-request.model' ;
2931import { HttpOptions } from '../dspace-rest/dspace-rest.service' ;
3032import { HALEndpointService } from '../shared/hal-endpoint.service' ;
3133import { getFirstCompletedRemoteData } from '../shared/operators' ;
3234import { SubmitDataResponseDefinitionObject } from '../shared/submit-data-response-definition.model' ;
3335import { URLCombiner } from '../url-combiner/url-combiner' ;
3436import { SubmissionResponse } from './submission-response.model' ;
3537
38+ /**
39+ * Retrieve the first emitting payload's dataDefinition, or throw an error if the request failed
40+ */
41+ export const getFirstDataDefinition = ( ) =>
42+ ( source : Observable < RemoteData < SubmissionResponse > > ) : Observable < SubmitDataResponseDefinitionObject > =>
43+ source . pipe (
44+ getFirstCompletedRemoteData ( ) ,
45+ map ( ( response : RemoteData < SubmissionResponse > ) => {
46+ if ( response . hasFailed ) {
47+ throw new Error ( response . errorMessage ) ;
48+ } else {
49+ return hasValue ( response ?. payload ?. dataDefinition ) ? response . payload . dataDefinition : [ response . payload ] ;
50+ }
51+ } ) ,
52+ distinctUntilChanged ( ) ,
53+ ) ;
54+
3655/**
3756 * The service handling all submission REST requests
3857 */
@@ -56,15 +75,7 @@ export class SubmissionRestService {
5675 */
5776 protected fetchRequest ( requestId : string ) : Observable < SubmitDataResponseDefinitionObject > {
5877 return this . rdbService . buildFromRequestUUID < SubmissionResponse > ( requestId ) . pipe (
59- getFirstCompletedRemoteData ( ) ,
60- map ( ( response : RemoteData < SubmissionResponse > ) => {
61- if ( response . hasFailed ) {
62- throw new ErrorResponse ( { statusText : response . errorMessage , statusCode : response . statusCode } as RequestError ) ;
63- } else {
64- return hasValue ( response . payload ) ? response . payload . dataDefinition : response . payload ;
65- }
66- } ) ,
67- distinctUntilChanged ( ) ,
78+ getFirstDataDefinition ( ) ,
6879 ) ;
6980 }
7081
@@ -116,21 +127,52 @@ export class SubmissionRestService {
116127 * The endpoint link name
117128 * @param id
118129 * The submission Object to retrieve
130+ * @param useCachedVersionIfAvailable
131+ * If this is true, the request will only be sent if there's no valid & cached version. Defaults to false
119132 * @return Observable<SubmitDataResponseDefinitionObject>
120133 * server response
121134 */
122- public getDataById ( linkName : string , id : string ) : Observable < SubmitDataResponseDefinitionObject > {
123- const requestId = this . requestService . generateRequestId ( ) ;
135+ public getDataById ( linkName : string , id : string , useCachedVersionIfAvailable = false ) : Observable < SubmitDataResponseDefinitionObject > {
124136 return this . halService . getEndpoint ( linkName ) . pipe (
125137 map ( ( endpointURL : string ) => this . getEndpointByIDHref ( endpointURL , id ) ) ,
126138 filter ( ( href : string ) => isNotEmpty ( href ) ) ,
127139 distinctUntilChanged ( ) ,
128- map ( ( endpointURL : string ) => new SubmissionRequest ( requestId , endpointURL ) ) ,
129- tap ( ( request : RestRequest ) => {
130- this . requestService . send ( request ) ;
140+ mergeMap ( ( endpointURL : string ) => {
141+ this . sendGetDataRequest ( endpointURL , useCachedVersionIfAvailable ) ;
142+ const startTime : number = new Date ( ) . getTime ( ) ;
143+ return this . requestService . getByHref ( endpointURL ) . pipe (
144+ map ( ( requestEntry ) => requestEntry ?. request ?. uuid ) ,
145+ hasValueOperator ( ) ,
146+ distinctUntilChanged ( ) ,
147+ switchMap ( ( requestId ) => this . rdbService . buildFromRequestUUID < SubmissionResponse > ( requestId ) ) ,
148+ // This skip ensures that if a stale object is present in the cache when you do a
149+ // call it isn't immediately returned, but we wait until the remote data for the new request
150+ // is created. If useCachedVersionIfAvailable is false it also ensures you don't get a
151+ // cached completed object
152+ skipWhile ( ( rd : RemoteData < SubmissionResponse > ) => rd . isStale || ( ! useCachedVersionIfAvailable && rd . lastUpdated < startTime ) ) ,
153+ tap ( ( rd : RemoteData < SubmissionResponse > ) => {
154+ if ( hasValue ( rd ) && rd . isStale ) {
155+ this . sendGetDataRequest ( endpointURL , useCachedVersionIfAvailable ) ;
156+ }
157+ } ) ,
158+ ) ;
131159 } ) ,
132- mergeMap ( ( ) => this . fetchRequest ( requestId ) ) ,
133- distinctUntilChanged ( ) ) ;
160+ getFirstDataDefinition ( ) ,
161+ ) ;
162+ }
163+
164+ /**
165+ * Send a GET SubmissionRequest
166+ *
167+ * @param href
168+ * Endpoint URL of the submission data
169+ * @param useCachedVersionIfAvailable
170+ * If this is true, the request will only be sent if there's no valid & cached version. Defaults to false
171+ */
172+ private sendGetDataRequest ( href : string , useCachedVersionIfAvailable = false ) {
173+ const requestId = this . requestService . generateRequestId ( ) ;
174+ const request = new SubmissionRequest ( requestId , href ) ;
175+ this . requestService . send ( request , useCachedVersionIfAvailable ) ;
134176 }
135177
136178 /**
0 commit comments