Skip to content

Commit

Permalink
Can't abstract centrifugo connection
Browse files Browse the repository at this point in the history
  • Loading branch information
Rethakgetse-Manaka committed Sep 10, 2024
1 parent 867bd95 commit 153cba9
Show file tree
Hide file tree
Showing 8 changed files with 405 additions and 186 deletions.
40 changes: 31 additions & 9 deletions frontend/occupi-web/src/AuthService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import axios from "axios";

const API_URL = "/auth"; // This will be proxied to https://dev.occupi.tech
const API_USER_URL = "/api"; // Adjust this if needed

const RTC_URL = "/rtc"; // Adjust this if needed
interface PublicKeyCredential {
id: string;
rawId: ArrayBuffer;
Expand Down Expand Up @@ -283,7 +283,7 @@ const AuthService = {
sendResetEmail: async (email: string) => {
try {
const response = await axios.post(`${API_URL}/forgot-password`, {
"email": email
email: email,
});
if (response.data.status === 200) {
return response.data;
Expand All @@ -299,14 +299,22 @@ const AuthService = {
}
},

resetPassword: async (email: string, otp: string, newPassword: string, newPasswordConfirm: string) => {
resetPassword: async (
email: string,
otp: string,
newPassword: string,
newPasswordConfirm: string
) => {
try {
const response = await axios.post(`${API_URL}/reset-password-admin-login`, {
"email": email,
"otp": otp,
"newPassword": newPassword,
"newPasswordConfirm": newPasswordConfirm
});
const response = await axios.post(
`${API_URL}/reset-password-admin-login`,
{
email: email,
otp: otp,
newPassword: newPassword,
newPasswordConfirm: newPasswordConfirm,
}
);
if (response.data.status === 200) {
return response.data;
} else {
Expand All @@ -320,6 +328,20 @@ const AuthService = {
throw new Error("An unexpected error occurred while sending reset email");
}
},
getToken: async () => {
try {
const response = await axios.get(
`http://localhost:8080/rtc/get-token`,
{}
);
return response.data.data;
} catch (error) {
if (axios.isAxiosError(error) && error.response?.data) {
throw error.response.data;
}
throw new Error("An unexpected error occurred");
}
},
};

function bufferEncode(value: ArrayBuffer): string {
Expand Down
139 changes: 137 additions & 2 deletions frontend/occupi-web/src/CapacityService.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
// src/services/capacityService.ts

import axios from "axios";
import {
Centrifuge,
Subscription,
PublicationContext,
SubscribedContext,
SubscriptionErrorContext,
} from "centrifuge";
import AuthService from "./AuthService";

interface ResponseItem {
Date: string;
Expand Down Expand Up @@ -56,7 +64,134 @@ export const fetchCapacityData = async (): Promise<CapacityData[]> => {
};

// Additional function to get only the data needed for the CapacityComparisonGraph
export const getCapacityComparisonData = async (): Promise<Pick<CapacityData, 'day' | 'predicted'>[]> => {
export const getCapacityComparisonData = async (): Promise<
Pick<CapacityData, "day" | "predicted">[]
> => {
const fullData = await fetchCapacityData();
return fullData.map(({ day, predicted }) => ({ day, predicted }));
};
};
// Helper function to get a cookie value by name
const getCookie = (name: string): string | null => {
const match = document.cookie.match(new RegExp("(^| )" + name + "=([^;]+)"));
return match ? match[2] : null;
};

// Singleton pattern for Centrifuge instance management
let centrifuge: Centrifuge | null = null;
const subscriptions: { [key: string]: Subscription | undefined } = {};

// Function to initialize or update Centrifuge with a new token
const initCentrifuge = async () => {
try {
// Check for existing token in cookies
let token = getCookie("rtc-token");
// If no token is found in cookies, fetch a new one
if (!token) {
const response = await AuthService.getToken();
token = response; // Assuming the response has a 'token' field
console.log("Received RTC token:", token);
}

if (!token) {
throw new Error("Failed to retrieve a valid RTC token");
}
if (!centrifuge) {
centrifuge = new Centrifuge("ws://localhost:8001/connection/websocket", {
token: token,
debug: true,
});

// Add event listeners
centrifuge.on("connected", (ctx) => {
console.log("Connected to Centrifuge:", ctx);
});

centrifuge.on("disconnected", (ctx) => {
console.log("Disconnected from Centrifuge:", ctx.reason);
});

centrifuge.on("error", (err) => {
console.error("Centrifuge error:", err);
});
} else {
centrifuge.setToken(token);
centrifuge.connect(); // Reconnect with the new token
}
} catch (error) {
console.error("Error initializing Centrifuge:", error);
}
};

// Function to get the existing Centrifuge instance
export const getCentrifugeInstance = (): Centrifuge | null => {
if (!centrifuge) {
initCentrifuge(); // Ensure Centrifuge is initialized
}
return centrifuge;
};

// Function to explicitly connect Centrifuge
export const connectCentrifuge = () => {
const centrifuge = getCentrifugeInstance();
if (centrifuge && centrifuge.state !== "connected") {
centrifuge.connect();
console.log("Connected to Centrifuge");
centrifuge.newSubscription("occupi-counter").subscribe();
console.log("Connected to channel: occupi-counter");
}
};

// Function to explicitly disconnect Centrifuge
export const disconnectCentrifuge = () => {
if (centrifuge) {
centrifuge.disconnect();
}
};

// Define specific types for handlers
interface SubscriptionHandlers {
onPublication?: (ctx: PublicationContext) => void;
onSubscribed?: (ctx: SubscribedContext) => void; // Correct type for onSubscribed
onError?: (ctx: SubscriptionErrorContext) => void; // Correct type for onError
}

// Function to subscribe to a channel with duplicate subscription prevention
export const subscribeToChannel = (
channelName: string,
handlers: SubscriptionHandlers
): Subscription | undefined => {
const centrifuge = getCentrifugeInstance();

// Check if already subscribed to the channel
if (subscriptions[channelName]) {
console.warn(`Already subscribed to channel: ${channelName}`);
return subscriptions[channelName];
}

// Create a new subscription
const subscription = centrifuge?.newSubscription(channelName);
console.log(`Creating subscription to channel: ${channelName}`);
// Attach provided event handlers to the subscription
if (handlers?.onPublication) {
subscription?.on("publication", handlers.onPublication);
}

if (handlers?.onSubscribed) {
subscription?.on("subscribed", handlers.onSubscribed);
}

if (handlers?.onError) {
subscription?.on("error", handlers.onError);
}

// Store the subscription in the map to prevent duplicate subscriptions
subscriptions[channelName] = subscription;

// Activate the subscription
subscription?.subscribe();
console.log(`Subscribed to channel: ${channelName}`);
return subscription;
};

// Export initCentrifuge to be called as needed, such as on app startup
export default initCentrifuge;
99 changes: 99 additions & 0 deletions frontend/occupi-web/src/CentrifugoService.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
// centrifugeSingleton.js
import { Centrifuge } from "centrifuge";
import AuthService from "./AuthService"; // Adjust the path as necessary

let centrifuge = Centrifuge :| null;
const subscriptions = {}; // Object to track active subscriptions

// Function to initialize or update Centrifuge with a new token
const initCentrifuge = async () => {
try {
const response = await AuthService.getToken();
const token = response.token;

if (!centrifuge) {
centrifuge = new Centrifuge("ws://localhost:8001/connection/websocket", {
token: token,
debug: true,
});

// Add connection event listeners
centrifuge.on("connected", (ctx) => {
console.log("Connected to Centrifuge:", ctx);
});

centrifuge.on("disconnected", (ctx) => {
console.log("Disconnected from Centrifuge:", ctx.reason);
});

centrifuge.on("error", (err) => {
console.error("Centrifuge error:", err);
});
} else {
centrifuge.setToken(token);
centrifuge.connect();
}
} catch (error) {
console.error("Error initializing Centrifuge:", error);
}
};

// Function to get the Centrifuge instance, ensuring only one instance exists
export const getCentrifugeInstance = () => {
if (!centrifuge) {
initCentrifuge();
}
return centrifuge;
};

// Function to subscribe to a channel with duplicate subscription prevention
export const subscribeToChannel = (channelName, handlers) => {
const centrifuge = getCentrifugeInstance();

// Check if already subscribed to the channel
if (subscriptions[channelName]) {
console.warn(`Already subscribed to channel: ${channelName}`);
return subscriptions[channelName];
}

// Create a new subscription
const subscription = centrifuge.newSubscription(channelName);

// Attach provided event handlers to the subscription
if (handlers?.onPublication) {
subscription.on("publication", handlers.onPublication);
}

if (handlers?.onSubscribed) {
subscription.on("subscribed", handlers.onSubscribed);
}

if (handlers?.onError) {
subscription.on("error", handlers.onError);
}

// Store the subscription in the map to prevent duplicate subscriptions
subscriptions[channelName] = subscription;

// Activate the subscription
subscription.subscribe();
console.log(`Subscribed to channel: ${channelName}`);
return subscription;
};

// Function to explicitly connect Centrifuge
export const connectCentrifuge = () => {
const centrifuge = getCentrifugeInstance();
if (centrifuge && centrifuge.state !== "connected") {
centrifuge.connect();
}
};

// Function to explicitly disconnect Centrifuge
export const disconnectCentrifuge = () => {
if (centrifuge) {
centrifuge.disconnect();
}
};

export default initCentrifuge;
Loading

0 comments on commit 153cba9

Please sign in to comment.