Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
bb5a9c3
[O2B-1545] Add GAQ summary models, adapters and migration
isaachilly Mar 5, 2026
4fade0f
[O2B-1545] Add GAQ summary repositories and timestamps
isaachilly Mar 16, 2026
15afdaa
[O2B-1545] Use default Sequelize createdAt/updatedAt instead of compu…
isaachilly Mar 17, 2026
363f09b
[O2B-1545] Use mcReproducibleCoverage float instead of boolean
isaachilly Mar 17, 2026
002f301
[O2B-1545] Remove mcReproducible field
isaachilly Mar 17, 2026
5bebbb5
[O2B-1563] Invalidate GAQ summaries on related changes
isaachilly Mar 17, 2026
16d3563
[O2B-1545] Rename GAQ summary coverage fields
isaachilly Mar 18, 2026
9bf8027
Merge branch 'feature/O2B-1545/Create-GAQ-Summary-Tables' into featur…
isaachilly Mar 18, 2026
170c1b3
[O2B-1563] Add GAQ summary invalidation trigger tests
isaachilly Mar 31, 2026
78a2181
[O2B-1563] Use dataPass.id in GAQ invalidation TYPO
isaachilly Mar 31, 2026
c2ccbd4
Add calculationFailed to GAQ summaries
isaachilly Apr 17, 2026
1e78cac
Merge branch 'feature/O2B-1545/Create-GAQ-Summary-Tables' into featur…
isaachilly Apr 17, 2026
35112e5
[O2B-1545] Make GAQ summary columns nullable
isaachilly Apr 17, 2026
c81cdf6
Merge branch 'feature/O2B-1545/Create-GAQ-Summary-Tables' into featur…
isaachilly Apr 17, 2026
5059082
[O2B-1545] Add invalidatedAt to gaq_summaries, remove invalidation table
isaachilly May 4, 2026
9893667
[O2B-1545] Rename calculationFailed to notComputable
isaachilly May 4, 2026
1588cd0
Merge branch 'feature/O2B-1545/Create-GAQ-Summary-Tables' into featur…
isaachilly May 4, 2026
47449a7
[O2B-1545] Remove unused GaqSummaryInvalidation files and imports
isaachilly May 4, 2026
6ed0538
Merge branch 'feature/O2B-1545/Create-GAQ-Summary-Tables' into featur…
isaachilly May 4, 2026
0b8b161
[O2B-1563] Use GaqSummaryRepository invalidation
isaachilly May 4, 2026
772a96c
[O2B-1545] Add index on gaq_summaries.invalidated_at
isaachilly May 5, 2026
4ecce8f
Merge branch 'feature/O2B-1545/Create-GAQ-Summary-Tables' into featur…
isaachilly May 5, 2026
92e3c54
[O2B-1563] Stealth fix: We do not need to soft delete flags that are …
isaachilly May 5, 2026
f5f686c
[O2B-1545] Add a composite primary key on GAQSummary table
isaachilly Jun 18, 2026
3c7bce3
Merge branch 'feature/O2B-1545/Create-GAQ-Summary-Tables' into featur…
isaachilly Jun 18, 2026
9c1116b
[O2B-1563] Centralise GAQ summary invalidation and skip redundant work
isaachilly Jun 18, 2026
ce0ac8c
Merge branch 'main' into feature/O2B-1563/Create-GAQ-summary-invalida…
isaachilly Jun 19, 2026
23f6e04
Revert "Merge branch 'main' into feature/O2B-1563/Create-GAQ-summary-…
isaachilly Jun 19, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .github/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
* @graduta
* @isaachilly
8 changes: 2 additions & 6 deletions .github/workflows/bookkeeping.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,6 @@ on:
branches:
- main

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
parallel_tests:
name: ${{ matrix.test_type }}
Expand Down Expand Up @@ -43,7 +39,7 @@ jobs:
steps:
- uses: actions/checkout@v6
- name: Set up Docker
uses: docker/setup-buildx-action@v4
uses: docker/setup-buildx-action@v3
- name: Create Coverage Directory
run: mkdir -p ${{ github.workspace }}/coverage

Expand Down Expand Up @@ -75,7 +71,7 @@ jobs:
env:
TEST_TYPE: ${{ matrix.test_type }}
- name: Upload Coverage to Codecov
uses: codecov/codecov-action@v6
uses: codecov/codecov-action@v5
with:
files: ./coverage/lcov.info
env:
Expand Down
4 changes: 0 additions & 4 deletions .github/workflows/docker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,6 @@ on:
permissions:
contents: read

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
linter:
runs-on: ubuntu-latest
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ RUN apk add --no-cache \
freetype=2.13.2-r0 \
freetype-dev=2.13.2-r0 \
harfbuzz=8.5.0-r0 \
ca-certificates=20260413-r0
ca-certificates=20250911-r0

