Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
99 commits
Select commit Hold shift + click to select a range
464c77f
feat: implement basic proto file
OmegaCreations Jun 8, 2025
268a99a
feat: Duplex stream with specific payload message events.
OmegaCreations Jun 10, 2025
7b7888a
feat: Duplex stream with specific payload message events.
OmegaCreations Jun 10, 2025
6373548
feat: Create typescript interfaces for duplex stream message model
OmegaCreations Jun 10, 2025
255e567
feat: Add description to typescript interfaces
OmegaCreations Jun 10, 2025
7edca58
feat: implement serialization and deserialization methods
OmegaCreations Jun 10, 2025
0485204
feat: add package dependencies and write unit tests for serialization…
OmegaCreations Jun 10, 2025
58666d5
fix: fixed oneof variable naming
OmegaCreations Jun 10, 2025
0118271
feat: Duplex stream with specific payload message events.
OmegaCreations Jun 10, 2025
7c5d552
feat: Create typescript interfaces for duplex stream message model
OmegaCreations Jun 10, 2025
4b18459
feat: implement serialization and deserialization methods
OmegaCreations Jun 10, 2025
dba904c
feat: add package dependencies and write unit tests for serialization…
OmegaCreations Jun 10, 2025
273b8e2
feat: Create grpc wrapper with basic connection manager and central s…
OmegaCreations Jun 10, 2025
6467c55
fix: fix grpc addresses to properly connect both client and central s…
OmegaCreations Jun 10, 2025
1a86d49
fix: refactor comments
OmegaCreations Jun 11, 2025
bec195c
fix: change central system class name to avoid conflicts with central…
OmegaCreations Jun 11, 2025
c6a3f01
feat: implement Connection class and a map storing all receiving and …
OmegaCreations Jun 11, 2025
fb12e55
feat: implement replacing new token for client from central system
OmegaCreations Jun 11, 2025
63faee3
feat: implement token revokation by changing connection status
OmegaCreations Jun 11, 2025
456bf84
fix: remove unnecessary params
OmegaCreations Jun 11, 2025
93c3a51
fix: fix enum naming
OmegaCreations Jun 17, 2025
ff0faf0
fix: fix proto types order based on Bookkeeping standards
OmegaCreations Jun 17, 2025
d207f78
Merge branch 'feature/TKN/OGUI-1702/basic-proto-file' of github.com:A…
OmegaCreations Jun 17, 2025
fb6c39c
fix: add copyright banner
OmegaCreations Jun 17, 2025
8106fe1
Merge branch 'feature/TKN/OGUI-1702/basic-proto-file' of github.com:A…
OmegaCreations Jun 17, 2025
72042c8
fix: add copyright banner and change enum naming convention
OmegaCreations Jun 17, 2025
d762f9f
Merge branch 'feature/TKN/OGUI-1703/basic-typescript-interfaces' of g…
OmegaCreations Jun 17, 2025
b70cf9e
fix: fix serialization comments and tests
OmegaCreations Jun 17, 2025
aff4c59
Merge branch 'feature/TKN/OGUI-1704/data-serialization-utils' of gith…
OmegaCreations Jun 17, 2025
9de3ce5
Merge branch 'dev' into feature/TKN/OGUI-1703/basic-typescript-interf…
graduta Jun 18, 2025
bdba63d
feat: add description comments and implement .listen() instead of aut…
OmegaCreations Jul 8, 2025
326eea5
fix: change enum values to numbers
OmegaCreations Jul 8, 2025
4011499
Merge branch 'feature/TKN/OGUI-1703/basic-typescript-interfaces' of g…
OmegaCreations Jul 8, 2025
5857652
fix: move test directory
OmegaCreations Jul 8, 2025
54447ea
feat: add webui logger instead of console logs and fix paths
OmegaCreations Jul 8, 2025
af429ce
Merge branch 'feature/TKN/OGUI-1703/basic-typescript-interfaces' of g…
OmegaCreations Jul 8, 2025
9db612e
feat: write tests for central system and connection manager
OmegaCreations Jul 9, 2025
ec193ca
Merge branch 'feature/TKN/OGUI-1705/client-central-basic-stream' of g…
OmegaCreations Jul 9, 2025
d0f4dad
feat: muldularize connection management. Add project building.
OmegaCreations Jul 10, 2025
b4a0bf9
fix: fix connection and remove exponential backoff for simplified ver…
OmegaCreations Jul 10, 2025
8d9c89a
fix: test setup fixes
OmegaCreations Jul 20, 2025
1081941
Merge branch 'feature/TKN/OGUI-1708/basic-connection-class' of github…
OmegaCreations Jul 20, 2025
b6695a4
fix: fix tscofing for js builds and typescript files/tests runtime
OmegaCreations Jul 28, 2025
e79215c
feat: refactor code for command design pattern
OmegaCreations Aug 4, 2025
90d713d
feat: unit tests for token revokation
OmegaCreations Aug 4, 2025
e079438
feat: implement token revokation logic and testing
OmegaCreations Aug 5, 2025
5527944
feat: implement connection direction info inside of payload
OmegaCreations Aug 5, 2025
090da6b
fix: fix tests
OmegaCreations Aug 7, 2025
fd0e1dd
feat: implement command for new token from central system
OmegaCreations Aug 7, 2025
5965abe
feat: add missing comments, banners and tests
OmegaCreations Aug 7, 2025
4562762
fix: fixed banner processing. removed console logs
OmegaCreations Aug 7, 2025
ec36841
feat: add github actions for wrapper tests
OmegaCreations Aug 16, 2025
836ff51
fix: paths
OmegaCreations Aug 16, 2025
c61ac97
fix: pathing
OmegaCreations Aug 16, 2025
351099d
Merge branch 'feature/TKN/OGUI-1710/handle-newly-generated-token' of …
OmegaCreations Aug 16, 2025
ec8ea1a
fix: fix tests
OmegaCreations Aug 16, 2025
6ac9f71
feat: implement simple connection peer to peers
OmegaCreations Aug 27, 2025
6ba86f2
fix: remove unnecessary utils
OmegaCreations Aug 31, 2025
2569c5c
fix: remove unused variable
OmegaCreations Aug 31, 2025
dd246bd
Merge branch 'dev' of github.com:AliceO2Group/WebUi into feature/TKN/…
OmegaCreations Aug 31, 2025
21fb63e
fix: refactor unit tests
OmegaCreations Aug 31, 2025
957a7be
feat: update unit tests for p2p connections
OmegaCreations Aug 31, 2025
b8edd56
feat: implement reconnection scheduler
OmegaCreations Sep 2, 2025
863438b
fix: fix scheduler
OmegaCreations Sep 3, 2025
542e0f6
fix: fix imports
OmegaCreations Sep 3, 2025
f41266f
Merge branch 'dev' of github.com:AliceO2Group/WebUi into feature/TKN/…
OmegaCreations Nov 6, 2025
37a8021
fix: remove duplicates
OmegaCreations Nov 6, 2025
feeb637
fix: unit tests
OmegaCreations Nov 6, 2025
44f58e4
fix: move .gitignore to parent .gitignore
OmegaCreations Nov 6, 2025
c87f1f1
fix: default wrapper port changed to 4100
OmegaCreations Nov 6, 2025
b2f24c6
fix: change private variables naming
OmegaCreations Nov 6, 2025
d043717
fix: rename directories to start with small letters
OmegaCreations Nov 6, 2025
48c51dc
fix: fix imports and add breaklines after banners
OmegaCreations Nov 6, 2025
9ae5c9b
feat: inform about central system address on connection
OmegaCreations Nov 6, 2025
75a9f14
fix: tests testing initializtion of object shouuld have object creati…
OmegaCreations Nov 6, 2025
f6cb712
feat: implement missing descriptions
OmegaCreations Nov 6, 2025
d0c57bf
fix: make sure that proto file enums have number 0 with default, unde…
OmegaCreations Nov 6, 2025
3c82edc
feat: implement eslint and fix its errors
OmegaCreations Nov 6, 2025
6552480
Merge branch 'feature/TKN/OGUI-1710/handle-newly-generated-token' of …
OmegaCreations Nov 11, 2025
95ff34f
Merge branch 'feature/TKN/OGUI-1746/add-github-actions-for-wrapper' o…
OmegaCreations Nov 11, 2025
a253f51
fix: fix files, unit tests and add tests for connection
OmegaCreations Nov 12, 2025
866f599
fix: rebuild package lock
OmegaCreations Nov 12, 2025
b85554f
Merge branch 'dev' into feature/TKN/OGUI-1747/simple-client-p2p-conne…
OmegaCreations Nov 12, 2025
9d05309
Merge branch 'dev' of github.com:AliceO2Group/WebUi into feature/TKN/…
OmegaCreations Nov 13, 2025
74af151
Merge branch 'feature/TKN/OGUI-1747/simple-client-p2p-connection' of …
OmegaCreations Nov 13, 2025
3d832ba
fix: fix rebase
OmegaCreations Nov 13, 2025
f0e4643
fix: tests, remove express, fix comments in gRPCWrapper
OmegaCreations Nov 13, 2025
baa9511
fix: tests
OmegaCreations Nov 13, 2025
6d658fb
feat: move peer listening to separate method and util file
OmegaCreations Nov 13, 2025
16a2ec6
fix: remove additional description
OmegaCreations Nov 13, 2025
b742ccc
Merge branch 'dev' into feature/TKN/OGUI-1747/simple-client-p2p-conne…
OmegaCreations Nov 13, 2025
0d22a81
Merge branch 'dev' into feature/TKN/OGUI-1747/simple-client-p2p-conne…
OmegaCreations Nov 16, 2025
1009225
Merge branch 'dev' into feature/TKN/OGUI-1747/simple-client-p2p-conne…
OmegaCreations Nov 18, 2025
a2d72da
Merge branch 'feature/TKN/OGUI-1747/simple-client-p2p-connection' of …
OmegaCreations Nov 18, 2025
3bbc627
feat: rebase, write tests for reconnection schaduler and fix it
OmegaCreations Nov 18, 2025
afc3927
Merge branch 'dev' into feature/TKN/OGUI-1754/create-reconnection-sch…
OmegaCreations Nov 26, 2025
cecb617
Merge branch 'dev' into feature/TKN/OGUI-1754/create-reconnection-sch…
OmegaCreations Nov 26, 2025
e01a65e
Merge branch 'dev' into feature/TKN/OGUI-1754/create-reconnection-sch…
OmegaCreations Nov 26, 2025
eab1552
Merge branch 'dev' into feature/TKN/OGUI-1754/create-reconnection-sch…
OmegaCreations Nov 26, 2025
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
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import type * as grpc from '@grpc/grpc-js';
import { LogManager } from '@aliceo2/web-ui';
import type { CentralCommandDispatcher } from './eventManagement/CentralCommandDispatcher';
import type { DuplexMessageModel } from '../../models/message.model';
import { ReconnectionScheduler } from '../../utils/connection/reconnectionScheduler';

