Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updating the production server to Node 18, Angular 15 and other changes #603

Merged
merged 50 commits into from
Oct 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
258c268
refactor(backend): Socket state management refactor + adding redis ad…
LunarFang416 Mar 28, 2024
95a457c
chore: run linter
LunarFang416 Mar 28, 2024
ecedf9a
Merge pull request #574 from encorelab/abubukker/socket-refactor
LunarFang416 May 15, 2024
f2d4bbe
Fixed the three dots menu issue on project-dashboard
markiianbabiak Jun 25, 2024
2f7e0d1
Fixed indentation
markiianbabiak Jun 25, 2024
2525d5e
Update create-workflow-modal.component.ts
marieklinaeva Jun 25, 2024
d06c7ff
Merge pull request #592 from encorelab/591-bug-adjust-3-dot-menu-for-…
markiianbabiak Jun 26, 2024
fc1ff8a
Added comments to create workflow component and TODOs to ts and html …
JoelWiebe Jun 28, 2024
a75f61d
Create dump.rdb
marieklinaeva Jul 3, 2024
5c54872
Update create-workflow-modal.component.html
marieklinaeva Jul 3, 2024
a944fe3
Allow for boards as destinations and changed BOARD to CANVAS
marieklinaeva Jul 5, 2024
93a156b
Prioritized projects in source and destination lists; see TODOs to co…
JoelWiebe Jul 5, 2024
c088c7d
merged with remote branch, added redis dump to gitignore
JoelWiebe Jul 5, 2024
48bb20b
Ordering of dest/source Options
marieklinaeva Jul 5, 2024
550d1de
Distribution workflows issues fixed
marieklinaeva Jul 9, 2024
0040f98
Ran document formatter with Prettier
marieklinaeva Jul 9, 2024
92882f3
Delete dump.rdb
markiianbabiak Jul 11, 2024
8023adb
Update .gitignore in backend with dump.rdb
markiianbabiak Jul 11, 2024
938e1f5
Merge pull request #595 from encorelab/issue-478-include-the-board-as…
markiianbabiak Jul 11, 2024
ad75bff
Updating dependancies
markiianbabiak Jul 17, 2024
9fc4dc9
Updating Angular from v12 to v13
markiianbabiak Jul 17, 2024
d1c82fd
Updating angular v13 to v14
markiianbabiak Jul 17, 2024
d8a7652
Updating Angular from v14 to v15
markiianbabiak Jul 17, 2024
6174912
Updating @angular-eslint from v12 to v15
markiianbabiak Jul 18, 2024
ce5ae7a
Updating @angular/cdk from v12 to v13
markiianbabiak Jul 18, 2024
90f92e6
Updating @angular/cdk from v13 to v14
markiianbabiak Jul 18, 2024
e88e243
Updating @angular/sdk from v14 to v15
markiianbabiak Jul 18, 2024
4aad888
Updating @angular/material from v12 to v13
markiianbabiak Jul 18, 2024
fb5c231
Updating @angular/material from v13 to v14
markiianbabiak Jul 18, 2024
f873115
Updating @angular/material from v14 to v15
markiianbabiak Jul 19, 2024
225e28f
Removing firebase calls
markiianbabiak Jul 19, 2024
57aaa95
Removing a warning during compilation
markiianbabiak Jul 19, 2024
b235501
Fixing errors
markiianbabiak Jul 19, 2024
4e8ce79
Commenting out all the references to fileUploadService
markiianbabiak Jul 19, 2024
638681b
Removing unused imports which messed up the styling
markiianbabiak Jul 19, 2024
8a94f5f
Changes in package-lock.json
markiianbabiak Jul 19, 2024
c30e334
Fixing the icon not showing up correctly
markiianbabiak Aug 26, 2024
de95e62
Fixed return to dashboard projectID undefined bug; fixed cancel x but…
JoelWiebe Aug 29, 2024
120f710
Trying to fix slider visibility issue
marieklinaeva Aug 30, 2024
404b6e6
Merge branch '597-feature-updating-node-to-version-17' of https://git…
marieklinaeva Aug 30, 2024
fe81677
Solved the peer dependancies conflict
markiianbabiak Sep 10, 2024
83d6866
Revert "Solved the peer dependancies conflict"
markiianbabiak Sep 10, 2024
b313dba
Dependencies update for node v18
markiianbabiak Sep 18, 2024
f17373a
Styling fix
markiianbabiak Sep 18, 2024
6faa2f8
Checkpoint
markiianbabiak Sep 27, 2024
d4654ff
Updating files to accommodate new rxjs version
markiianbabiak Sep 28, 2024
0d395b8
Styling fixes
markiianbabiak Sep 28, 2024
30a4095
Merge pull request #600 from encorelab/599-bug-update-rxjs-to-deal-wi…
markiianbabiak Oct 3, 2024
cbcae84
Merge branch 'master' into master-merge-updates
markiianbabiak Oct 5, 2024
7963d29
Styling fix
markiianbabiak Oct 5, 2024
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
node_modules
/.vscode/launch.json
.DS_Store
dump.rdb
4 changes: 3 additions & 1 deletion backend/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,6 @@
*.js

