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' ;
@@ -25,14 +30,30 @@ import {
2530} from '../data/request.models' ;
2631import { RequestService } from '../data/request.service' ;
2732import { RequestError } from '../data/request-error.model' ;
28- import { RestRequest } from '../data/rest-request.model' ;
2933import { HttpOptions } from '../dspace-rest/dspace-rest.service' ;
3034import { HALEndpointService } from '../shared/hal-endpoint.service' ;
3135import { getFirstCompletedRemoteData } from '../shared/operators' ;
3236import { SubmitDataResponseDefinitionObject } from '../shared/submit-data-response-definition.model' ;
3337import { URLCombiner } from '../url-combiner/url-combiner' ;
3438import { SubmissionResponse } from './submission-response.model' ;
3539
40+ /**
41+ * Retrieve the first emitting payload's dataDefinition, or throw an error if the request failed
42+ */
43+ export const getFirstDataDefinition = ( ) =>
44+ ( source : Observable < RemoteData < SubmissionResponse > > ) : Observable < SubmitDataResponseDefinitionObject > =>
45+ source . pipe (
46+ getFirstCompletedRemoteData ( ) ,
47+ map ( ( response : RemoteData < SubmissionResponse > ) => {
48+ if ( response . hasFailed ) {
49+ throw new ErrorResponse ( { statusText : response . errorMessage , statusCode : response . statusCode } as RequestError ) ;
50+ } else {
51+ return hasValue ( response ?. payload ?. dataDefinition ) ? response . payload . dataDefinition : [ response . payload ] ;
52+ }
53+ } ) ,
54+ distinctUntilChanged ( ) ,
55+ ) ;
56+
3657/**
3758 * The service handling all submission REST requests
3859 */
@@ -56,15 +77,7 @@ export class SubmissionRestService {
5677 */
5778 protected fetchRequest ( requestId : string ) : Observable < SubmitDataResponseDefinitionObject > {
5879 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 ( ) ,
80+ getFirstDataDefinition ( ) ,
6881 ) ;
6982 }
7083
@@ -116,21 +129,52 @@ export class SubmissionRestService {
116129 * The endpoint link name
117130 * @param id
118131 * The submission Object to retrieve
132+ * @param useCachedVersionIfAvailable
133+ * If this is true, the request will only be sent if there's no valid & cached version. Defaults to false
119134 * @return Observable<SubmitDataResponseDefinitionObject>
120135 * server response
121136 */
122- public getDataById ( linkName : string , id : string ) : Observable < SubmitDataResponseDefinitionObject > {
123- const requestId = this . requestService . generateRequestId ( ) ;
137+ public getDataById ( linkName : string , id : string , useCachedVersionIfAvailable = false ) : Observable < SubmitDataResponseDefinitionObject > {
124138 return this . halService . getEndpoint ( linkName ) . pipe (
125139 map ( ( endpointURL : string ) => this . getEndpointByIDHref ( endpointURL , id ) ) ,
126140 filter ( ( href : string ) => isNotEmpty ( href ) ) ,
127141 distinctUntilChanged ( ) ,
128- map ( ( endpointURL : string ) => new SubmissionRequest ( requestId , endpointURL ) ) ,
129- tap ( ( request : RestRequest ) => {
130- this . requestService . send ( request ) ;
142+ mergeMap ( ( endpointURL : string ) => {
143+ this . sendGetDataRequest ( endpointURL , useCachedVersionIfAvailable ) ;
144+ const startTime : number = new Date ( ) . getTime ( ) ;
145+ return this . requestService . getByHref ( endpointURL ) . pipe (
146+ map ( ( requestEntry ) => requestEntry ?. request ?. uuid ) ,
147+ hasValueOperator ( ) ,
148+ distinctUntilChanged ( ) ,
149+ switchMap ( ( requestId ) => this . rdbService . buildFromRequestUUID < SubmissionResponse > ( requestId ) ) ,
150+ // This skip ensures that if a stale object is present in the cache when you do a
151+ // call it isn't immediately returned, but we wait until the remote data for the new request
152+ // is created. If useCachedVersionIfAvailable is false it also ensures you don't get a
153+ // cached completed object
154+ skipWhile ( ( rd : RemoteData < SubmissionResponse > ) => rd . isStale || ( ! useCachedVersionIfAvailable && rd . lastUpdated < startTime ) ) ,
155+ tap ( ( rd : RemoteData < SubmissionResponse > ) => {
156+ if ( hasValue ( rd ) && rd . isStale ) {
157+ this . sendGetDataRequest ( endpointURL , useCachedVersionIfAvailable ) ;
158+ }
159+ } ) ,
160+ ) ;
131161 } ) ,
132- mergeMap ( ( ) => this . fetchRequest ( requestId ) ) ,
133- distinctUntilChanged ( ) ) ;
162+ getFirstDataDefinition ( ) ,
163+ ) ;
164+ }
165+
166+ /**
167+ * Send a GET SubmissionRequest
168+ *
169+ * @param href
170+ * Endpoint URL of the submission data
171+ * @param useCachedVersionIfAvailable
172+ * If this is true, the request will only be sent if there's no valid & cached version. Defaults to false
173+ */
174+ private sendGetDataRequest ( href : string , useCachedVersionIfAvailable = false ) {
175+ const requestId = this . requestService . generateRequestId ( ) ;
176+ const request = new SubmissionRequest ( requestId , href ) ;
177+ this . requestService . send ( request , useCachedVersionIfAvailable ) ;
134178 }
135179
136180 /**
0 commit comments