/**
* This class manages the duplex stream with the CentralSystem gRPC service.
Expand All @@ -24,6 +25,11 @@ import type { DuplexMessageModel } from '../../models/message.model';
export class CentralConnection {
private _logger = LogManager.getLogger('CentralConnection');
private _stream?: grpc.ClientDuplexStream<unknown, unknown>;
private _reconnectionScheduler: ReconnectionScheduler = new ReconnectionScheduler(
() => this.connect(),
{ initialDelay: 1000, maxDelay: 30000 },
this._logger
);

/**
* Constructor for the CentralConnection class.
Expand All @@ -44,32 +50,23 @@ export class CentralConnection {

this._stream?.on('data', (payload: DuplexMessageModel) => {
this._logger.debugMessage(`Received payload: ${JSON.stringify(payload)}`);
this._reconnectionScheduler.reset();
this._dispatcher.dispatch(payload);
});

this._stream?.on('end', () => {
this._logger.infoMessage(`Stream ended, attempting to reconnect...`);
this._stream = undefined;
this.scheduleReconnect();
this._reconnectionScheduler.schedule();
});

this._stream?.on('error', (err: any) => {
this._logger.infoMessage('Stream error:', err, ' attempting to reconnect...');
this._stream = undefined;
this.scheduleReconnect();
this._reconnectionScheduler.schedule();
});
}

/**
* Schedules a reconnect with exponential backoff.
*/
private scheduleReconnect() {
setTimeout(() => {
this._logger.infoMessage(`Trying to reconnect...`);
this.connect();
}, 2000);
}

