Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 0 additions & 2 deletions lib/domain/entities/GaqDetector.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,4 @@
* @property {number} dataPassId
* @property {number} runNumber
* @property {number} detectorId
* @property {number} createdAt
* @property {number} updatedAt
*/
57 changes: 57 additions & 0 deletions lib/server/api-docs/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -491,3 +491,60 @@ Responses:
```bash
curl -g "$BOOKKEEPING_URL/api/lhcPeriodsStatistics/1?token=$TOKEN"
```

## GAQ detectors

Detectors whose QC flags contribute to the global aggregated quality (GAQ) of a run in a data pass.

### `GET /gaqDetectors` - List the detectors contributing to the GAQ of a run in a data pass

Operation id: `listGaqDetectors`

Returns the detectors whose QC flags contribute to the global aggregated quality (GAQ) of a run in a data pass, sorted by name. Not paginated.
The list is empty when no detector is set for this run and data pass, **or when the run or the data pass does not exist** (never `404`).

| Parameter | In | Type | Required | Notes |
| --- | --- | --- | --- | --- |
| `dataPassId` | query | integer | yes | Data pass identifier. |
| `runNumber` | query | integer | yes | Run number. |

Responses:

- `200`: The detectors.
- `400`: The request failed validation. HTTP status is 400 although each error's `status` field is `"422"`. `source.pointer` has the form `/data/attributes/<query|params|body>/<field>`.

```bash
curl -g "$BOOKKEEPING_URL/api/gaqDetectors?dataPassId=3&runNumber=56&token=$TOKEN"
```

### `POST /gaqDetectors` - Set the detectors contributing to the GAQ of runs in a data pass (not for LLM use)

Operation id: `setGaqDetectors`

Requires the role `admin` or `gaq`. For each given run, replaces the detectors contributing to the GAQ in the data pass by the given ones.
Every run must be linked to the data pass and have every given detector.

**Not meant for LLM or MCP tool use** (`x-llm-exclude`).

**Required role:** `admin`, `gaq`

Request body (JSON):

| Field | Type | Required | Notes |
| --- | --- | --- | --- |
| `dataPassId` | integer | yes | |
| `runNumbers` | array | yes | Run numbers of the runs to update, without duplicates. |
| `detectorIds` | array | yes | Ids of the detectors contributing to the GAQ, without duplicates. |

Responses:

- `201`: The created associations between runs and detectors, one per run and detector.
- `400`: The request failed validation (see the validation errors format), **or** a run is not linked to the data pass, a detector does not exist or a run does not have a given detector. In these last cases the error has `title: Service unavailable` and the reason in `detail`.
- `403`: The token lacks the role required by this operation.
- `404`: The data pass does not exist.

```bash
curl -g -X POST "$BOOKKEEPING_URL/api/gaqDetectors?token=$TOKEN" \
-H 'content-type: application/json' \
-d '{"dataPassId":3,"runNumbers":[49,56],"detectorIds":[4,7]}'
```
90 changes: 90 additions & 0 deletions lib/server/api-docs/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -896,6 +896,96 @@ <h2>LHC periods statistics</h2>
<pre><code class="language-bash">curl -g &quot;$BOOKKEEPING_URL/api/lhcPeriodsStatistics/1?token=$TOKEN&quot;
</code></pre>
</details>
<h2>GAQ detectors</h2>
<p>Detectors whose QC flags contribute to the global aggregated quality (GAQ) of a run in a data pass.</p>
<details>
<summary><h3><span class="method get">GET</span> <code>/gaqDetectors</code> - List the detectors contributing to the GAQ of a run in a data pass</h3></summary>

<p>Operation id: <code>listGaqDetectors</code></p>
<p>Returns the detectors whose QC flags contribute to the global aggregated quality (GAQ) of a run in a data pass, sorted by name. Not paginated.
The list is empty when no detector is set for this run and data pass, <strong>or when the run or the data pass does not exist</strong> (never <code>404</code>).</p>
<table>
<thead>
<tr>
<th>Parameter</th>
<th>In</th>
<th>Type</th>
<th>Required</th>
<th>Notes</th>
</tr>
</thead>
<tbody><tr>
<td><code>dataPassId</code></td>
<td>query</td>
<td>integer</td>
<td>yes</td>
<td>Data pass identifier.</td>
</tr>
<tr>
<td><code>runNumber</code></td>
<td>query</td>
<td>integer</td>
<td>yes</td>
<td>Run number.</td>
</tr>
</tbody></table>
<p>Responses:</p>
<ul>
<li><code>200</code>: The detectors.</li>
<li><code>400</code>: The request failed validation. HTTP status is 400 although each error&#39;s <code>status</code> field is <code>&quot;422&quot;</code>. <code>source.pointer</code> has the form <code>/data/attributes/&lt;query|params|body&gt;/&lt;field&gt;</code>.</li>
</ul>
<pre><code class="language-bash">curl -g &quot;$BOOKKEEPING_URL/api/gaqDetectors?dataPassId=3&amp;runNumber=56&amp;token=$TOKEN&quot;
</code></pre>
</details>
<details>
<summary><h3><span class="method post">POST</span> <code>/gaqDetectors</code> - Set the detectors contributing to the GAQ of runs in a data pass <span class="no-llm" title="Changes data: not meant for LLM or MCP tool use (x-llm-exclude)">not for LLM use</span></h3></summary>

