Skip to content

Commit

Permalink
fix: manual start endpoint scan
Browse files Browse the repository at this point in the history
  • Loading branch information
ralfaron committed Nov 10, 2024
1 parent 979a070 commit c1dab60
Show file tree
Hide file tree
Showing 16 changed files with 178 additions and 83 deletions.
2 changes: 1 addition & 1 deletion projects/aas-lib/src/lib/aas-table/aas-table-row.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export class AASTableRow extends TreeNode<AASDocument> {
}

public get thumbnail(): string {
return this.element.thumbnail ?? '/assets/resources/aas.32.png';
return this.element.thumbnail || '/assets/resources/aas.32.png';
}

public get endpoint(): string {
Expand Down
10 changes: 5 additions & 5 deletions projects/aas-lib/src/lib/aas-table/aas-table.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
@switch (row.state) {
@case ('unloaded') {
<div class="position-relative">
<img class="img-fluid opacity-50" width="40" height="40" [src]="row.thumbnail" alt="" />
<img class="img-fluid opacity-50" width="40" height="40" [src]="row.thumbnail" [alt]="row.name" />
<div
class="position-absolute top-50 start-50 translate-middle p-2 bg-transparent rounded-circle text-info">
<i class="bi bi-cloud-arrow-down"></i>
Expand All @@ -46,7 +46,7 @@
}
@case ('unavailable') {
<div class="position-relative">
<img class="img-fluid opacity-50" width="40" height="40" [src]="row.thumbnail" alt="" />
<img class="img-fluid opacity-50" width="40" height="40" [src]="row.thumbnail" [alt]="row.name" />
<div
class="position-absolute top-50 start-50 translate-middle p-2 bg-transparent rounded-circle text-danger">
<i class="bi bi-cone-striped"></i>
Expand All @@ -55,7 +55,7 @@
}
@default {
<div>
<img class="img-fluid" width="40" height="40" [src]="row.thumbnail" alt="" />
<img class="img-fluid" width="40" height="40" [src]="row.thumbnail" [alt]="row.name" />
</div>
}
}
Expand All @@ -77,8 +77,8 @@
<thead>
<tr>
<th class="th-w-checkbox">
<input type="checkbox" class="form-check-input" [indeterminate]="someSelected()" [checked]="everySelected()"
(change)="toggleSelections()">
<input type="checkbox" class="form-check-input" [indeterminate]="someSelected()"
[checked]="everySelected()" (change)="toggleSelections()">
</th>
<th scope="col">
<div class="text-center" translate>COLUMN_NAME</div>
Expand Down
44 changes: 22 additions & 22 deletions projects/aas-server/src/app/aas-index/mysql/mysql-index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,12 @@ export class MySqlIndex extends AASIndex {
name: row.name,
url: row.url,
type: row.type,
version: row.version,
};

if (row.version) {
endpoint.version = row.version;
}

if (row.headers) {
endpoint.headers = JSON.parse(row.headers);
}
Expand Down Expand Up @@ -270,17 +273,8 @@ export class MySqlIndex extends AASIndex {

const uuid = result[0][0].uuid;
await connection.query<ResultSetHeader>(
'UPDATE `documents` SET address = ?, crc32 = ?, idShort = ?, onlineReady = ?, readonly = ?, timestamp = ?, thumbnail = ? WHERE uuid = ?;',
[
document.address,
document.crc32,
document.idShort,
!!document.onlineReady,
document.readonly,
document.timestamp,
document.thumbnail,
uuid,
],
'UPDATE `documents` SET address = ?, crc32 = ?, idShort = ?, timestamp = ?, thumbnail = ? WHERE uuid = ?;',
[document.address, document.crc32, document.idShort, document.timestamp, document.thumbnail, uuid],
);

if (document.content) {
Expand All @@ -301,18 +295,16 @@ export class MySqlIndex extends AASIndex {
await connection.beginTransaction();
const uuid = v4();
await connection.query<ResultSetHeader>(
'INSERT INTO `documents` (uuid, address, crc32, endpoint, id, idShort, assetId, onlineReady, readonly, thumbnail, timestamp) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);',
'INSERT INTO `documents` (uuid, address, crc32, endpoint, id, idShort, assetId, thumbnail, timestamp) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);',
[
uuid,
document.address,
document.crc32,
document.endpoint,
document.id,
document.idShort,
document.assetId,
!!document.onlineReady,
document.readonly,
document.thumbnail ?? '',
document.assetId || null,
document.thumbnail || null,
BigInt(document.timestamp),
],
);
Expand Down Expand Up @@ -582,19 +574,27 @@ export class MySqlIndex extends AASIndex {
}

private toDocument(result: MySqlDocument): AASDocument {
return {
const document: AASDocument = {
address: result.address,
crc32: result.crc32,
endpoint: result.endpoint,
id: result.id,
idShort: result.idShort,
assetId: result.assetId,
readonly: result.readonly ? true : false,
timestamp: Number(result.timestamp),
content: null,
onlineReady: result.onlineReady ? true : false,
thumbnail: result.thumbnail,
onlineReady: true,
readonly: true,
};

if (result.assetId) {
document.assetId = result.assetId;
}

if (result.thumbnail) {
document.thumbnail = result.thumbnail;
}

return document;
}

private async initialize(): Promise<Connection> {
Expand Down
16 changes: 11 additions & 5 deletions projects/aas-server/src/app/aas-index/mysql/mysql-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,25 @@
*****************************************************************************/

import { RowDataPacket } from 'mysql2/promise';
import { AASDocument, AASEndpointType } from 'aas-core';
import { AASEndpointType } from 'aas-core';

export interface MySqlEndpoint extends RowDataPacket {
name: string;
url: string;
type: AASEndpointType;
version?: string;
headers?: string;
schedule?: string;
version: string | null;
headers: string | null;
schedule: string | null;
}

export interface MySqlDocument extends AASDocument, RowDataPacket {
export interface MySqlDocument extends RowDataPacket {
uuid: string;
address: string;
crc32: number;
idShort: string;
assetId: string | null;
thumbnail: string | null;
timestamp: number;
}

export interface MySqlElement extends RowDataPacket {
Expand Down
57 changes: 43 additions & 14 deletions projects/aas-server/src/app/aas-provider/aas-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ import { AASResourceFactory } from '../packages/aas-resource-factory.js';
import { Variable } from '../variable.js';
import { WSServer } from '../ws-server.js';
import { ERRORS } from '../errors.js';
import { TaskHandler } from './task-handler.js';
import { Task, TaskHandler } from './task-handler.js';
import { HierarchicalStructure } from './hierarchical-structure.js';
import { AASCache } from './aas-cache.js';

Expand Down Expand Up @@ -237,7 +237,8 @@ export class AASProvider {
} as AASServerMessage,
});

setTimeout(this.scanEndpoint, 0, this.taskHandler.createTaskId(), endpoint);
const task = this.taskHandler.createTask(endpointName, this, 'ScanEndpoint');
setTimeout(this.scanEndpoint, 0, task, endpoint);
}

/**
Expand All @@ -261,6 +262,11 @@ export class AASProvider {
const endpoint = await this.index.getEndpoint(endpointName);
if (endpoint) {
await this.index.removeEndpoint(endpoint.name);
const task = this.taskHandler.find(endpointName, 'ScanEndpoint');
if (task) {
this.taskHandler.delete(task.id);
}

this.logger.info(`Endpoint ${endpoint.name} (${endpoint.url}) removed.`);
this.wsServer.notify('IndexChange', {
type: 'AASServerMessage',
Expand Down Expand Up @@ -429,6 +435,27 @@ export class AASProvider {
return nodes;
}

/** Starts a scan of the AAS endpoint with the specified name.
* @param name The name of the endpoint.
*/
public async startEndpointScan(name: string): Promise<void> {
const endpoint = await this.index.getEndpoint(name);
const task = this.taskHandler.find(name, 'ScanEndpoint');
if (task === undefined) {
throw new Error(``);
}

if (endpoint.schedule?.type !== 'manual') {
throw new Error(`Endpoint ${name} is not configured for the manual start of a scan.`);
}

if (task.state === 'inProgress') {
throw new Error(`Scanning endpoint ${name} is already in progress.`);
}

setTimeout(this.scanEndpoint, 0, task, endpoint);
}

private async restart(): Promise<void> {
this.resetRequested = false;
await this.index.reset();
Expand Down Expand Up @@ -482,14 +509,16 @@ export class AASProvider {
continue;
}

setTimeout(this.scanEndpoint, 0, this.taskHandler.createTaskId(), endpoint);
const task = this.taskHandler.createTask(endpoint.name, this, 'ScanEndpoint');
this.taskHandler.set(task);
setTimeout(this.scanEndpoint, 0, task, endpoint);
}
} catch (error) {
this.logger.error(error);
}
};

private computeTimeout(schedule: AASEndpointSchedule | undefined, start?: number): number {
private computeTimeout(schedule: AASEndpointSchedule | undefined, start: number, end: number): number {
if (schedule === undefined) {
return this.variable.SCAN_ENDPOINT_TIMEOUT;
}
Expand All @@ -498,23 +527,23 @@ export class AASProvider {
if (schedule.type === 'every') {
const values = schedule.values;
if (values && values.length > 0 && typeof values[0] === 'number') {
const timeout = Date.now() - start - values[0];
const timeout = end - start - values[0];
return timeout >= 0 ? timeout : values[0];
}
}

return this.variable.SCAN_ENDPOINT_TIMEOUT;
}

private scanEndpoint = async (taskId: number, endpoint: AASEndpoint) => {
private scanEndpoint = async (task: Task, endpoint: AASEndpoint) => {
const data: ScanEndpointData = {
type: 'ScanEndpointData',
taskId,
taskId: task.id,
endpoint,
start: Date.now(),
};

this.taskHandler.set(taskId, { endpointName: endpoint.name, owner: this, type: 'ScanEndpoint' });
task.state = 'inProgress';
task.start = Date.now();
this.parallel.execute(data);
};

Expand Down Expand Up @@ -544,21 +573,21 @@ export class AASProvider {

private parallelOnEnd = async (result: ScanResult) => {
const task = this.taskHandler.get(result.taskId);
if (!task || task.owner !== this) {
if (task === undefined || task.owner !== this) {
return;
}

this.taskHandler.delete(result.taskId);
if ((await this.index.hasEndpoint(task.endpointName)) === true) {
const endpoint = await this.index.getEndpoint(task.endpointName);

if (endpoint.schedule?.type === 'once') {
if (endpoint.schedule?.type === 'once' || endpoint.schedule?.type === 'manual') {
return;
}

task.state === 'idle';
task.end = Date.now();
setTimeout(
this.scanEndpoint,
this.computeTimeout(endpoint.schedule, result.start),
this.computeTimeout(endpoint.schedule, task.start, task.end),
result.taskId,
endpoint,
);
Expand Down
1 change: 0 additions & 1 deletion projects/aas-server/src/app/aas-provider/scan-result.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ export interface ScanResult {
type: 'ScanEndResult' | 'ScanEndpointResult' | 'ScanTemplatesResult';
kind: ScanResultKind;
taskId: number;
start: number;
messages?: Message[];
}

Expand Down
32 changes: 27 additions & 5 deletions projects/aas-server/src/app/aas-provider/task-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,13 @@
import { singleton } from 'tsyringe';

export interface Task {
id: number;
endpointName: string;
owner: object;
type: 'ScanEndpoint' | 'ScanTemplates';
state: 'idle' | 'inProgress';
start: number;
end: number;
}

@singleton()
Expand All @@ -28,8 +32,8 @@ export class TaskHandler {
return this.tasks.get(taskId);
}

public set(taskId: number, task: Task) {
this.tasks.set(taskId, task);
public set(task: Task) {
this.tasks.set(task.id, task);
}

public empty(owner: object, name?: string): boolean {
Expand All @@ -42,9 +46,27 @@ export class TaskHandler {
return true;
}

public createTaskId(): number {
const taskId = this.nextTaskId;
public createTask(endpointName: string, owner: object, type: 'ScanEndpoint' | 'ScanTemplates'): Task {
const id = this.nextTaskId;
++this.nextTaskId;
return taskId;
return {
id,
type,
endpointName,
owner,
state: 'idle',
start: 0,
end: 0,
};
}

public find(endpointName: string, type: 'ScanEndpoint' | 'ScanTemplates'): Task | undefined {
for (const task of this.tasks.values()) {
if (task.endpointName === endpointName && type === task.type) {
return task;
}
}

return undefined;
}
}
1 change: 0 additions & 1 deletion projects/aas-server/src/app/aas-provider/worker-data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import { AASEndpoint } from 'aas-core';
export interface WorkerData {
taskId: number;
type: 'ScanEndpointData' | 'ScanTemplatesData';
start: number;
}

export interface ScanEndpointData extends WorkerData {
Expand Down
16 changes: 16 additions & 0 deletions projects/aas-server/src/app/controller/endpoints-controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,4 +143,20 @@ export class EndpointsController extends AASController {
this.logger.stop();
}
}

/**
* @summary Starts a scan of the AAS endpoint with the specified name.
* @param name The endpoint name.
*/
@Post('{name}/scan')
@Security('bearerAuth', ['editor'])
@OperationId('reset')
public async startEndpointScan(@Path() name: string): Promise<void> {
try {
this.logger.start('startEndpointScan');
await this.aasProvider.startEndpointScan(decodeBase64Url(name));
} finally {
this.logger.stop();
}
}
}
Loading

0 comments on commit c1dab60

Please sign in to comment.