# misc
.DS_Store
.DS_Store

dump.rdp
10,523 changes: 3,879 additions & 6,644 deletions backend/package-lock.json

Large diffs are not rendered by default.

13 changes: 8 additions & 5 deletions backend/package.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"dependencies": {
"@socket.io/redis-adapter": "^8.1.0",
"@typegoose/typegoose": "^9.8.1",
"@types/bcrypt": "^5.0.0",
"bcrypt": "^5.0.1",
Expand All @@ -9,14 +10,15 @@
"dotenv": "^16.0.0",
"express": "^4.17.3",
"express-jwt": "^7.7.0",
"ioredis": "^5.3.2",
"jsonwebtoken": "^8.5.1",
"migrate-mongo": "^9.0.0",
"mongo-dot-notation": "^3.1.0",
"mongoose": "^6.3.2",
"mongoose-autopopulate": "^0.17.1",
"nodemon": "^2.0.16",
"prettier": "^2.6.2",
"socket.io": "^4.4.1",
"socket.io": "^4.7.5",
"uuid": "^8.3.2"
},
"scripts": {
Expand All @@ -38,15 +40,16 @@
"@types/crypto-js": "^4.1.1",
"@types/express": "^4.17.13",
"@types/jsonwebtoken": "^8.5.8",
"@types/node": "^17.0.31",
"@types/node": "^18.19.50",
"@types/uuid": "^8.3.4",
"@typescript-eslint/eslint-plugin": "^5.22.0",
"@typescript-eslint/parser": "^5.22.0",
"cross-env": "^7.0.3",
"eslint": "^8.17.0",
"migrate-mongo": "^9.0.0",
"ts-node": "^10.7.0",
"ts-node-dev": "^1.1.8",
"typescript": "^4.6.4"
"ts-node": "^10.9.1",
"ts-node-dev": "^2.0.0",
"typescript": "^4.7.4"
},
"author": "",
"license": "ISC",
Expand Down
12 changes: 10 additions & 2 deletions backend/src/api/workflows.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import mongoose from 'mongoose';
import WorkflowManager from '../agents/workflow.agent';
import { SocketEvent } from '../constants';
import { GroupTaskModel, GroupTaskStatus } from '../models/GroupTask';

Check warning on line 5 in backend/src/api/workflows.ts

View workflow job for this annotation

GitHub Actions / Linting and Code Formating Check CI (backend)

'GroupTaskStatus' is defined but never used
import { PostType } from '../models/Post';
import {
ContainerType,
Expand Down Expand Up @@ -311,7 +311,11 @@

await dalGroupTask.update(groupTaskID, task);

Socket.Instance.emit(SocketEvent.WORKFLOW_PROGRESS_UPDATE, [task], true);
Socket.Instance.emit(
SocketEvent.WORKFLOW_PROGRESS_UPDATE,
[task],
workflow.boardID
);

res.status(200).json(task);
});
Expand Down Expand Up @@ -360,7 +364,11 @@
}
}

