Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/dev' into Add-kafka-messages-con…
Browse files Browse the repository at this point in the history
…sumer-to-the-Framework
  • Loading branch information
martinboulais committed Feb 5, 2025
2 parents 8a11f03 + a8bf2f1 commit d5a14e6
Show file tree
Hide file tree
Showing 146 changed files with 11,024 additions and 10,447 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/control.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ jobs:
- run: (cd Control; npm run coverage )
- run: (cd Control; ./node_modules/.bin/nyc report --reporter=text-lcov > coverage.lcov)
- name: Send codecov report for Control
uses: codecov/codecov-action@v4
uses: codecov/codecov-action@v5
with:
token: ${{ secrets.CODECOV_TOKEN }}
flags: control
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/framework.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ jobs:
- run: (cd Framework; npm run coverage )
- run: (cd Framework; ./node_modules/.bin/nyc report --reporter=text-lcov > coverage.lcov)
- name: Send codecov report for Framework
uses: codecov/codecov-action@v4
uses: codecov/codecov-action@v5
with:
token: ${{ secrets.CODECOV_TOKEN }}
flags: framework
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/infologger.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ jobs:
- run: (cd InfoLogger; npm run coverage )
- run: (cd InfoLogger; ./node_modules/.bin/nyc report --reporter=text-lcov > coverage.lcov)
- name: Send codecov report for InfoLogger
uses: codecov/codecov-action@v4
uses: codecov/codecov-action@v5
with:
token: ${{ secrets.CODECOV_TOKEN }}
flags: infologger
Expand Down
42 changes: 27 additions & 15 deletions .github/workflows/qc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,32 +10,44 @@ on:
- 'dev'

jobs:
lint-check:
name: Check eslint rules on ubuntu-latest
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup node
uses: actions/setup-node@v4
with:
node-version: '20.x'
- run: (cd QualityControl; npm ci )
- run: (cd QualityControl; npm run lint )
test:
name: Tests on ubuntu-latest
name: Tests on ubuntu-latest only if lint-check passes
runs-on: ubuntu-latest
needs: lint-check
steps:
- uses: actions/checkout@v4
- name: Setup node
uses: actions/setup-node@v4
with:
node-version: '20.x'
- run: (cd QualityControl; npm ci )
- run: (cd QualityControl; npm run test )
coverage:
name: Tests and generate lcov reoprt coverage on ubuntu-latest
runs-on: ubuntu-latest
needs: lint-check
steps:
- uses: actions/checkout@v4
- name: Setup node
uses: actions/setup-node@v4
with:
node-version: '20.x'
- run: (cd QualityControl; npm ci )
- run: (cd QualityControl; npm run coverage )
- run: (cd QualityControl; ./node_modules/.bin/nyc report --reporter=text-lcov > coverage.lcov)
- run: (cd QualityControl; npm run coverage-lcov )
- name: Send codecov report for QualityControl
uses: codecov/codecov-action@v4
uses: codecov/codecov-action@v5
with:
token: ${{ secrets.CODECOV_TOKEN }}
flags: qualitycontrol
fail_ci_if_error: true
#coverage: Job is currently disabled due to known issue with node-gyp on GH runners
# name: Tests & coverage on macOS-latest
# runs-on: macOS-latest
# steps:
# - uses: actions/checkout@v4
# - name: Setup node
# uses: actions/setup-node@v4
# with:
# node-version: '20.x'
# - run: (cd QualityControl; npm ci )
# - run: (cd QualityControl; npm run test)
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@ build
tobject2json.node
*/.nyc*
*/test/integration/test-config*
.vscode
.vscode/*
!.vscode/launch.json
.idea
23 changes: 23 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "[ilg] run dev",
"request": "launch",
"runtimeArgs": [
"run-script",
"dev"
],
"localRoot": "${workspaceFolder}/InfoLogger/",
"runtimeExecutable": "npm",
"skipFiles": [
"<node_internals>/**"
],
"outputCapture": "std",
"type": "node",
"windows": {
"localRoot": "${workspaceFolder}\\InfoLogger\\"
}
}
]
}
89 changes: 86 additions & 3 deletions Control/lib/adapters/DcsIntegratedEventAdapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,15 @@
* or submit itself to any jurisdiction.
*/

const {
EcsOperationAndStepStatus: {
DONE_ERROR,
DONE_TIMEOUT
}
} = require('../common/ecsOperationAndStepStatus.enum.js');

