correct-apricot
correct-apricot5mo ago

Infinite websocket call on custom liveProvider implementation with socket.io

import { LiveProvider } from "@refinedev/core";
import { Socket } from "socket.io-client";

type ListenerType = {
type: string;
payload: { ids: string[] };
date: Date;
channel: string;
};

const liveProvider: (socket: Socket) => LiveProvider = (socket) => ({
subscribe({ channel, types, params, callback }) {
const eventName = generateEventName(channel, types);

const listener = (data: ListenerType) => {
if (types.includes("*") || types.includes(data.type)) {
if (
data.type !== "created" &&
params?.ids !== undefined &&
data.payload?.ids !== undefined
) {
if (
params.ids.filter((value) =>
data.payload.ids.includes(value as string)
).length > 0
) {
callback(data);
}
} else {
callback(data);
}
}
};
socket.on(eventName, listener);
return { eventName, listener };
},
unsubscribe({
eventName,
listener,
}: {
eventName: string;
listener: () => void;
}) {
console.log("ubsub");
socket.off(eventName, listener);
},
publish(event) {
// socket.emit(generateEventName(event.channel, event.type), event.payload);
},
});

const generateEventName = (channel: string, type: string | string[]) => {
const channelName = channel.replace("resources/", "");
return `database.table.${channelName}.${type}`;
};

export default liveProvider;
import { LiveProvider } from "@refinedev/core";
import { Socket } from "socket.io-client";

type ListenerType = {
type: string;
payload: { ids: string[] };
date: Date;
channel: string;
};

const liveProvider: (socket: Socket) => LiveProvider = (socket) => ({
subscribe({ channel, types, params, callback }) {
const eventName = generateEventName(channel, types);

const listener = (data: ListenerType) => {
if (types.includes("*") || types.includes(data.type)) {
if (
data.type !== "created" &&
params?.ids !== undefined &&
data.payload?.ids !== undefined
) {
if (
params.ids.filter((value) =>
data.payload.ids.includes(value as string)
).length > 0
) {
callback(data);
}
} else {
callback(data);
}
}
};
socket.on(eventName, listener);
return { eventName, listener };
},
unsubscribe({
eventName,
listener,
}: {
eventName: string;
listener: () => void;
}) {
console.log("ubsub");
socket.off(eventName, listener);
},
publish(event) {
// socket.emit(generateEventName(event.channel, event.type), event.payload);
},
});

const generateEventName = (channel: string, type: string | string[]) => {
const channelName = channel.replace("resources/", "");
return `database.table.${channelName}.${type}`;
};

export default liveProvider;
and server returns this data created:
{
channel: eventName,
type: 'created',
payload: { ids: [event.entity.id] },
date: new Date()
}
{
channel: eventName,
type: 'created',
payload: { ids: [event.entity.id] },
date: new Date()
}
deleted:
{
channel: eventName,
type: 'deleted',
payload: { ids: [event.entityId] },
date: new Date()
}
{
channel: eventName,
type: 'deleted',
payload: { ids: [event.entityId] },
date: new Date()
}
updatec:
{
channel: eventName,
type: 'updated',
payload: { ids: [event.entity?.id] },
date: new Date()
}
{
channel: eventName,
type: 'updated',
payload: { ids: [event.entity?.id] },
date: new Date()
}
query:
{
channel: eventName,
type: '*',
payload: { success: event.success },
date: new Date()
}
{
channel: eventName,
type: '*',
payload: { success: event.success },
date: new Date()
}
5 Replies
kapa.ai
kapa.ai5mo ago
Hi @Onder. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave: ---------------------- To implement a custom liveProvider using socket.io for your refine application, you can follow the structure provided in your question. Below is a refined version of your implementation, ensuring it aligns with the refine framework's requirements for a LiveProvider. Custom liveProvider Implementation with socket.io
import { LiveProvider } from "@refinedev/core";
import { Socket } from "socket.io-client";

type ListenerType = {
type: string;
payload: { ids: string[] };
date: Date;
channel: string;
};

const liveProvider: (socket: Socket) => LiveProvider = (socket) => ({
subscribe({ channel, types, params, callback }) {
const eventName = generateEventName(channel, types);

const listener = (data: ListenerType) => {
if (types.includes("*") || types.includes(data.type)) {
if (
data.type !== "created" &&
params?.ids !== undefined &&
data.payload?.ids !== undefined
) {
if (
params.ids.filter((value) =>
data.payload.ids.includes(value as string)
).length > 0
) {
callback(data);
}
} else {
callback(data);
}
}
};
socket.on(eventName, listener);
return { eventName, listener };
},
unsubscribe({
eventName,
listener,
}: {
eventName: string;
listener: () => void;
}) {
socket.off(eventName, listener);
},
publish(event) {
// socket.emit(generateEventName(event.channel, event.type), event.payload);
},
});

const generateEventName = (channel: string, type: string | string[]) => {
const channelName = channel.replace("resources/", "");
return `database.table.${channelName}.${type}`;
};