/**
* Starts the connection to the central system.
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
/**
* @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 { ReconnectionScheduler } from '../../../utils/connection/reconnectionScheduler';

describe('ReconnectionScheduler', () => {
let reconnectCallback: jest.Mock;
let logger: { infoMessage: jest.Mock; errorMessage?: jest.Mock };
let scheduler: ReconnectionScheduler;

beforeEach(() => {
jest.useFakeTimers();
reconnectCallback = jest.fn();
logger = {
infoMessage: jest.fn(),
errorMessage: jest.fn(),
};

scheduler = new ReconnectionScheduler(
reconnectCallback,
{
initialDelay: 1000,
maxDelay: 8000,
},
logger as any
);
});

afterEach(() => {
jest.clearAllTimers();
jest.useRealTimers();
});

test("schedule's first attempt should schedule and call reconnectCallback", () => {
scheduler.schedule();

expect(logger.infoMessage).toHaveBeenCalledWith('Recconection attempt #1: Sleep for 2000 ms.');

expect(reconnectCallback).not.toHaveBeenCalled();
jest.advanceTimersByTime(1999);
expect(reconnectCallback).not.toHaveBeenCalled();
jest.advanceTimersByTime(1);
expect(reconnectCallback).toHaveBeenCalledTimes(1);
});

test('Schedule attempts should be exponential', () => {
scheduler.schedule();
jest.advanceTimersByTime(2000);

scheduler.schedule();
expect(logger.infoMessage).toHaveBeenLastCalledWith('Recconection attempt #2: Sleep for 4000 ms.');
jest.advanceTimersByTime(4000);
expect(reconnectCallback).toHaveBeenCalledTimes(2);
});

test("schedule's delay should be limited by maxDelay", () => {
scheduler = new ReconnectionScheduler(
reconnectCallback,
{
initialDelay: 1000,
maxDelay: 3000,
},
logger as any
);

scheduler.schedule();
expect(logger.infoMessage).toHaveBeenLastCalledWith('Recconection attempt #1: Sleep for 2000 ms.');
jest.advanceTimersByTime(2000);

scheduler.schedule();
expect(logger.infoMessage).toHaveBeenLastCalledWith('Recconection attempt #2: Sleep for 3000 ms.');
jest.advanceTimersByTime(3000);

scheduler.schedule();
expect(logger.infoMessage).toHaveBeenLastCalledWith('Recconection attempt #3: Sleep for 3000 ms.');
});

test('schedule() should not schedule again if it is scheduled', () => {
scheduler.schedule();
scheduler.schedule();

expect(logger.infoMessage).toHaveBeenCalledTimes(1);

jest.advanceTimersByTime(100000);
expect(reconnectCallback).toHaveBeenCalledTimes(1);
});

test('reset() should clear timer, reset attemptCount and currentDelay', () => {
scheduler.schedule();

jest.advanceTimersByTime(500);
expect(reconnectCallback).not.toHaveBeenCalled();

scheduler.reset();

jest.advanceTimersByTime(100000);
expect(reconnectCallback).not.toHaveBeenCalled();

scheduler.schedule();
expect(logger.infoMessage).toHaveBeenLastCalledWith('Recconection attempt #1: Sleep for 2000 ms.');
});

test('reset() should ignore another reset due to isResseting variable', () => {
scheduler.schedule();
scheduler.reset();
scheduler.reset();
scheduler.schedule();

jest.advanceTimersByTime(2000);
expect(reconnectCallback).toHaveBeenCalledTimes(1);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/**
* @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.
*/