<p>Operation id: <code>setGaqDetectors</code></p>
<p>Requires the role <code>admin</code> or <code>gaq</code>. For each given run, replaces the detectors contributing to the GAQ in the data pass by the given ones.
Every run must be linked to the data pass and have every given detector.</p>
<p><strong>Not meant for LLM or MCP tool use</strong> (<code>x-llm-exclude</code>).</p>
<p><strong>Required role:</strong> <code>admin</code>, <code>gaq</code></p>
<p>Request body (JSON):</p>
<table>
<thead>
<tr>
<th>Field</th>
<th>Type</th>
<th>Required</th>
<th>Notes</th>
</tr>
</thead>
<tbody><tr>
<td><code>dataPassId</code></td>
<td>integer</td>
<td>yes</td>
<td></td>
</tr>
<tr>
<td><code>runNumbers</code></td>
<td>array</td>
<td>yes</td>
<td>Run numbers of the runs to update, without duplicates.</td>
</tr>
<tr>
<td><code>detectorIds</code></td>
<td>array</td>
<td>yes</td>
<td>Ids of the detectors contributing to the GAQ, without duplicates.</td>
</tr>
</tbody></table>
<p>Responses:</p>
<ul>
<li><code>201</code>: The created associations between runs and detectors, one per run and detector.</li>
<li><code>400</code>: The request failed validation (see the validation errors format), <strong>or</strong> a run is not linked to the data pass, a detector does not exist or a run does not have a given detector. In these last cases the error has <code>title: Service unavailable</code> and the reason in <code>detail</code>.</li>
<li><code>403</code>: The token lacks the role required by this operation.</li>
<li><code>404</code>: The data pass does not exist.</li>
</ul>
<pre><code class="language-bash">curl -g -X POST &quot;$BOOKKEEPING_URL/api/gaqDetectors?token=$TOKEN&quot; \
-H &#39;content-type: application/json&#39; \
-d &#39;{&quot;dataPassId&quot;:3,&quot;runNumbers&quot;:[49,56],&quot;detectorIds&quot;:[4,7]}&#39;
</code></pre>
</details>

</main>
<footer>Generated from openapi.yaml by <code>npm run docs:api</code> · ALICE Bookkeeping · internal use only</footer>
Expand Down
109 changes: 109 additions & 0 deletions lib/server/api-docs/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ tags:
description: Monte Carlo simulation productions.
- name: LHC periods statistics
description: LHC periods with statistics on their physics runs.
- name: GAQ detectors
description: Detectors whose QC flags contribute to the global aggregated quality (GAQ) of a run in a data pass.

paths:
/tags:
Expand Down Expand Up @@ -606,6 +608,84 @@ paths:
application/json:
schema: { $ref: '#/components/schemas/ErrorResponse' }