/**
* DcsIntegratedEventAdapter - Given an AliECS Integrated Service Event for DCS.SOR, build a DCS Integrated Event
* @class DcsIntegratedEventAdapter - Given an AliECS Integrated Service Event for DCS.SOR, build a DCS Integrated Event
*
* The DCS SOR event is a special event that comes from either:
* * the DCS service itself (when containing the payload "dcsEvent") and it is for one detector only
Expand All @@ -26,7 +33,77 @@ class DcsIntegratedEventAdapter {
}

/**
* Build a DCS Integrated Event from an AliECS Integrated Service Event. If it is a DCSevent, the detector will replace detectors array
* Build a DCS Integrated Event from an AliECS Integrated Service Event - SOR. If it is a DCSevent, the detector will replace detectors array
*
* // IntegratedService event, related to SOR but with a failure on ECS side (such as timeout)
* @example
* {
* "timestamp": 1733497646607,
* "integratedServiceEvent": {
* "name": "readout-dataflow.dcs.sor",
* "error": "DCS SOR timed out after 1s: rpc error: code = DeadlineExceeded desc = Deadline Exceeded",
* "operationName": "dcs.StartOfRun()",
* "operationStatus": "ONGOING",
* "operationStep": "perform DCS call: StartOfRun",
* "operationStepStatus": "DONE_TIMEOUT",
* "environmentId": "2rRm96N9k7E",
* "payload": "{\"detectors\":[\"EMC\"],\"detectorsReadiness\":{\"EMC\":\"SOR_AVAILABLE\"},\"runNumber\":1601}"
* }
* // IntegratedService event with final state DONE_ERROR following the DONE_TIMEOUT from above
* @example
* {
* "timestamp": 1734004912438,
* "integratedServiceEvent": {
* "name": "readout-dataflow.dcs.sor",
* "error": "DCS SOR timed out after 100ms: rpc error: code = DeadlineExceeded desc = context deadline exceeded : SOR failed for EMC, FDD, DCS EOR will run anyway for this run",
* "operationName": "dcs.StartOfRun()",
* "operationStatus": "DONE_ERROR",
* "operationStep": "perform DCS call: StartOfRun",
* "operationStepStatus": "DONE_ERROR",
* "environmentId": "2rYQabnjWy2",
* "payload": "{\"detectors\":[\"EMC\",\"FDD\"],\"detectorsReadiness\":{\"EMC\":\"SOR_AVAILABLE\",\"FDD\":\"SOR_AVAILABLE\"},\"failedDetectors\":[\"EMC\",\"FDD\"],\"runNumber\":1622}"
* }
*
* // IntegratedService event, related to SOR_PROGRESSING with payload from DCS
* @example
* {
* "timestamp": 1734004912360,
* "timestampNano": 1734004912360675322,
* "environmentEvent": null,
* "taskEvent": null,
* "roleEvent": null,
* "callEvent": null,
* "integratedServiceEvent": {
* "name": "readout-dataflow.dcs.sor",
* "error": null,
* "operationName": "dcs.StartOfRun()",
* "operationStatus": "ONGOING",
* "operationStep": "perform DCS call: StartOfRun",
* "operationStepStatus": "ONGOING",
* "environmentId": "2rYQabnjWy2",
* "payload": \"{
* \"dcsEvent\": {
* \"eventtype\":20,
* \"detector\":2,
* \"state\":5,\"
* extraParameters\":{
* \"run_no\":\"1622\"
* },
* \"timestamp\":\"2024-12-12 13:01:52.358\",
* \"message\":\"run_type\"
* },
* \"detector\":\"EMC\",
* \"detectors\":[\"EMC\",\"FDD\"],
* \"detectorsReadiness\":{
* \"EMC\":\"SOR_AVAILABLE\",
* \"FDD\":\"SOR_AVAILABLE\"
* },
* \"runNumber\":1622,
* \"state\":\"SOR_PROGRESSING\"
* }"
* }
*
* Final OperationStates: DONE_TIMEOUT/DONE_ERROR/DONE_OK
* @param {object} event - AliECS Integrated Service Event
* @param {number} timestamp - timestamp of the event (int64 as per proto file definition)
* @return {object} DCS Integrated Event
Expand All @@ -37,7 +114,13 @@ class DcsIntegratedEventAdapter {

const payloadJSON = JSON.parse(payload);
const { dcsEvent, runNumber, detector = null, state } = payloadJSON;
if (!dcsEvent) {

if (!dcsEvent
&& operationStatus !== DONE_ERROR && operationStatus !== DONE_TIMEOUT
&& operationStepStatus !== DONE_ERROR && operationStepStatus !== DONE_TIMEOUT
) {
// if there is no DCS event and status is not final error or timeout, we ignore the event as we expect to have `RUN_OK` from DCS as final state
// or DONE_TIMEOUT or DONE_ERROR from ECS. We are not interested in DONE_OK from ECS as this means all detectors in RUN_OK which we already look for
return null;
}
let { detectors } = payloadJSON;
Expand Down
37 changes: 27 additions & 10 deletions Control/lib/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ const config = require('./config/configProvider.js');

// middleware
const {minimumRoleMiddleware} = require('./middleware/minimumRole.middleware.js');
const {addDetectorIdMiddleware} = require('./middleware/addDetectorId.middleware.js');
const {DetectorId} = require('./common/detectorId.enum.js');
const {lockOwnershipMiddleware} = require('./middleware/lockOwnership.middleware.js');

// controllers
Expand Down Expand Up @@ -117,15 +119,20 @@ module.exports.setup = (http, ws) => {

let aliEcsSynchronizer = undefined;
if (config.kafka && config.kafka?.enable) {
const kafkaClient = new Kafka({
clientId: 'control-gui',
brokers: config.kafka.brokers,
retry: { retries: 3 },
logLevel: logLevel.NOTHING,
});

aliEcsSynchronizer = new AliEcsSynchronizer(kafkaClient, cacheService);
aliEcsSynchronizer.start();
try {
const kafkaClient = new Kafka({
clientId: 'control-gui',
brokers: config.kafka.brokers,
retry: { retries: 3 },
logLevel: logLevel.NOTHING,
});
aliEcsSynchronizer = new AliEcsSynchronizer(kafkaClient, cacheService);
aliEcsSynchronizer.start();

} catch (error) {
logger.errorMessage(`Kafka initialization failed: ${error.message}`);
}

}

const statusService = new StatusService(
Expand Down Expand Up @@ -184,7 +191,17 @@ module.exports.setup = (http, ws) => {

// Lock Service
http.get('/locks', lockController.getLocksStateHandler.bind(lockController));
http.put('/locks/:action/:detectorId', lockController.actionLockHandler.bind(lockController));

http.put(`/locks/:action/${DetectorId.ALL}`,
minimumRoleMiddleware(Role.GLOBAL),
addDetectorIdMiddleware(DetectorId.ALL),
lockController.actionLockHandler.bind(lockController)
);

http.put('/locks/:action/:detectorId',
minimumRoleMiddleware(Role.DETECTOR),
lockController.actionLockHandler.bind(lockController)
);
http.put('/locks/force/:action/:detectorId',
minimumRoleMiddleware(Role.GLOBAL),
lockController.actionForceLockHandler.bind(lockController));
Expand Down
22 changes: 22 additions & 0 deletions Control/lib/common/detectorId.enum.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/**
* @license
* Copyright 2019-2024 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.
*/

