Skip to content

Commit 45650c1

Browse files
authored
Merge pull request DSpace#2480 from atmire/feature-process_polling
Feature process polling
2 parents 1c7f098 + 049fbb8 commit 45650c1

28 files changed

Lines changed: 652 additions & 417 deletions

src/app/collection-page/edit-collection-page/collection-source/collection-source-controls/collection-source-controls.component.spec.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ describe('CollectionSourceControlsComponent', () => {
8888
invoke: createSuccessfulRemoteDataObject$(process),
8989
});
9090
processDataService = jasmine.createSpyObj('processDataService', {
91-
findById: createSuccessfulRemoteDataObject$(process),
91+
autoRefreshUntilCompletion: createSuccessfulRemoteDataObject$(process),
9292
});
9393
bitstreamService = jasmine.createSpyObj('bitstreamService', {
9494
findByHref: createSuccessfulRemoteDataObject$(bitstream),
@@ -137,7 +137,7 @@ describe('CollectionSourceControlsComponent', () => {
137137
{name: '-i', value: new ContentSourceSetSerializer().Serialize(contentSource.oaiSetId)},
138138
], []);
139139

140-
expect(processDataService.findById).toHaveBeenCalledWith(process.processId, false);
140+
expect(processDataService.autoRefreshUntilCompletion).toHaveBeenCalledWith(process.processId);
141141
expect(bitstreamService.findByHref).toHaveBeenCalledWith(process._links.output.href);
142142
expect(notificationsService.info).toHaveBeenCalledWith(jasmine.anything() as any, 'Script text');
143143
});
@@ -151,7 +151,7 @@ describe('CollectionSourceControlsComponent', () => {
151151
{name: '-r', value: null},
152152
{name: '-c', value: collection.uuid},
153153
], []);
154-
expect(processDataService.findById).toHaveBeenCalledWith(process.processId, false);
154+
expect(processDataService.autoRefreshUntilCompletion).toHaveBeenCalledWith(process.processId);
155155
expect(notificationsService.success).toHaveBeenCalled();
156156
});
157157
});
@@ -164,7 +164,7 @@ describe('CollectionSourceControlsComponent', () => {
164164
{name: '-o', value: null},
165165
{name: '-c', value: collection.uuid},
166166
], []);
167-
expect(processDataService.findById).toHaveBeenCalledWith(process.processId, false);
167+
expect(processDataService.autoRefreshUntilCompletion).toHaveBeenCalledWith(process.processId);
168168
expect(notificationsService.success).toHaveBeenCalled();
169169
});
170170
});

src/app/collection-page/edit-collection-page/collection-source/collection-source-controls/collection-source-controls.component.ts