/gaqDetectors:
get:
tags: [GAQ detectors]
operationId: listGaqDetectors
summary: List the detectors contributing to the GAQ of a run in a data pass
description: |
Returns the detectors whose QC flags contribute to the global aggregated quality (GAQ) of a run in a data pass, sorted by name. Not paginated.
The list is empty when no detector is set for this run and data pass, **or when the run or the data pass does not exist** (never `404`).
parameters:
- name: dataPassId
in: query
required: true
description: Data pass identifier.
schema: { type: integer, minimum: 1, examples: [3] }
- name: runNumber
in: query
required: true
description: Run number.
schema: { type: integer, minimum: 1, examples: [56] }
responses:
'200':
description: The detectors.
content:
application/json:
schema: { $ref: '#/components/schemas/DetectorListResponse' }
example:
data:
- { id: 7, name: FT0, type: PHYSICAL }
- { id: 4, name: ITS, type: PHYSICAL }
'400': { $ref: '#/components/responses/ValidationError' }
post:
tags: [GAQ detectors]
operationId: setGaqDetectors
x-llm-exclude: true
x-required-roles: [admin, gaq]
summary: Set the detectors contributing to the GAQ of runs in a data pass
description: |
Requires the role `admin` or `gaq`. For each given run, replaces the detectors contributing to the GAQ in the data pass by the given ones.
Every run must be linked to the data pass and have every given detector.
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/SetGaqDetectors' }
example:
dataPassId: 3
runNumbers: [49, 56]
detectorIds: [4, 7]
responses:
'201':
description: The created associations between runs and detectors, one per run and detector.
content:
application/json:
schema: { $ref: '#/components/schemas/GaqDetectorEntriesResponse' }
example:
data:
- { dataPassId: 3, runNumber: 49, detectorId: 4 }
- { dataPassId: 3, runNumber: 49, detectorId: 7 }
'400':
description: |
The request failed validation (see the validation errors format), **or** a run is not linked to the data pass, a detector does not exist or
a run does not have a given detector. In these last cases the error has `title: Service unavailable` and the reason in `detail`.
content:
application/json:
schema: { $ref: '#/components/schemas/ErrorResponse' }
example:
errors:
- { status: 400, title: Service unavailable, detail: 'No association between data pass with id 3 and following runs: 1' }
'403': { $ref: '#/components/responses/Forbidden' }
'404':
description: The data pass does not exist.
content:
application/json:
schema: { $ref: '#/components/schemas/ErrorResponse' }
example:
errors:
- { status: 404, title: Not found, detail: Data pass with this id (99999) could not be found }

components:
securitySchemes:
jwtQuery:
Expand Down Expand Up @@ -936,3 +1016,32 @@ components:
type: array
items: { $ref: '#/components/schemas/LhcPeriodStatistics' }
meta: { $ref: '#/components/schemas/PageMeta' }
SetGaqDetectors:
type: object
required: [dataPassId, runNumbers, detectorIds]
properties:
dataPassId: { type: integer, minimum: 1 }
runNumbers:
type: array
description: Run numbers of the runs to update, without duplicates.
uniqueItems: true
items: { type: integer, minimum: 1 }
detectorIds:
type: array
description: Ids of the detectors contributing to the GAQ, without duplicates.
uniqueItems: true
items: { type: integer, minimum: 1 }
GaqDetectorEntry:
type: object
required: [dataPassId, runNumber, detectorId]
properties:
dataPassId: { type: integer }
runNumber: { type: integer }
detectorId: { type: integer }
GaqDetectorEntriesResponse:
type: object
required: [data]
properties:
data:
type: array
items: { $ref: '#/components/schemas/GaqDetectorEntry' }
11 changes: 6 additions & 5 deletions lib/server/controllers/gaqDetectors.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

const Joi = require('joi');
const { DtoFactory } = require('../../domain/dtos/DtoFactory.js');
const EntityIdDto = require('../../domain/dtos/EntityIdDto.js');
const { dtoValidator } = require('../utilities/dtoValidator.js');
const { updateExpressResponseFromNativeError } = require('../express/updateExpressResponseFromNativeError.js');
const { gaqDetectorService } = require('../services/gaq/GaqDetectorsService.js');
Expand All @@ -26,9 +27,9 @@ const { gaqDetectorService } = require('../services/gaq/GaqDetectorsService.js')
const setGaqDetectorsHandler = async (req, res) => {
const validatedDTO = await dtoValidator(
DtoFactory.bodyOnly(Joi.object({
dataPassId: Joi.number(),
runNumbers: Joi.array().items(Joi.number()).unique(),
detectorIds: Joi.array().items(Joi.number()).unique(),
dataPassId: EntityIdDto.required(),
runNumbers: Joi.array().items(EntityIdDto).unique().required(),
detectorIds: Joi.array().items(EntityIdDto).unique().required(),
})),
req,
res,
Expand Down Expand Up @@ -63,8 +64,8 @@ const setGaqDetectorsHandler = async (req, res) => {
const listGaqDetectorsHandler = async (req, res) => {
const validatedDTO = await dtoValidator(
DtoFactory.queryOnly(Joi.object({
dataPassId: Joi.number().required(),
runNumber: Joi.number().required(),
dataPassId: EntityIdDto.required(),
runNumber: EntityIdDto.required(),
})),
req,
res,
Expand Down
Loading
Loading