Add scan session management to SocketUser class
All checks were successful
farmcontrol/farmcontrol-ws/pipeline/head This commit looks good

- Introduced a `scanSessions` map to track active scan sessions.
- Implemented logic in `handleObjectActionEvent` to add and remove sessions based on scan actions.
- Added `cancelScanSessions` method to clear active sessions upon user disconnect, ensuring proper cleanup.
- Updated tests to verify that scan sessions are correctly canceled during disconnection.
This commit is contained in:
Tom Butcher 2026-09-14 22:55:43 +01:00
parent dc285a63fe
commit 940c05078e
2 changed files with 58 additions and 1 deletions

View File

@ -335,5 +335,24 @@ describe('SocketUser', () => {
socketUser.notificationManager.removeAllListeners socketUser.notificationManager.removeAllListeners
).toHaveBeenCalled(); ).toHaveBeenCalled();
}); });
it('should cancel tracked scan sessions', async () => {
socketUser.scanSessions.set('session-1', 'host-1');
socketUser.scanSessions.set('session-2', 'host-2');
await socketUser.handleDisconnect();
expect(socketUser.actionManager.sendObjectAction).toHaveBeenCalledWith(
'host-1',
'host',
{ type: 'scanNetworkStop', data: { sessionId: 'session-1' } }
);
expect(socketUser.actionManager.sendObjectAction).toHaveBeenCalledWith(
'host-2',
'host',
{ type: 'scanNetworkStop', data: { sessionId: 'session-2' } }
);
expect(socketUser.scanSessions.size).toBe(0);
});
}); });
}); });

View File

@ -35,6 +35,7 @@ export class SocketUser {
this.serverManager = new ServerManager(this); this.serverManager = new ServerManager(this);
this.userSettingsManager = new UserSettingsManager(this); this.userSettingsManager = new UserSettingsManager(this);
this.keycloakAuth = new KeycloakAuth(); this.keycloakAuth = new KeycloakAuth();
this.scanSessions = new Map();
this.setupSocketEventHandlers(); this.setupSocketEventHandlers();
} }
@ -352,15 +353,52 @@ export class SocketUser {
} }
async handleObjectActionEvent(data, callback) { async handleObjectActionEvent(data, callback) {
const action = data?.action;
const sessionId = action?.data?.sessionId;
if (
data?.objectType === 'host' &&
action?.type === 'scanNetwork' &&
sessionId
) {
this.scanSessions.set(sessionId, data._id);
}
if (action?.type === 'scanNetworkStop' && sessionId) {
this.scanSessions.delete(sessionId);
}
await this.actionManager.sendObjectAction( await this.actionManager.sendObjectAction(
data._id, data._id,
data.objectType, data.objectType,
data.action, action,
callback callback
); );
} }
async cancelScanSessions() {
const sessions = Array.from(this.scanSessions.entries());
this.scanSessions.clear();
if (sessions.length === 0) {
return;
}
logger.info('Cancelling scan sessions on user disconnect:', sessions.length);
await Promise.all(
sessions.map(([sessionId, hostId]) =>
this.actionManager.sendObjectAction(hostId, 'host', {
type: 'scanNetworkStop',
data: { sessionId }
})
)
);
}
async handleDisconnect() { async handleDisconnect() {
await this.cancelScanSessions();
if (this.user?._id) { if (this.user?._id) {
const userId = this.user._id.toString(); const userId = this.user._id.toString();
for (const activityKey of this.trackedActivities) { for (const activityKey of this.trackedActivities) {