# Tell Puppeteer to skip installing Chrome. We'll be using the installed package.
ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true
Expand Down
62 changes: 62 additions & 0 deletions lib/database/adapters/GaqSummaryAdapter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/**
* @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.
*/

/**
* GaqSummaryAdapter
*/
class GaqSummaryAdapter {
/**
* Constructor
*/
constructor() {
this.toEntity = this.toEntity.bind(this);
}

/**
* Converts the given database object to an entity object.
*
* @param {SequelizeGaqSummary} databaseObject Object to convert.
* @returns {GaqSummary} Converted entity object.
*/
toEntity(databaseObject) {
const {
dataPassId,
runNumber,
badRunCoverage,
explicitlyNotBadRunCoverage,
mcReproducibleCoverage,
missingVerificationsCount,
undefinedQualityPeriodsCount,
notComputable,
invalidatedAt,
createdAt,
updatedAt,
} = databaseObject;

return {
dataPassId,
runNumber,
badRunCoverage,
explicitlyNotBadRunCoverage,
mcReproducibleCoverage,
missingVerificationsCount,
undefinedQualityPeriodsCount,
notComputable,
invalidatedAt,
createdAt,
updatedAt,
};
}
}

module.exports = { GaqSummaryAdapter };
3 changes: 3 additions & 0 deletions lib/database/adapters/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ const EorReasonAdapter = require('./EorReasonAdapter');
const FlpRoleAdapter = require('./FlpRoleAdapter');
const { HostAdapter } = require('./HostAdapter.js');
const { GaqDetectorAdapter } = require('./GaqDetectorAdapter.js');
const { GaqSummaryAdapter } = require('./GaqSummaryAdapter.js');
const { LhcFillAdapter } = require('./LhcFillAdapter.js');
const { LhcFillStatisticsAdapter } = require('./LhcFillStatisticsAdapter.js');
const LhcPeriodAdapter = require('./LhcPeriodAdapter');
Expand Down Expand Up @@ -63,6 +64,7 @@ const environmentHistoryItemAdapter = new EnvironmentHistoryItemAdapter();
const eorReasonAdapter = new EorReasonAdapter();
const flpRoleAdapter = new FlpRoleAdapter();
const gaqDetectorAdapter = new GaqDetectorAdapter();
const gaqSummaryAdapter = new GaqSummaryAdapter();
const hostAdapter = new HostAdapter();
const lhcFillAdapter = new LhcFillAdapter();
const lhcFillStatisticsAdapter = new LhcFillStatisticsAdapter();
Expand Down Expand Up @@ -159,6 +161,7 @@ module.exports = {
eorReasonAdapter,
flpRoleAdapter,
gaqDetectorAdapter,
gaqSummaryAdapter,
hostAdapter,
lhcFillAdapter,
lhcFillStatisticsAdapter,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
'use strict';

/** @type {import('sequelize-cli').Migration} */
module.exports = {
up: async (queryInterface, Sequelize) => queryInterface.sequelize.transaction(async (transaction) => {
await queryInterface.createTable('gaq_summaries', {
data_pass_id: {
type: Sequelize.INTEGER,
primaryKey: true,
allowNull: false,
references: {
model: 'data_passes',
key: 'id',
},
},
run_number: {
type: Sequelize.INTEGER,
primaryKey: true,
allowNull: false,
references: {
model: 'runs',
key: 'run_number',
},
},
bad_run_coverage: {
type: Sequelize.FLOAT,
},
explicitly_not_bad_run_coverage: {
type: Sequelize.FLOAT,
},
mc_reproducible_coverage: {
type: Sequelize.FLOAT,
},
missing_verifications_count: {
type: Sequelize.INTEGER,
},
undefined_quality_periods_count: {
type: Sequelize.INTEGER,
},
not_computable: {
type: Sequelize.BOOLEAN,
allowNull: false,
defaultValue: false,
},
invalidated_at: {
type: Sequelize.DATE(3),
allowNull: true,
defaultValue: null,
},
created_at: {
type: Sequelize.DATE(3),
allowNull: false,
defaultValue: Sequelize.literal('CURRENT_TIMESTAMP(3)'),
},
updated_at: {
type: Sequelize.DATE(3),
allowNull: false,
defaultValue: Sequelize.literal('CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)'),
},
}, { transaction });

await queryInterface.addIndex('gaq_summaries', {
name: 'gaq_summaries_invalidated_at_idx',
fields: ['invalidated_at'],
}, { transaction });
}),

down: async (queryInterface) => queryInterface.sequelize.transaction(async (transaction) => {
await queryInterface.dropTable('gaq_summaries', { transaction });
}),
};

This file was deleted.

59 changes: 59 additions & 0 deletions lib/database/models/gaqSummary.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/**
* @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.
*/

module.exports = (sequelize) => {
const Sequelize = require('sequelize');

const GaqSummary = sequelize.define('GaqSummary', {
dataPassId: {
type: Sequelize.INTEGER,
primaryKey: true,
},
runNumber: {
type: Sequelize.INTEGER,
primaryKey: true,
},
badRunCoverage: {
type: Sequelize.FLOAT,
},
explicitlyNotBadRunCoverage: {
type: Sequelize.FLOAT,
},
mcReproducibleCoverage: {
type: Sequelize.FLOAT,
},
missingVerificationsCount: {
type: Sequelize.INTEGER,
},
undefinedQualityPeriodsCount: {
type: Sequelize.INTEGER,
},
notComputable: {
type: Sequelize.BOOLEAN,
allowNull: false,
defaultValue: false,
},
invalidatedAt: {
type: Sequelize.DATE(3),
},
}, { tableName: 'gaq_summaries' });

GaqSummary.removeAttribute('id');

GaqSummary.associate = (models) => {
GaqSummary.belongsTo(models.Run, { foreignKey: 'runNumber', as: 'run' });
GaqSummary.belongsTo(models.DataPass, { foreignKey: 'dataPassId', as: 'dataPass' });
};

return GaqSummary;
};
2 changes: 2 additions & 0 deletions lib/database/models/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ const EorReason = require('./eorreason');
const EpnRoleSession = require('./epnrolesession');
const FlpRole = require('./flprole');
const GaqDetector = require('./gaqDetector.js');
const GaqSummary = require('./gaqSummary.js');
const Host = require('./host.js');
const LhcFill = require('./lhcFill');
const LhcFillStatistics = require('./lhcFillStatistics.js');
Expand Down Expand Up @@ -66,6 +67,7 @@ module.exports = (sequelize) => {
EpnRoleSessionkey: EpnRoleSession(sequelize),
FlpRole: FlpRole(sequelize),
GaqDetector: GaqDetector(sequelize),
GaqSummary: GaqSummary(sequelize),
Host: Host(sequelize),
LhcFill: LhcFill(sequelize),
LhcFillStatistics: LhcFillStatistics(sequelize),
Expand Down
55 changes: 55 additions & 0 deletions lib/database/repositories/GaqSummaryRepository.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/**
* @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.
*/

const {
models: {
GaqSummary,
},
} = require('..');
const Repository = require('./Repository');

/**
* GaqSummary repository
*/
class GaqSummaryRepository extends Repository {
/**
* Creates a new `GaqSummaryRepository` instance.
*/
constructor() {
super(GaqSummary);
}

/**
* Mark the summary for a given (dataPassId, runNumber) as invalidated, creating the row if it does not yet exist
*
* @param {number} dataPassId data pass id
* @param {number} runNumber run number
* @return {Promise<void>} resolves once the summary is invalidated
*/
async invalidate(dataPassId, runNumber) {
await this.upsert({ dataPassId, runNumber, invalidatedAt: new Date() });
}

/**
* Mark a list of summaries as invalidated in parallel
*
* @param {{ dataPassId: number, runNumber: number }[]} pairs the (dataPassId, runNumber) pairs to invalidate
* @return {Promise<void>} resolves once all summaries are invalidated
*/
async invalidateMany(pairs) {
const invalidatedAt = new Date();
await Promise.all(pairs.map(({ dataPassId, runNumber }) => this.upsert({ dataPassId, runNumber, invalidatedAt })));
}
}

module.exports = new GaqSummaryRepository();
2 changes: 2 additions & 0 deletions lib/database/repositories/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ const EnvironmentRepository = require('./EnvironmentRepository');
const EorReasonRepository = require('./EorReasonRepository');
const FlpRoleRepository = require('./FlpRoleRepository');
const GaqDetectorRepository = require('./GaqDetectorRepository.js');
const GaqSummaryRepository = require('./GaqSummaryRepository.js');
const HostRepository = require('./HostRepository.js');
const LhcFillRepository = require('./LhcFillRepository');
const LhcFillStatisticsRepository = require('./LhcFillStatisticsRepository.js');
Expand Down Expand Up @@ -70,6 +71,7 @@ module.exports = {
EorReasonRepository,
FlpRoleRepository,
GaqDetectorRepository,
GaqSummaryRepository,
HostRepository,
LhcFillRepository,
LhcFillStatisticsRepository,
Expand Down
Loading
Loading