Lines changed: 39 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,12 @@ import { ScriptDataService } from '../../../../core/data/processes/script-data.s
33
import { ContentSource } from '../../../../core/shared/content-source.model';
44
import { ProcessDataService } from '../../../../core/data/processes/process-data.service';
55
import {
6-
getAllCompletedRemoteData,
76
getAllSucceededRemoteDataPayload,
87
getFirstCompletedRemoteData,
98
getFirstSucceededRemoteDataPayload
109
} from '../../../../core/shared/operators';
1110
import { filter, map, switchMap, tap } from 'rxjs/operators';
12-
import { hasValue, hasValueOperator } from '../../../../shared/empty.util';
11+
import { hasValue } from '../../../../shared/empty.util';
1312
import { ProcessStatus } from '../../../../process-page/processes/process-status.model';
1413
import { BehaviorSubject, Observable, Subscription } from 'rxjs';
1514
import { RequestService } from '../../../../core/data/request.service';
@@ -95,36 +94,25 @@ export class CollectionSourceControlsComponent implements OnDestroy {
9594
}),
9695
// filter out responses that aren't successful since the pinging of the process only needs to happen when the invocation was successful.
9796
filter((rd) => rd.hasSucceeded && hasValue(rd.payload)),
98-
switchMap((rd) => this.processDataService.findById(rd.payload.processId, false)),
99-
getAllCompletedRemoteData(),
100-
filter((rd) => !rd.isStale && (rd.hasSucceeded || rd.hasFailed)),
101-
map((rd) => rd.payload),
102-
hasValueOperator(),
97+
switchMap((rd) => this.processDataService.autoRefreshUntilCompletion(rd.payload.processId)),
98+
map((rd) => rd.payload)
10399
).subscribe((process: Process) => {
104-
if (process.processStatus.toString() !== ProcessStatus[ProcessStatus.COMPLETED].toString() &&
105-
process.processStatus.toString() !== ProcessStatus[ProcessStatus.FAILED].toString()) {
106-
// Ping the current process state every 5s
107-
setTimeout(() => {
108-
this.requestService.setStaleByHrefSubstring(process._links.self.href);
109-
}, 5000);
110-
}
111-
if (process.processStatus.toString() === ProcessStatus[ProcessStatus.FAILED].toString()) {
112-
this.notificationsService.error(this.translateService.get('collection.source.controls.test.failed'));
113-
this.testConfigRunning$.next(false);
114-
}
115-
if (process.processStatus.toString() === ProcessStatus[ProcessStatus.COMPLETED].toString()) {
116-
this.bitstreamService.findByHref(process._links.output.href).pipe(getFirstSucceededRemoteDataPayload()).subscribe((bitstream) => {
117-
this.httpClient.get(bitstream._links.content.href, {responseType: 'text'}).subscribe((data: any) => {
118-
const output = data.replaceAll(new RegExp('.*\\@(.*)', 'g'), '$1')
119-
.replaceAll('The script has started', '')
120-
.replaceAll('The script has completed', '');
121-
this.notificationsService.info(this.translateService.get('collection.source.controls.test.completed'), output);
122-
});
100+
if (process.processStatus.toString() === ProcessStatus[ProcessStatus.FAILED].toString()) {
101+
this.notificationsService.error(this.translateService.get('collection.source.controls.test.failed'));
102+
this.testConfigRunning$.next(false);
103+
}
104+
if (process.processStatus.toString() === ProcessStatus[ProcessStatus.COMPLETED].toString()) {
105+
this.bitstreamService.findByHref(process._links.output.href).pipe(getFirstSucceededRemoteDataPayload()).subscribe((bitstream) => {
106+
this.httpClient.get(bitstream._links.content.href, {responseType: 'text'}).subscribe((data: any) => {
107+
const output = data.replaceAll(new RegExp('.*\\@(.*)', 'g'), '$1')
108+
.replaceAll('The script has started', '')
109+
.replaceAll('The script has completed', '');
110+
this.notificationsService.info(this.translateService.get('collection.source.controls.test.completed'), output);
123111
});
124-
this.testConfigRunning$.next(false);
125-
}
112+
});
113+
this.testConfigRunning$.next(false);
126114
}
127-
));
115+
}));
128116
}
129117

