Skip to content

Commit 6ff81d8

Browse files
authored
[O2B-1569] Fix duplicated requests sent by front-end for runs-per-data-pass page (#2109)
* Prevent pagination from re-calling data pass id endpoint * Fetch items only when needed * Fetch runs from data pass only if pagination did not already do so * Trigger an immediate update in case observable already finished * Registration should happen only when page is loaded * Check if pagination triggered event More details: * request GET `dataPass` for specific id is sent 2 times instead of one because of pagination observer and initial loading page; * because of the double fetching, the summary request of QC periods is done also 2 times. Moreover, for each of the 2 times, the observer kicks in and does another 2 same requests, bringing the total to 4 summary requests fetching the same data in parallel (not even in sequence so that the browser can use its cache mechanism) * registration of events was moved to `load` methods as otherwise they will trigger in constructor (at load of application) * rename of miss-spelled words * total requests now down to 9 from 17 and loading times of all requests together for `runs-per-data-pass` halved
1 parent 0977d77 commit 6ff81d8

5 files changed

Lines changed: 88 additions & 55 deletions

File tree

lib/public/views/Runs/Overview/RunsWithQcModel.js

Lines changed: 50 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ export class RunsWithQcModel extends RunsOverviewModel {
7070
constructor(model) {
7171
super(model);
7272

73+
this._observablesQcFlagsSummaryDependsOn$ = null;
7374
this._mcReproducibleAsNotBad = false;
7475

7576
this._runDetectorsSelectionModel = new RunDetectorsSelectionModel();
@@ -131,57 +132,73 @@ export class RunsWithQcModel extends RunsOverviewModel {
131132
*/
132133
async load() {
133134
this._runDetectorsSelectionModel.reset();
134-
this._fetchQcSummary();
135+
// Only fetch QC summary manually if no observer is registered
136+
if (!this._observablesQcFlagsSummaryDependsOn$) {
137+
this._fetchQcSummary();
138+
}
135139
super.load();
136140
}
137141

138142
/**
139-
* Register not-bad fraction detectors filtering model
143+
* Register not-bad fraction detectors filtering model and update it when detectors are loaded
144+
* Also, trigger an immediate update if detectors are already loaded at the moment of registration
140145
*
141146
* @param {ObservableData<RemoteData<Detector>>} detectors$ detectors remote data observable
142147
*/
143148
registerDetectorsNotBadFractionFilterModels(detectors$) {
144-
detectors$.observe((observableData) => observableData.getCurrent().apply({
145-
Success: (detectors) => detectors.forEach(({ id }) => {
146-
this._filteringModel.put(`detectorsQc[_${id}][notBadFraction]`, new NumericalComparisonFilterModel({
147-
scale: 0.01,
148-
integer: false,
149-
}));
150-
}),
151-
}));
149+
const callback = (observableData) => {
150+
const current = observableData.getCurrent();
151+
current?.apply({
152+
Success: (detectors) => detectors.forEach(({ id }) => {
153+
this._filteringModel.put(`detectorsQc[_${id}][notBadFraction]`, new NumericalComparisonFilterModel({
154+
scale: 0.01,
155+
integer: false,
156+
}));
157+
}),
158+
});
159+
};
160+
detectors$.observe(callback);
161+
callback(detectors$);
152162
}
153163

154164
/**
155-
* Register detectors for QC flags data export
165+
* Register detectors for QC flags data export and update export configuration when detectors are loaded
166+
* Also, trigger an immediate update if detectors are already loaded at the moment of registration
156167
*
157168
* @param {ObservableData<RemoteData<Detector>>} detectors$ detectors remote data observable
158169
*/
159170
registerDetectorsForQcFlagsDataExport(detectors$) {
160-
detectors$.observe((observableData) => observableData.getCurrent().apply({
161-
Success: (detectors) => {
162-
this._exportModel.setDataExportConfiguration({
163-
...baseDataExportConfiguration,
164-
...qcFlagsExportConfigurationFactory(detectors),
165-
});
166-
},
167-
Other: () => null,
168-
}));
171+
const callback = (observableData) => {
172+
const current = observableData.getCurrent();
173+
current?.apply({
174+
Success: (detectors) => {
175+
this._exportModel.setDataExportConfiguration({
176+
...baseDataExportConfiguration,
177+
...qcFlagsExportConfigurationFactory(detectors),
178+
});
179+
},
180+
Other: () => null,
181+
});
182+
};
183+
detectors$.observe(callback);
184+
// Also trigger immediately if detectors are already loaded
185+
callback(detectors$);
169186
}
170187

171188
/**
172-
* Register obervables data, which QC flags fetching operation success dependes on
189+
* Register observables data, which QC flags fetching operation success depends on
173190
*
174-
* @param {ObservableData<RemoteData>[]} observables obervable data list
191+
* @param {ObservableData<RemoteData<Detector>>} detectors$ observable data which QC flags fetching operation success depends on
175192
*/
176-
registerObervablesQcSummaryDependesOn(observables) {
177-
this._observablesQcFlagsSummaryDepndsOn$ = ObservableData
178-
.builder()
179-
.sources(observables)
180-
.apply((remoteDataList) => mergeRemoteData(remoteDataList))
181-
.build();
182-
183-
this._observablesQcFlagsSummaryDepndsOn$
184-
.observe((observableData) => observableData.getCurrent().apply({ Success: () => this._fetchQcSummary() }));
193+
registerObservablesQcSummaryDependsOn(detectors$) {
194+
this._observablesQcFlagsSummaryDependsOn$ = detectors$;
195+
const callback = (observableData) => {
196+
const current = observableData.getCurrent();
197+
current?.apply({ Success: () => this._fetchQcSummary() });
198+
};
199+
this._observablesQcFlagsSummaryDependsOn$.observe(callback);
200+
// Also trigger immediately if detectors are already loaded
201+
callback(this._observablesQcFlagsSummaryDependsOn$);
185202
}
186203

187204
/**
@@ -208,8 +225,8 @@ export class RunsWithQcModel extends RunsOverviewModel {
208225
async _fetchQcSummary() {
209226
const qcSummaryScopeValid = Object.entries(this.qcSummaryScope).filter(([, id]) => id).length == 1;
210227

211-
if (qcSummaryScopeValid && this.detectors && this._observablesQcFlagsSummaryDepndsOn$.getCurrent()) {
212-
mergeRemoteData([this.detectors, this._observablesQcFlagsSummaryDepndsOn$.getCurrent()]).match({
228+
if (qcSummaryScopeValid && this.detectors && this._observablesQcFlagsSummaryDependsOn$?.getCurrent()) {
229+
mergeRemoteData([this.detectors, this._observablesQcFlagsSummaryDependsOn$.getCurrent()]).match({
213230
Success: async ([detectors]) => {
214231
this._qcSummary$.setCurrent(RemoteData.loading());
215232
try {

lib/public/views/Runs/RunPerDataPass/RunsPerDataPassOverviewModel.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,6 @@ export class RunsPerDataPassOverviewModel extends FixedPdpBeamTypeRunsOverviewMo
5252
.build();
5353

5454
this._detectors$.bubbleTo(this);
55-
this.registerDetectorsNotBadFractionFilterModels(this._detectors$);
56-
this.registerDetectorsForQcFlagsDataExport(this._detectors$);
57-
this.registerObervablesQcSummaryDependesOn([this._detectors$]);
5855

5956
this._markAsSkimmableRequestResult$ = new ObservableData(RemoteData.notAsked());
6057
this._markAsSkimmableRequestResult$.bubbleTo(this);
@@ -135,6 +132,11 @@ export class RunsPerDataPassOverviewModel extends FixedPdpBeamTypeRunsOverviewMo
135132
},
136133
Other: () => null,
137134
}));
135+
136+
this.registerDetectorsNotBadFractionFilterModels(this._detectors$);
137+
this.registerDetectorsForQcFlagsDataExport(this._detectors$);
138+
this.registerObservablesQcSummaryDependsOn(this._detectors$);
139+
138140
super.load();
139141
}
140142

lib/public/views/Runs/RunPerPeriod/RunsPerLhcPeriodOverviewModel.js

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,6 @@ export class RunsPerLhcPeriodOverviewModel extends FixedPdpBeamTypeRunsOverviewM
4949
}))
5050
.build();
5151

52-
this.registerDetectorsForQcFlagsDataExport(this._syncDetectors$);
53-
this.registerObervablesQcSummaryDependesOn([this._syncDetectors$]);
54-
5552
this._syncDetectors$.bubbleTo(this);
5653
this._onlineDetectors$.bubbleTo(this);
5754
this._lhcPeriodStatistics$.bubbleTo(this);
@@ -82,12 +79,15 @@ export class RunsPerLhcPeriodOverviewModel extends FixedPdpBeamTypeRunsOverviewM
8279
return;
8380
}
8481

85-
await this._fetchLhcPeriod().then(() => {
86-
this._lhcPeriodStatistics$.getCurrent().match({
87-
Success: ({ pdpBeamTypes }) => this.setPdpBeamTypes(pdpBeamTypes),
88-
Other: () => null,
89-
});
82+
await this._fetchLhcPeriod();
83+
this._lhcPeriodStatistics$.getCurrent().match({
84+
Success: ({ pdpBeamTypes }) => this.setPdpBeamTypes(pdpBeamTypes),
85+
Other: () => null,
9086
});
87+
88+
this.registerDetectorsForQcFlagsDataExport(this._syncDetectors$);
89+
this.registerObservablesQcSummaryDependsOn(this._syncDetectors$);
90+
9191
super.load();
9292
}
9393

lib/public/views/Runs/RunsModel.js

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,14 @@ export class RunsModel extends Observable {
114114
loadPerDataPassOverview({ dataPassId }) {
115115
if (!this._perDataPassOverviewModel.pagination.isInfiniteScrollEnabled) {
116116
this._perDataPassOverviewModel.dataPassId = parseInt(dataPassId, 10);
117-
this._perDataPassOverviewModel.load();
117+
if (this._perDataPassOverviewModel.pagination._defaultItemsPerPage) {
118+
/**
119+
* If the default items per page is set, it means model has loaded already once,
120+
* so the pagination trigger will not refresh the data.
121+
* Thus, we need to trigger the load here.
122+
*/
123+
this._perDataPassOverviewModel.load();
124+
}
118125
}
119126
}
120127

@@ -135,7 +142,14 @@ export class RunsModel extends Observable {
135142
loadPerSimulationPassOverview({ simulationPassId }) {
136143
if (!this._perSimulationPassOverviewModel.pagination.isInfiniteScrollEnabled) {
137144
this._perSimulationPassOverviewModel.simulationPassId = parseInt(simulationPassId, 10);
138-
this._perSimulationPassOverviewModel.load();
145+
if (this._perSimulationPassOverviewModel.pagination._defaultItemsPerPage) {
146+
/**
147+
* If the default items per page is set, it means model has loaded already once,
148+
* so the pagination trigger will not refresh the data.
149+
* Thus, we need to trigger the load here.
150+
*/
151+
this._perSimulationPassOverviewModel.load();
152+
}
139153
}
140154
}
141155

lib/public/views/Runs/RunsPerSimulationPass/RunsPerSimulationPassOverviewModel.js

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,6 @@ export class RunsPerSimulationPassOverviewModel extends FixedPdpBeamTypeRunsOver
3131

3232
this._detectors$ = rctDetectorsProvider.qc$;
3333

34-
this.registerObervablesQcSummaryDependesOn([this._detectors$]);
35-
this.registerDetectorsNotBadFractionFilterModels(this._detectors$);
36-
this.registerDetectorsForQcFlagsDataExport(this._detectors$);
37-
3834
this._detectors$.bubbleTo(this);
3935
this._simulationPass$.bubbleTo(this);
4036
}
@@ -61,12 +57,16 @@ export class RunsPerSimulationPassOverviewModel extends FixedPdpBeamTypeRunsOver
6157
return;
6258
}
6359

64-
this._fetchSimulationPass().then(() => {
65-
this._simulationPass$.getCurrent().match({
66-
Success: ({ pdpBeamTypes }) => this.setPdpBeamTypes(pdpBeamTypes),
67-
Other: () => null,
68-
});
60+
await this._fetchSimulationPass();
61+
this._simulationPass$.getCurrent().match({
62+
Success: ({ pdpBeamTypes }) => this.setPdpBeamTypes(pdpBeamTypes),
63+
Other: () => null,
6964
});
65+
66+
this.registerDetectorsNotBadFractionFilterModels(this._detectors$);
67+
this.registerDetectorsForQcFlagsDataExport(this._detectors$);
68+
this.registerObservablesQcSummaryDependsOn(this._detectors$);
69+
7070
super.load();
7171
}
7272

0 commit comments

Comments
 (0)