Skip to content
18 changes: 18 additions & 0 deletions QualityControl/common/library/typedef/DataPass.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/**
* @license
* Copyright CERN and copyright holders of ALICE O2. This software is
* distributed under the terms of the GNU General Public License v3 (GPL
* Version 3), copied verbatim in the file "COPYING".
*
* See http://alice-o2.web.cern.ch/license for full licensing information.
*
* In applying this license CERN does not waive the privileges and immunities
* granted to it by virtue of its status as an Intergovernmental Organization
* or submit itself to any jurisdiction.
*/

/**
* @typedef {object} DataPass
* @property {string} name - Human-readable data pass name.
* @property {boolean} isFrozen - Whether the data pass is frozen.
*/
18 changes: 18 additions & 0 deletions QualityControl/common/library/typedef/DetectorSummary.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/**
* @license
* Copyright CERN and copyright holders of ALICE O2. This software is
* distributed under the terms of the GNU General Public License v3 (GPL
* Version 3), copied verbatim in the file "COPYING".
*
* See http://alice-o2.web.cern.ch/license for full licensing information.
*
* In applying this license CERN does not waive the privileges and immunities
* granted to it by virtue of its status as an Intergovernmental Organization
* or submit itself to any jurisdiction.
*/

/**
* @typedef {object} DetectorSummary
* @property {string} name - Human-readable detector name.
* @property {string} type - Detector type identifier.
*/
7 changes: 7 additions & 0 deletions QualityControl/lib/QCModel.js
Original file line number Diff line number Diff line change
Expand Up @@ -171,4 +171,11 @@ function initializeIntervals(intervalsService, qcObjectService, filterService, r
runModeService.refreshInterval,
);
}