130118
/**
@@ -147,31 +135,19 @@ export class CollectionSourceControlsComponent implements OnDestroy {
147135
}
148136
}),
149137
filter((rd) => rd.hasSucceeded && hasValue(rd.payload)),
150-
switchMap((rd) => this.processDataService.findById(rd.payload.processId, false)),
151-
getAllCompletedRemoteData(),
152-
filter((rd) => !rd.isStale && (rd.hasSucceeded || rd.hasFailed)),
153-
map((rd) => rd.payload),
154-
hasValueOperator(),
138+
switchMap((rd) => this.processDataService.autoRefreshUntilCompletion(rd.payload.processId)),
139+
map((rd) => rd.payload)
155140
).subscribe((process) => {
156-
if (process.processStatus.toString() !== ProcessStatus[ProcessStatus.COMPLETED].toString() &&
157-
process.processStatus.toString() !== ProcessStatus[ProcessStatus.FAILED].toString()) {
158-
// Ping the current process state every 5s
159-
setTimeout(() => {
160-
this.requestService.setStaleByHrefSubstring(process._links.self.href);
161-
this.requestService.setStaleByHrefSubstring(this.collection._links.self.href);
162-
}, 5000);
163-
}
164-
if (process.processStatus.toString() === ProcessStatus[ProcessStatus.FAILED].toString()) {
165-
this.notificationsService.error(this.translateService.get('collection.source.controls.import.failed'));
166-
this.importRunning$.next(false);
167-
}
168-
if (process.processStatus.toString() === ProcessStatus[ProcessStatus.COMPLETED].toString()) {
169-
this.notificationsService.success(this.translateService.get('collection.source.controls.import.completed'));
170-
this.requestService.setStaleByHrefSubstring(this.collection._links.self.href);
171-
this.importRunning$.next(false);
172-
}
141+
if (process.processStatus.toString() === ProcessStatus[ProcessStatus.FAILED].toString()) {
142+
this.notificationsService.error(this.translateService.get('collection.source.controls.import.failed'));
143+
this.importRunning$.next(false);
144+
}
145+
if (process.processStatus.toString() === ProcessStatus[ProcessStatus.COMPLETED].toString()) {
146+
this.notificationsService.success(this.translateService.get('collection.source.controls.import.completed'));
147+
this.requestService.setStaleByHrefSubstring(this.collection._links.self.href);
148+
this.importRunning$.next(false);
173149
}
174-
));
150+
}));
175151
}
176152

177153
/**
@@ -194,31 +170,19 @@ export class CollectionSourceControlsComponent implements OnDestroy {
194170
}
195171
}),
196172
filter((rd) => rd.hasSucceeded && hasValue(rd.payload)),
197-
switchMap((rd) => this.processDataService.findById(rd.payload.processId, false)),
198-
getAllCompletedRemoteData(),
199-
filter((rd) => !rd.isStale && (rd.hasSucceeded || rd.hasFailed)),
200-
map((rd) => rd.payload),
201-
hasValueOperator(),
173+
switchMap((rd) => this.processDataService.autoRefreshUntilCompletion(rd.payload.processId)),
174+
map((rd) => rd.payload)
202175
).subscribe((process) => {
203-
if (process.processStatus.toString() !== ProcessStatus[ProcessStatus.COMPLETED].toString() &&
204-
process.processStatus.toString() !== ProcessStatus[ProcessStatus.FAILED].toString()) {
205-
// Ping the current process state every 5s
206-
setTimeout(() => {
207-
this.requestService.setStaleByHrefSubstring(process._links.self.href);
208-
this.requestService.setStaleByHrefSubstring(this.collection._links.self.href);
209-
}, 5000);
210-
}
211-
if (process.processStatus.toString() === ProcessStatus[ProcessStatus.FAILED].toString()) {
212-
this.notificationsService.error(this.translateService.get('collection.source.controls.reset.failed'));
213-
this.reImportRunning$.next(false);
214-
}
215-
if (process.processStatus.toString() === ProcessStatus[ProcessStatus.COMPLETED].toString()) {
216-
this.notificationsService.success(this.translateService.get('collection.source.controls.reset.completed'));
217-
this.requestService.setStaleByHrefSubstring(this.collection._links.self.href);
218-
this.reImportRunning$.next(false);
219-
}
176+
if (process.processStatus.toString() === ProcessStatus[ProcessStatus.FAILED].toString()) {
177+
this.notificationsService.error(this.translateService.get('collection.source.controls.reset.failed'));
178+
this.reImportRunning$.next(false);
179+
}
180+
if (process.processStatus.toString() === ProcessStatus[ProcessStatus.COMPLETED].toString()) {
181+
this.notificationsService.success(this.translateService.get('collection.source.controls.reset.completed'));
182+
this.requestService.setStaleByHrefSubstring(this.collection._links.self.href);
183+
this.reImportRunning$.next(false);
220184
}
221-
));
185+
}));
222186
}
223187

224188
ngOnDestroy(): void {

src/app/core/cache/builders/remote-data-build.service.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -273,12 +273,13 @@ export class RemoteDataBuildService {
273273
return isStale(r2.state) ? r1 : r2;
274274
}
275275
}),
276-
distinctUntilKeyChanged('lastUpdated')
277276
);
278277

279278
const payload$ = this.buildPayload<T>(requestEntry$, href$, ...linksToFollow);
280279

281-
return this.toRemoteDataObservable<T>(requestEntry$, payload$);
280+
return this.toRemoteDataObservable<T>(requestEntry$, payload$).pipe(
281+
distinctUntilKeyChanged('lastUpdated'),
282+
);
282283
}
283284

284285
/**

0 commit comments

Comments
 (0)