Vue-Socket Mutation Listener - vue.js

I recently changed over to connecting to a namespace on the socket.
Previously the connection was working fine and my Vuex mutations were catching the emission from the server.
After switching to the namespace I have verified that the connection is being made and the correct event is firing on the socket, but my Vuex mutation is no longer firing.
Here is the applicable code:
Server Side
const complianceNamespace = IO.of("/compliance");
complianceNamespace.on("connection", function (socket) {
socket.on("UPDATE_REQUEST_SERVICE", function (requestService) {
IO.emit("UPDATE_REQUEST_SERVICE", requestService);
});
socket.on("ADD_REQUEST_SERVICE", function (requestService) {
IO.emit("ADD_REQUEST_SERVICE", requestService)
});
});
Client Side
const SocketInstance = process.env.NODE_ENV === 'development' ? socketio('http://localhost:3001/compliance') : socketio('https://real.address.com/compliance');
Vue.use(new VueSocketIO({
debug: false,
connection: SocketInstance,
vuex: {
store,
actionPrefix: 'SOCKET_',
mutationPrefix: 'SOCKET_'
}
}));
// Mutation
SOCKET_UPDATE_REQUEST_SERVICE(state, requestService) {
// some code runs
}
Again, I have verified that the socket is getting to UPDATE_REQUEST_SERVICE, but the mutation is never being run when the socket emits, it worked when not using namespace.
I am thinking that the prefix is altered or doesn't work when using a namespace?