export default liveProvider;
import { LiveProvider } from "@refinedev/core";
import { Socket } from "socket.io-client";

type ListenerType = {
type: string;
payload: { ids: string[] };
date: Date;
channel: string;
};

const liveProvider: (socket: Socket) => LiveProvider = (socket) => ({
subscribe({ channel, types, params, callback }) {
const eventName = generateEventName(channel, types);

const listener = (data: ListenerType) => {
if (types.includes("*") || types.includes(data.type)) {
if (
data.type !== "created" &&
params?.ids !== undefined &&
data.payload?.ids !== undefined
) {
if (
params.ids.filter((value) =>
data.payload.ids.includes(value as string)
).length > 0
) {
callback(data);
}
} else {
callback(data);
}
}
};
socket.on(eventName, listener);
return { eventName, listener };
},
unsubscribe({
eventName,
listener,
}: {
eventName: string;
listener: () => void;
}) {
socket.off(eventName, listener);
},
publish(event) {
// socket.emit(generateEventName(event.channel, event.type), event.payload);
},
});

const generateEventName = (channel: string, type: string | string[]) => {
const channelName = channel.replace("resources/", "");
return `database.table.${channelName}.${type}`;
};

export default liveProvider;
Explanation 1. Subscribe Method: - The subscribe method listens to events from the server using socket.on. - It filters events based on the types and params provided. - The callback function is called when an event matches the criteria. 2. Unsubscribe Method: - The unsubscribe method stops listening to events using socket.off. 3. Generate Event Name: - The generateEventName function constructs the event name based on the channel and type. Server Data Format Ensure your server sends data in the following format for different event types: - Created:
{
channel: eventName,
type: 'created',
payload: { ids: [event.entity.id] },
date: new Date()
}

{
channel: eventName,
type: 'created',
payload: { ids: [event.entity.id] },
date: new Date()
}

- Deleted:
{
channel: eventName,
type: 'deleted',
payload: { ids: [event.entityId] },
date: new Date()
}

{
channel: eventName,
type: 'deleted',
payload: { ids: [event.entityId] },
date: new Date()
}

- Updated:
{
channel: eventName,
type: 'updated',
payload: { ids: [event.entity?.id] },
date: new Date()
}

{
channel: eventName,
type: 'updated',
payload: { ids: [event.entity?.id] },
date: new Date()
}

- Query:
{
channel: eventName,
type: '*',
payload: { success: event.success },
date: new Date()
}

{
channel: eventName,
type: '*',
payload: { success: event.success },
date: new Date()
}

Additional Resources For more information on implementing a LiveProvider and handling real-time updates in refine, refer to the following documentation: - Live Provider Documentation (https://refine.dev/docs/realtime/live-provider/) - [useInfiniteList Hook](https://refine.dev/docs/data/hooks ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai5mo ago
<@238969575289389057> kapa.ai is still learning and improving, please let us know how it did by reacting below
correct-apricot
correct-apricotOP5mo ago
@kapa.ai you don't have a clue. the refine always make ws calls almost 50 per second when i write it on console, i couldn't understand the reason
kapa.ai
kapa.ai5mo ago
Let me check the knowledge base for you. One moment! :books: ---------------------- Hmm, I don't know enough to give you a confident answer yet. However, I can provide some guidance based on the information available. Potential Causes and Solutions 1. Development Environment Behavior: - In development environments, it's common to see repeated API calls or network errors. This is often due to the way development servers handle hot reloading and other development-specific features. - Refer to the FAQ on API calls triggering twice (https://refine.dev/docs/faq/#why-are-api-calls-triggering-twice) for more details. 2. WebSocket Configuration: - Ensure that your WebSocket configuration is correct and that you are not inadvertently creating multiple connections. Each subscribe call should ideally create a single WebSocket connection. 3. Debugging Tips: - Check your WebSocket server logs to see if multiple connections are being established. - Use browser developer tools to monitor WebSocket connections and messages. 4. Refine's LiveProvider: - Make sure your liveProvider implementation is not causing multiple subscriptions unintentionally. Review the subscribe and unsubscribe methods to ensure they are correctly managing WebSocket connections. Example Debugging Steps 1. Check WebSocket Connections:
console.log(socket.connected); // Should be true if connected
console.log(socket.id); // Unique identifier for the socket connection

console.log(socket.connected); // Should be true if connected
console.log(socket.id); // Unique identifier for the socket connection

2. Monitor Network Activity: - Use the Network tab in browser developer tools to monitor WebSocket connections and messages. 3. Review Server Logs: - Ensure that your server is not broadcasting messages too frequently or to unintended clients. If the problem persists, you might want to reach out to the refine community for more specific help: - GitHub Issues (https://github.com/refinedev/refine/issues) - Discord Community (https://discord.gg/refine) For more detailed guidance, you can refer to the Live Provider Documentation (https://refine.dev/docs/realtime/live-provider/). If you have any specific error messages or logs, sharing those might help in diagnosing the issue further. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai5mo ago
<@238969575289389057> kapa.ai is still learning and improving, please let us know how it did by reacting below

Did you find this page helpful?