export interface ReconnectionOptions {
initialDelay?: number; // Initial delay in ms
maxDelay?: number; // Maximum delay in ms
}

/**
* A scheduler that manages reconnection attempts with an exponential backoff.
*/
export class ReconnectionScheduler {
private reconnectCallback: any;
private initialDelay: number;
private maxDelay: number;
private currentDelay: number;
private attemptCount: number;
private timeoutId: any;
private logger: Logger;

private isResetting: boolean = false;
private isScheduling: boolean = false;

/**
* Creates a new instance of the ReconnectionScheduler.
* @param {any} reconnectCallback - The callback to be called when a reconnection attempt is scheduled.
* @param {ReconnectionOptions} [options] - Options for the reconnection schedule.
* @param {Logger} logger - The logger instance to be used for logging messages.
*/
constructor(reconnectCallback: any, options: ReconnectionOptions = {}, logger: Logger) {
this.reconnectCallback = reconnectCallback;
this.initialDelay = options.initialDelay ?? 1000;
this.maxDelay = options.maxDelay ?? 30000;

this.currentDelay = this.initialDelay;
this.attemptCount = 0;
this.timeoutId = null;

this.logger = logger;
}

/**
* Schedules the next reconnection attempt using exponential backoff.
*/
schedule() {
if (this.isScheduling) return;
this.isScheduling = true;
this.isResetting = false;
this.attemptCount++;

// Exponential backoff calculation
const delay = this.initialDelay * Math.pow(2, this.attemptCount);

this.currentDelay = Math.min(this.maxDelay, delay);

this.logger.infoMessage(`Recconection attempt #${this.attemptCount}: Sleep for ${this.currentDelay.toFixed(0)} ms.`);

// Plan the reconnection attempt
this.timeoutId = setTimeout(() => {
this.isScheduling = false;
this.reconnectCallback();
}, this.currentDelay);
}

/**
* Resets the scheduler to its initial state.
*/
reset() {
if (this.isResetting) return;
this.isScheduling = false;
this.isResetting = true;

clearTimeout(this.timeoutId);
this.attemptCount = 0;
this.currentDelay = this.initialDelay;
}
}
14 changes: 8 additions & 6 deletions Tokenization/backend/wrapper/src/utils/types/webui.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,13 @@

declare module '@aliceo2/web-ui' {
export const LogManager: {
getLogger: (name: string) => {
infoMessage: (...args: any[]) => void;
errorMessage: (...args: any[]) => void;
warnMessage: (...args: any[]) => void;
debugMessage: (...args: any[]) => void;
};
getLogger: (name: string) => Logger;
};
}

declare interface Logger {
infoMessage: (...args: any[]) => void;
errorMessage: (...args: any[]) => void;
warnMessage: (...args: any[]) => void;
debugMessage: (...args: any[]) => void;
}