if (filterService.dataPassesRefreshInterval > 0) {
intervalsService.register(
filterService.getDataPasses.bind(runModeService),
filterService.dataPassesRefreshInterval,
);
}
}
9 changes: 5 additions & 4 deletions QualityControl/lib/controllers/FilterController.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,12 +63,13 @@ export class FilterController {
*/
async getFilterConfigurationHandler(req, res) {
try {
let runTypes = [];
if (this._filterService) {
runTypes = await this._filterService.runTypes;
}
const runTypes = this._filterService?.runTypes ?? [];
const detectors = this._filterService?.detectors ?? [];
const dataPasses = this._filterService?.dataPasses ?? [];
res.status(200).json({
runTypes,
detectors,
dataPasses,
});
} catch (error) {
res.status(503).json({ error: error.message || error });
Expand Down
2 changes: 2 additions & 0 deletions QualityControl/lib/dtos/ObjectGetDto.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

import Joi from 'joi';
import { RunNumberDto } from './filters/RunNumberDto.js';
import { QcDetectorNameDto } from './filters/QcDetectorNameDto.js';

const periodNamePattern = /^LHC\d{1,2}[a-z0-9]+$/i;

Expand All @@ -25,6 +26,7 @@ const periodNamePattern = /^LHC\d{1,2}[a-z0-9]+$/i;
function createFiltersSchema(runTypes) {
return Joi.object({
RunNumber: RunNumberDto.optional(),
QcDetectorName: QcDetectorNameDto.optional(),
RunType: runTypes.length > 0
? Joi.string().valid(...runTypes).optional()
: Joi.string().optional(),
Expand Down
22 changes: 22 additions & 0 deletions QualityControl/lib/dtos/filters/QcDetectorNameDto.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/**
* @license
* Copyright 2019-2020 CERN and copyright holders of ALICE O2.
* See http://alice-o2.web.cern.ch/copyright for details of the copyright holders.
* All rights not expressly granted are reserved.
*
* This software is distributed under the terms of the GNU General Public
* License v3 (GPL Version 3), copied verbatim in the file "COPYING".
*
* In applying this license CERN does not waive the privileges and immunities
* granted to it by virtue of its status as an Intergovernmental Organization
* or submit itself to any jurisdiction.
*/

import Joi from 'joi';

export const QcDetectorNameDto = Joi.string()
.min(1)
.messages({
'number.base': 'Detector name must be a string',
'number.min': 'Detector name must not be an empty string',
});
36 changes: 36 additions & 0 deletions QualityControl/lib/services/BookkeepingService.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ import { wrapRunStatus } from '../dtos/BookkeepingDto.js';
const GET_BKP_DATABASE_STATUS_PATH = '/api/status/database';
const GET_RUN_TYPES_PATH = '/api/runTypes';
const GET_RUN_PATH = '/api/runs';
const GET_DETECTORS_PATH = '/api/detectors';
const GET_DATA_PASSES_PATH = '/api/dataPasses';

const LOG_FACILITY = `${process.env.npm_config_log_label ?? 'qcg'}/bkp-service`;

Expand Down Expand Up @@ -127,6 +129,23 @@ export class BookkeepingService {
return data;
}

/**
* Retrieve the list of data passes from the bookkeeping service.
* @returns {Promise<object[]>} Resolves with an array of data passes.
*/
async retrieveDataPasses() {
const { data } = await httpGetJson(
this._hostname,
this._port,
this._createPath(GET_DATA_PASSES_PATH),
{
protocol: this._protocol,
rejectUnauthorized: false,
},
);
return Array.isArray(data) ? data : [];
}

/**
* Retrieves the information of a specific run from the Bookkeeping service
* @param {number} runNumber - The run number to check the status for
Expand Down Expand Up @@ -181,6 +200,23 @@ export class BookkeepingService {
}
}

/**
* Retrieves the information about the detectors from the Bookkeeping service.
* @returns {Promise<object[]>} Array of detector summaries.
*/
async retrieveDetectorSummaries() {
const { data } = await httpGetJson(
this._hostname,
this._port,
this._createPath(GET_DETECTORS_PATH),
{
protocol: this._protocol,
rejectUnauthorized: false,
},
);
return Array.isArray(data) ? data : [];
}

/**
* Helper method to construct a URL path with the required authentication token.
* Appends the service's token as a query parameter to the provided path.
Expand Down
67 changes: 65 additions & 2 deletions QualityControl/lib/services/FilterService.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,13 @@
this._logger = LogManager.getLogger(LOG_FACILITY);
this._bookkeepingService = bookkeepingService;
this._runTypes = [];
this.initFilters();
this._detectors = Object.freeze([]);
this._dataPasses = Object.freeze([]);

this._runTypesRefreshInterval = config?.bookkeeping?.runTypesRefreshInterval ??
(config?.bookkeeping ? 24 * 60 * 60 * 1000 : -1);
(config?.bookkeeping ? 24 * 60 * 60 * 1000 : -1);// default interval is 1 day
this._dataPassesRefreshInterval = config?.bookkeeping?.dataPassesRefreshInterval ??
(config?.bookkeeping ? 60 * 60 * 1000 : -1);// default interval is 1 hour

this.initFilters().catch((error) => {
this._logger.errorMessage(`FilterService initialization failed: ${error.message || error}`);
Expand All @@ -48,6 +51,8 @@
async initFilters() {
await this._bookkeepingService.connect();
await this.getRunTypes();
await this._initializeDetectors();
await this.getDataPasses();
}

/**
Expand All @@ -71,6 +76,56 @@
}
}

/**
* This method is used to retrieve the list of data passes from the bookkeeping service.
* @returns {Promise<void>} Resolves when the list of data passes is available.
*/
async getDataPasses() {
try {
if (!this._bookkeepingService.active) {
return;
}

const rawDataPasses = await this._bookkeepingService.retrieveDataPasses();
this._dataPasses = Object.freeze(rawDataPasses.map(({ name, isFrozen }) => Object.freeze({ name, isFrozen })));
} catch (error) {
this._logger.errorMessage(`Error while retrieving data passes: ${error.message || error}`);
}
}

/**
* Returns a list of data passes.
* @returns {Readonly<DataPass[]>} An immutable array of data passes.
*/
get dataPasses() {
return this._dataPasses;
}

/**
* This method is used to retrieve the list of detectors from the bookkeeping service
* @returns {Promise<undefined>} Resolves when the list of detectors is available
*/
async _initializeDetectors() {
try {
if (!this._bookkeepingService.active) {
return;
}

Check failure on line 113 in QualityControl/lib/services/FilterService.js

View workflow job for this annotation

GitHub Actions / Check eslint rules on ubuntu-latest

Trailing spaces not allowed
const detectorSummaries = await this._bookkeepingService.retrieveDetectorSummaries();
this._detectors = Object.freeze(detectorSummaries.map(({ name, type }) => Object.freeze({ name, type })));
} catch (error) {
this._logger.errorMessage(`Failed to retrieve detectors: ${error?.message || error}`);
}
}

/**
* Returns a list of detector summaries.
* @returns {Readonly<DetectorSummary[]>} An immutable array of detector summaries.
*/
get detectors() {
return this._detectors;
}

/**
* Returns the interval in milliseconds for how often the list of run types should be refreshed.
* @returns {number} Interval in milliseconds for refreshing the list of run types.
Expand All @@ -79,6 +134,14 @@
return this._runTypesRefreshInterval;
}

/**
* Returns the interval in milliseconds for how often the list of data passes should be refreshed.
* @returns {number} Interval in milliseconds for refreshing the list of data passes.
*/
get dataPassesRefreshInterval() {
return this._dataPassesRefreshInterval;
}

/**
* This method is used to initialize the filter service
* @returns {string[]} - resolves when the filter service is initialized
Expand Down
Loading
Loading