Socket.Instance.emit(SocketEvent.WORKFLOW_POST_SUBMIT, post, true);
Socket.Instance.emit(
SocketEvent.WORKFLOW_POST_SUBMIT,
post,
workflow.boardID
);
return res.status(200).json(updatedGroupTask);
} catch (e) {
return res.status(500).end('Unable to submit post!');
Expand Down
26 changes: 20 additions & 6 deletions backend/src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import groups from './api/groups';
import todoItems from './api/todoItem';
import learner from './api/learner';
import { isAuthenticated } from './utils/auth';
import RedisClient from './utils/redis';
dotenv.config();

const port = process.env.PORT || 8001;
Expand All @@ -29,14 +30,25 @@ const dbUrl = process.env.DB_URL;
const dbName = process.env.DB_NAME;
const dbURI = `mongodb+srv://${dbUsername}:${dbPassword}@${dbUrl}.mongodb.net/${dbName}?retryWrites=true&w=majority`;

const redisHost = process.env.REDIS_HOST || 'localhost';
const redisPort = (process.env.REDIS_PORT || 6379) as number;
const redisPassword = process.env.REDIS_PASSWORD || '';

const app = express();
app.use(cors());
app.use(bodyParser.json());
app.use(express.static(path.join(__dirname, '../../frontend/dist/ck-board')));
const server = http.createServer(app);

const redis = new RedisClient({
host: redisHost,
port: redisPort,
password: redisPassword,
});

const socket = Socket.Instance;
socket.init(server);

socket.init(redis);

app.use('/api/projects', isAuthenticated, projects);
app.use('/api/boards', isAuthenticated, boards);
Expand All @@ -52,11 +64,13 @@ app.use('/api/trace', isAuthenticated, trace);
app.use('/api/todoItems', isAuthenticated, todoItems);
app.use('/api/learner', isAuthenticated, learner);

app.get('*', (req, res) => {
res.sendFile(
path.join(__dirname + '/../../frontend/dist/ck-board/index.html')
);
});
const shutdown = async () => {
await redis.disconnect();
process.exit(0);
};

// Handle termination signals
process.on('SIGINT', shutdown);

mongoose
.connect(dbURI)
Expand Down
95 changes: 56 additions & 39 deletions backend/src/socket/socket.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@ import * as socketIO from 'socket.io';
import { SocketEvent } from '../constants';
import events from './events';
import SocketManager from './socketManager';
import RedisClient from '../utils/redis';
import { createAdapter } from '@socket.io/redis-adapter';

class Socket {
private static _instance: Socket;

private _socketManager: SocketManager;
private _io: socketIO.Server | null = null;
private _socket: socketIO.Socket | null = null;
private _currentRoom: string | null = null;

// eslint-disable-next-line @typescript-eslint/no-empty-function
private constructor() {
Expand All @@ -28,42 +28,46 @@ class Socket {
* @param server the http server
* @returns void
*/
init(server: Server) {
const io = new socketIO.Server(server, {

init(redis: RedisClient) {
const io = new socketIO.Server(8000, {
cors: {
origin: '*',
},
adapter: createAdapter(redis.getPublisher, redis.getSubscriber),
});

this._io = io;

console.log('Socket server running...');

io.on('connection', (socket) => {
this._socket = socket;
// this._socket = socket;

socket.on('join', (user: string, room: string) => {
socket.data.room = room;
this._safeJoin(socket, user, room);
this._listenForEvents(io, socket);
this._logUserSocketsAndRooms(user);
});

socket.on('leave', (user: string, room: string) => {
if (this._currentRoom && this._currentRoom == room) {
socket.leave(this._currentRoom);
console.log(`Socket ${socket.id} left room ${room}`);

events.map((e) => socket.removeAllListeners(e.type.toString()));
socket.data.room = null;
this._currentRoom = null;
this._socketManager.removeByUserId(user);
}
socket.leave(room);
console.log(`Socket ${socket.id} left room ${room}`);
events.map((e) => socket.removeAllListeners(e.type.toString()));

// Remove the specific socketId for the user from the SocketManager
this._socketManager.removeBySocketId(socket.id);
this._logUserSocketsAndRooms(user);
});

socket.on('disconnect', () => {
if (this._socket) {
this._currentRoom = null;
this._socketManager.removeBySocketId(this._socket.id);
}
const rooms = socket.rooms;
rooms.forEach((room) => {
socket.leave(room);
// Potentially update or notify the room of the disconnect
});
this._socketManager.removeBySocketId(socket.id);
});

socket.on('disconnectAll', async (room: string) => {
Expand All @@ -74,27 +78,19 @@ class Socket {
}

/**
* Sends an event to all users connected to socket (except sender).
* Emits an event to a specific room.
*
* @param event the type of event being emitted
* @param eventData data associated with event
* @param toSender send event to room and sender
* @returns void
* @param event The type of event being emitted.
* @param eventData Data associated with the event.
* @param roomId The ID of the room to which the event should be emitted.
* @param toSender Indicates whether the event should also be sent to the sender.
*/
emit(event: SocketEvent, eventData: unknown, toSender = false): void {
if (this._socket == null) {
throw new Error('Socket not initialized. Please invoke init() first.');
} else if (this._currentRoom == null) {
throw new Error('Socket not connected to any rooms.');
} else if (this._io == null) {
emit(event: SocketEvent, eventData: unknown, roomId: string): void {
if (!this._io) {
throw new Error('IO not initialized. Please invoke init() first.');
}

if (toSender) {
this._io.to(this._currentRoom).emit(event, eventData);
} else {
this._socket.to(this._currentRoom).emit(event, eventData);
}
this._io.to(roomId).emit(event, eventData);
}

/**
Expand Down Expand Up @@ -123,13 +119,34 @@ class Socket {
* @returns void
*/
private _safeJoin(socket: socketIO.Socket, user: string, nextRoom: string) {
if (this._currentRoom) socket.leave(this._currentRoom);

socket.join(nextRoom);

this._socketManager.add(user, socket.id);
this._currentRoom = nextRoom;
console.log(`Socket ${socket.id} joined room ${nextRoom}`);
console.log(`Socket ${socket.id} (userID ${user}) joined room ${nextRoom}`);
}

/**
* Logs the sockets and their corresponding rooms for a given user.
*
* @param userId The ID of the user whose sockets and rooms to log.
*/
private _logUserSocketsAndRooms(userId: string): void {
const socketIds = this._socketManager.get(userId);
if (!socketIds) {
return;
}

console.log(`User ${userId} =>`);
socketIds.forEach((socketId) => {
const socket = this._io?.sockets.sockets.get(socketId);
if (socket && socket.data.room) {
console.log(`\tSocket ID: ${socketId}, Room: ${socket.data.room}`);
} else {
console.log(
`\tSocket ID: ${socketId} is not currently connected or has no room.`
);
}
});
console.log('');
}
}

Expand Down
36 changes: 29 additions & 7 deletions backend/src/socket/socketManager.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
class SocketManager {
private static _instance: SocketManager;

private _userToSocket: Map<string, string>;
private _userToSocket: Map<string, string[]>;

private constructor() {
this._userToSocket = new Map();
Expand All @@ -11,24 +11,46 @@ class SocketManager {
return this._instance || (this._instance = new this());
}

add(userID: string, socketID: string): Map<string, string> {
return this._userToSocket.set(userID, socketID);
/**
* Adds a socket ID to a user's list of socket IDs.
* If the user does not exist, creates a new entry.
*/
add(userID: string, socketID: string): void {
const sockets = this._userToSocket.get(userID) || [];
sockets.push(socketID);
this._userToSocket.set(userID, sockets);
}

removeByUserId(userID: string): boolean {
return this._userToSocket.delete(userID);
}

/**
* Removes a specific socket ID from a user's list.
* If the user has no more socket IDs left after removal, deletes the user's entry.
*/
removeBySocketId(socketID: string): boolean {
for (const [user, socket] of this._userToSocket.entries()) {
if (socket == socketID) {
return this._userToSocket.delete(user);
for (const [user, sockets] of this._userToSocket.entries()) {
const index = sockets.indexOf(socketID);
if (index !== -1) {
sockets.splice(index, 1);
if (sockets.length === 0) {
// If no sockets left, remove the user entry
this._userToSocket.delete(user);
} else {
// Update with the modified array
this._userToSocket.set(user, sockets);
}
return true;
}
}
return false;
}

get(userID: string) {
/**
* Retrieves the list of socket IDs for a user.
*/
get(userID: string): string[] | undefined {
return this._userToSocket.get(userID);
}
}
Expand Down
Loading
Loading