/**
* Enum for detector IDs.
*/
const DetectorId = Object.freeze({
ALL: 'ALL',
});

exports.DetectorId = DetectorId;
27 changes: 27 additions & 0 deletions Control/lib/common/ecsOperationAndStepStatus.enum.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/**
* @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.
*/

/**
* Available ECS Statuses of operations for Kafka Events
* These operations can be under the label:
* * operationStatus
* * operationStepStatus
*/
const EcsOperationAndStepStatus = Object.freeze({
DONE_OK: 'DONE_OK',
DONE_ERROR: 'DONE_ERROR',
DONE_TIMEOUT: 'DONE_TIMEOUT',
});

exports.EcsOperationAndStepStatus = EcsOperationAndStepStatus;
2 changes: 1 addition & 1 deletion Control/lib/control-core/GrpcProxy.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
const protoLoader = require('@grpc/proto-loader');
const grpcLibrary = require('@grpc/grpc-js');
const path = require('path');
const {grpcErrorToNativeError} = require('./../errors/grpcErrorToNativeError.js');
const {grpcErrorToNativeError} = require('@aliceo2/web-ui');
const {Status} = require(path.join(__dirname, './../../protobuf/status_pb.js'));
const {EnvironmentInfo} = require(path.join(__dirname, './../../protobuf/environmentinfo_pb.js'));
const logger = (require('@aliceo2/web-ui').LogManager)
Expand Down
Loading

0 comments on commit d5a14e6

Please sign in to comment.