Answer: mistake within the namespace connection event listeners.
I was setting up a connection with the namespace (complianceNamespace) then emitting events to a different connection (IO).
Correction code:
complianceNamespace.on("connection", (socket) => {
socket.on("SOME_EVENT", function(user) {
complianceNamespace.emit("SOME_EVENT", user);
}
});

Related

vue-socket.io fail to trigger event when url route is present

I have a Python Flask backend that listens at port 8000 (at '/') and keeps emitting digest event after receiving a connection. At the Vue frontend, I setup the connection as
Vue.use(
new VueSocketIO({
debug: false,
connection: "http://localhost:8000",
})
);
and in a component, I have
sockets: {
connect() {
console.log('connected');
},
afterConnect(data) {
console.log(data);
},
// get digest from backend
digest(data) {
console.log(data)
},
}
The digest function here will be triggered correctly.
However, when I change the setup to
Vue.use(
new VueSocketIO({
debug: false,
connection: "http://localhost:8000/abc", // add whatever route here
})
);
I can still receive correct data packets through the socket, but digest function is simply not triggered. The abc in the route can be anything, it won't break the connection.
Any help is appreciated! Thanks!

Is there any way in Nuxt3 to load a plugin once?

I'm trying to integrate Sequelize to my Nuxt 3 project. However, I couldn't figure out how to make it load only once instead of reloading it every time the page was refreshed / navigating to another routes.
I couldn't find any information on the docs. Is it even possible?
~/plugins/sequelize.server.ts
import { Sequelize } from "sequelize"
export default defineNuxtPlugin(async (nuxtApp) => {
const config = useRuntimeConfig()
const sequelize = new Sequelize(config.dbName, config.dbUser, config.dbPass,{
host: config.dbHost,
port: parseInt(config.dbPort),
dialect: 'mysql',
})
try {
await sequelize.authenticate()
// this log was executed every time I navigate to a new route
// or refreshing the browser.
console.log('Connection has been established successfully.');
} catch (error) {
console.error('Unable to connect to the database:', error);
}
return {
provide: {
db: sequelize
}
}
})
OP solved his issue by removing a composable that was initialized on a component's mounted lifecycle hook.
Just a remaining piece of code.

VueSocketIO offer fallback connection url

I am using Vuetify together with Vuex and VueSocketIO for my WebApp and here is an example Part of the code:
Vue.use(new VueSocketIO({
reconnection: true,
debug: true,
connection: SocketIO(`http://${process.env.ip}:4000`),
vuex: {
store,
actionPrefix: 'SOCKET_',
},
}));
If I understand it correctly, using Vuex and VueSocketIO together makes it only possible to use one Socket like this at the same time.
In some cases Vue might not be able to connect to the socket specified at connection.
I was wondering if there was a possibility to first let Vue try to connect to one socket (also with some number of reconnection attempts) but to switch to another connection value and try with that one afterwards as a fallback?
Thank you in advance!
Final solution
const options = {
reconnection: true,
reconnectionAttempts: 2,
reconnectionDelay: 10,
reconnectionDelayMax: 1,
timeout: 300,
};
let connection = new SocketIO(`http://${process.env.ip}:4000`, options);
const instance = new VueSocketIO({
debug: true,
connection,
vuex: {
store,
actionPrefix: 'SOCKET_',
},
options,
});
const options2 = {
reconnection: true,
reconnectionAttempts: 4,
};
connection.on('reconnect_failed', () => {
connection = new SocketIO(`http://${process.env.fallback}:4000`, options2);
instance.listener.io = connection;
instance.listener.register();
Vue.prototype.$socket = connection;
});
To specify the number of reconnection attempts you can set reconnectionAttempts option.
Example Code:
const url = `http://${process.env.ip}:4000`
const options = {
reconnectionAttempts: 3
}
Vue.use(new VueSocketIO({
debug: true,
connection: new SocketIO(url, options),
vuex: { ... }
}))
But switching to another connection is not easy as both of vue-socket.io and socket.io-client it was not designed for that.
First we have to listen on reconnect_failed event which will fires when reconnection attempts is exceeded.
Then we have to create a new connection to connect to the fallback url.
The VueSocketIO instance have two important properties which emitter and listener we cannot create the new emitter since it might already used in some components (with subscribe function) so we have to use old emitter but new listener.
Unfortunately, we cannot import Listener class directly from vue-socket.io package. So we have to use old listener but change the io property to the new connection then manually call register method.
Binding Vue.prototype.$socket to the new connection for the future use.
Example Code:
const url = `http://${process.env.ip}:4000`
const fallbackUrl = `http://${process.env.ip}:4001`
const options = {
reconnectionAttempts: 3
}
const connection = new SocketIO(url, options)
const instance = new VueSocketIO({
debug: true,
connection,
vuex: {
store,
actionPrefix: 'SOCKET_'
},
options
})
connection.on('reconnect_failed', error => {
const connection = new SocketIO(fallbackUrl, options)
instance.listener.io = connection
instance.listener.register()
Vue.prototype.$socket = connection;
})
Vue.use(instance)

502 Bad Gateway in Kubernetes cluster after I added mongoDB connection code

I was chugging along with my Kubernetes cluster project when after creating a User model to start creating users in my application, I get a 502 Bad Gateway error in my Postman client.
So I was so focused on my ingress-nginx yaml file, staring at it for typos, rewriting it, uninstalling, reinstalling and still getting that error, that I decided to take it the next step further.
Via the current user route handler:
import express from "express";
const router = express.Router();
router.get("/api/users/currentuser", (req, res) => {
res.send("howdy!");
});
export { router as currentUserRouter };
I have always been able to go to my browser and successfully see howdy! rendered when I went to mywebsite.com/api/users/currentuser
but then I added some logic to index.ts file I did not particular care for from the https://expressjs.com/en/guide/routing.html:
app.all("*", async (req, res) => {
throw new NotFoundError();
});
Well, sure enough that killed my ability to go to mywebsite.com/api/users/currentuser and see howdy! rendered and instead I was getting a 502 Bad Gateway. So I said okay I will just leave that one out then.
But then I noticed a huge chunk of very important code was breaking my ability to visit that url as well:
// const start = async () => {
// try {
// await mongooose.connect("mongodb://auth-mongo-srv:27017/auth", {
// useNewUrlParser: true,
// useUnifiedTopology: true,
// useCreateIndex: true,
// });
// console.log("Connected to MongoDB");
// } catch (error) {
// app.listen(3000, () => {
// console.log("Listening on port 3000!!!!!");
// });
// }
// };
// start();
All of the above is what I need to connect to my local MongoDB server and start creating users.
So I started to even get more granular and slowly commenting code back in. Well, the app.all() is not a problem anymore, the problem seems to be throwing my mongoDB connection code inside of a try/catch statement, but I have no idea why that would have created the problem. Any ideas anyone?
So instead if I just run it like this:
const start = async () => {
await mongooose.connect("mongodb://auth-mongo-srv:27017/auth", {
useNewUrlParser: true,
useUnifiedTopology: true,
useCreateIndex: true,
});
console.log("Connected to MongoDB");
app.listen(3000, () => {
console.log("Listening on port 3000!!!!!");
});
};
start();
It all works fine again.

Sending an action from within a socket.io event in a saga

I am trying to make my login flow work using socket.io and redux-saga.
There is no problem making the socket connection and validating the user, but when I try to dispatch an action from the "loginSuccess"-event, nothing is happening
The login saga looks like this:
import { takeLatest, call, put, take } from "redux-saga/effects";
import * as types from "../actions/types";
import connect from "../constants/socketConnection";
function* doLogin(action) {
const socket = yield call(connect);
socket.emit("login", {
username: action.username,
password: action.password
});
socket.on("loginSuccess", (response) => {
yield put({type: types.SET_CURRENT_USER, currentUser: response.user})
});
}
export function* login() {
yield takeLatest(types.LOGIN, doLogin);
}
Is it not possible to send an action from within a socket.on()?
The syntax is correct (it works in my other projects), but VS code says that the "put" and "response" are never used and Prettier cannot auto format when the put is there, so it is not registered. No errors are showing though.