QueueEvents don't trigger with BullMQ using Heroku Redis - javascript

I'm trying to implement a queue in NodeJS using BullMQ but i have some issues in production when trying to use a remote Redis (Heroku Redis or Redis Cloud).
In local, everything work well but when i try to use a REDIS_URL, a job is created but events doesn't work.
Here is the code:
// test_job.js
import { Queue, Worker, QueueEvents } from "bullmq";
import IORedis from "ioredis";
import Dotenv from "dotenv";
Dotenv.config();
// Good
const connection = new IORedis(process.env.REDIS_URL || 6379);
// Good
const queue = new Queue("Paint", { connection });
// Good
const worker = new Worker(
"Paint",
async job => {
if (job.name === "cars") {
console.log(job.data.color);
}
},
{ connection }
);
/**
* BUG HERE: Events work in local but not when using a remote Redis (REDIS_URL)
*/
const queueEvents = new QueueEvents("Paint");
queueEvents.on("completed", jobId => {
console.log("done painting");
});
queue.add("cars", { color: "blue" });

const queueEvents = new QueueEvents("Paint", { connection: connection.duplicate() });
https://github.com/taskforcesh/bullmq/issues/173

Related

Subscribing to Azure Pub Sub web service from react causes Unhandled Rejection (TypeError)

Based on the official documentation, i am able to get the subscribed messages. When i simply run the javascript code, it runs without any error.
const WebSocket = require('ws');
const { WebPubSubServiceClient } = require('#azure/web-pubsub');
async function main() {
const hub = "hub1";
let service = new WebPubSubServiceClient(process.env.WebPubSubConnectionString, hub);
let token = await service.getClientAccessToken();
let ws = new WebSocket(token.url);
ws.on('open', () => console.log('connected'));
ws.on('message', data => console.log('Message received: %s', data));
}
main();
But when i try to do this within React class's, componentDidMount() function, facing error.
import React from "react";
// == Azure WebPuSub
// import { WebPubSubServiceClient } from '#azure/web-pubsub';
// import { WebSocket } from 'ws';
const { WebPubSubServiceClient } = require('#azure/web-pubsub');
const WebSocket = require('ws');
class AzurePubSubTest extends React.Component {
constructor(_props, _context) {
super(_props, _context);
this.connectToPubSub = this.connectToPubSub.bind(this);
this.state = {
}
}
async componentDidMount() {
console.log("===Mounting....")
await this.connectToPubSub();
}
componentWillUnmount() {
console.log("Unmounting....")
}
async connectToPubSub() {
const hub = "hub1";
let endpoint;
// endpoint = process.env.WebPubSubConnectionString;
endpoint = "Endpoint=https://***check.webpubsub.azure.com;AccessKey=***;Version=1.0;"
// endpoint = "wss://***check.webpubsub.azure.com/client/hubs/Hub?access_token=***";
console.log("process.env.WebPubSubConnectionString");
console.log(endpoint);
let service = new WebPubSubServiceClient(endpoint, hub);
let token = await service.getClientAccessToken();
let ws = new WebSocket(token.url);
ws.on('open', () => console.log('connected'));
ws.on('message', data => console.log('Message received: %s', data));
}
render() {
const user = { username: "Check" };
let testMessages = [];
if (testMessages === undefined || testMessages === null) {
testMessages = [];
}
return (
<div>Testing....</div>
)
}
}
export default AzurePubSubTest;
× Unhandled Rejection (TypeError): Right-hand side of 'instanceof' is
not an object
Stacktrace 1
Stacktrace 2
Stacktrace 3
The issue here is with the Jsonwebtoken package which is used with the websocket.
Jsonwebtoken is predominantly build for NodeJS to be run on a web server so it doesn't fully work with the client-side rendering of the react apps
try installing the latest version of jsonwebtoken , otherwise the ideal way of working would be with an intermediary between the react app and azure pub sub.
One workaround with this approach would be with azure function with azure web pub sub input/output bindings. and then use a WebSocket in the react app to connect to the azure function.
Here you will need a HTTP trigger with the input bindings of the azure pub sub . This trigger will return the URL which you can use in web sockets of your react app.
function.json (for http trigger) :
{
"bindings":[
{
"authLevel": "anonymous",
"type": "httpTrigger",
"direction": "in",
"name": "req"
},
{
"type": "http",
"direction": "out",
"name": "res"
},
{
"type": "webPubSubConnection",
"name": "connection",
"hub": "notification",
"direction": "in"
}
]
}
Here I am sending the message using a time trigger and in a simple HTML file I created a WebSocket the html file which is served using different HTTP trigger. Thus after every interval of time I will get messages

How to connect any server using ssh in Cypress.io to run a command?

I know that this probably is not the best way to do this. I read the question with the same title here, but it not solve my problem.
The question is: I have a server that only will achieve a result that I wanna if I run a command line in the server. So I wanna write a test to check the state of one page before and after I run that command. How I do that?
I tried to use the simple-ssh package, but I keep getting this error while trying to read the ssh key file:
fs.readFileSync is not a function
Actually my code looks like this:
import * as fs from 'fs';
let sshConfig = Cypress.config('ssh')
sshConfig.key = fs.readFileSync('path/to/key/file')
let SSH = require('simple-ssh');
Cypress.Commands.add('teste', () => {
let ssh = new SSH(sshConfig)
ssh.exec('echo', {
args: ['$PATH'],
out: function(stdout) {
console.log(stdout);
}
}).start();
})
Other possibility's are welcome.
As Fody mentioned, there are node.js functions present inside simple-ssh so a task is needed.
This is the basic configuration.
It's a direct translation of what you have, but you would want to return something from the task. As it is, the console.log() goes to the terminal console not the browser console.
cypress.config.js
const { defineConfig } = require('cypress')
const fs = require('fs')
const SSH = require('simple-ssh');
module.exports = defineConfig({
e2e: {
setupNodeEvents(on, config) {
on('task', {
ssh() {
const sshConfig = config.ssh
sshConfig.key = fs.readFileSync('path/to/key/file')
const ssh = new SSH(sshConfig)
ssh.exec('echo', {
args: ['$PATH'],
out: function(stdout) {
console.log(stdout);
}
}).start();
return null
},
})
}
}
})
test
Cypress.Commands.add('ssh', () => {
cy.task('ssh')
})
cy.ssh()
Try it with cy.readFile().
const SSH = require('simple-ssh');
Cypress.Commands.add('testSSH', () => {
cy.readFile('path/to/key/file').then(key
const sshConfig = Cypress.config('ssh')
sshConfig.key = key
const ssh = new SSH(sshConfig)
ssh.exec('echo', {
args: ['$PATH'],
out: function(stdout) {
console.log(stdout);
}
}).start()
})
})
The problem is fs is a node.js library, and it cannot be used in the browser.
But you may find the same thing applies to simple-ssh, If so, you will have to shift the code into a task where you can use any node.js functions.

Hooks.js running the db connection and results twice in sveltekit

I'm using sveltekit and trying to understand all the new features added after retiring Sapper. One of those new features is hooks.js which runs on the server and not accessible to the frontend. It makes dealing with db safe. So I created a connection to my mongodb to retrieve user's data before I use the db results in my getSession function. It works but I noticed that it access my database TWICE. Here is my hooks.js code:
import * as cookie from 'cookie';
import { connectToDatabase } from '$lib/mongodb.js';
export const handle = async ({event, resolve})=>{
const dbConnection = await connectToDatabase();
const db = dbConnection.db;
const userinfo = await db.collection('users').findOne({ username: "a" });
console.log("db user is :" , userinfo) //username : John
const response = await resolve(event)
response.headers.set(
'set-cookie', cookie.serialize("cookiewithjwt", "sticksafterrefresh")
)
return response
}
export const getSession = (event)=>{
return {
user : {
name : "whatever"
}
}
}
The console.log you see here returns the user data twice. One as soon as I fire up my app at localhost:3000 with npm run dev and then less than a second, it prints another console log with the same information
db user is : John
a second later without clicking on anything a second console.log prints
db user is : John
So my understanding from the sveltekit doc is that hooks.js runs every time SvelteKit receives a request. I removed all prerender and prefetch from my code. I made sure I only have the index.svelte in my app but still it prints twice. My connection code I copied from an online post has the following:
/**
* Global is used here to maintain a cached connection across hot reloads
* in development. This prevents connections growing exponentially
* during API Route usage.
*/
Here is my connection code:
import { MongoClient } from 'mongodb';
const mongoURI ="mongodb+srv://xxx:xxx#cluster0.qjeag.mongodb.net/xxxxdb?retryWrites=true&w=majority";
const mongoDB = "xxxxdb"
export const MONGODB_URI = mongoURI;
export const MONGODB_DB = mongoDB;
if (!MONGODB_URI) {
throw new Error('Please define the mongoURI property inside config/default.json');
}
if (!MONGODB_DB) {
throw new Error('Please define the mongoDB property inside config/default.json');
}
/**
* Global is used here to maintain a cached connection across hot reloads
* in development. This prevents connections growing exponentially
* during API Route usage.
*/
let cached = global.mongo;
if (!cached) {
cached = global.mongo = { conn: null, promise: null };
}
export const connectToDatabase = async() => {
if (cached.conn) {
return cached.conn;
}
if (!cached.promise) {
const opts = {
useNewUrlParser: true,
useUnifiedTopology: true
};
cached.promise = MongoClient.connect(MONGODB_URI).then((client) => {
return {
client,
db: client.db(MONGODB_DB)
};
});
}
cached.conn = await cached.promise;
return cached.conn;
So my question is : is hooks.js runs twice all the time, one time on the server and one time on the front? If not, then why the hooks.js running/printing twice the db results in my case?
Anyone?

node Mqtt.js structuring code / best practices

So I've been searching for a long time on mqtt.js examples for structuring and best practices and haven't found anything worthwhile. thus [main] how do you structure your mqtt.js code in your node/express application?
[1] So the libraries mqttjs/async-MQTT provides some example on connecting and on-message but on a real app with lots of subscription and publishes how to structure code so that it initiliazes on the app.js and uses the same client (return from the mqtt.connect) for all the sub/pub in different files.
[2] and from the question[1] should my app only use 1 client for all the works or can use multiple clients as needed on multiple files (let's say I have 3 files mqttInit, subscriber, publisher. so if I use the init on subscriber and get a client should I export it or just make a new instance of a client on the publisher file)
[3] so the mqttjs API provides only an onMessage function so all subscribed topics message gets here thus I put a switch or a if else to manage this so if we have a lot of topics how do you manage this
[4] so my current setup is kind of messed up
this is the initializer file lets say'
mqttService.js
const mqtt = require("mqtt");
const { readFileSync } = require("fs");
module.exports = class mqttService {
constructor() {
this.client = mqtt.connect("mqtt://xxxxxxxxxxx", {
cert: readFileSync(process.cwd() + "/certificates/client.crt"),
key: readFileSync(process.cwd() + "/certificates/client.key"),
rejectUnauthorized: false,
});
this.client.on("error", (err) => {
console.log(err);
});
this.client.once("connect", () => {
console.log("connected to MQTT server");
});
}
};
subscriber.js
this is the function(subscribe()) that I call in app.js to init the mqtt thing
const { sendDeviceStatus, sendSensorStatus } = require("../socketApi");
const { client } = new (require("./mqttService"))();
function subscribe() {
let state = {
timer: false,
};
...
let topics = {
....
},
client.subscribe([...]);
client.on("message", async (topic, buffer) => {
if (topic) {
...
}
});
}
module.exports = {
subscribe,
client,
};
publish.js
const { AsyncClient } = require("async-mqtt");
const _client = require("./subscribe").client;
const client = new AsyncClient(_client);
async function sendSensorList(daqId) {
let returnVal = await client.publish(
`${daqId}-GSL-DFC`,
JSON.stringify(publishObject),
{ qos: 1 }
);
console.log(returnVal);
return publishObject;
}
.....
module.exports = {
sendSensorList,
.......
};
so as you can see from the above code everything is kind of linked with one another and messed up thus I need some expo on how you structure code
thanks for reading, please feel free to provide any info and any info is much appreciated

How to connect VPN using nodejs in ubuntu

I have the code in my nodejs file which gives me the following information
host:"147.0.40.145"
method:"aes-256-cfb"
password:"9c359ad1ebeec200"
port:38473
I need to use above information and want to connect VPN through it. I have used below code to extract the above information.
const connectServer = (serverId) => {
const token = store('access_token')
httpOptions.Authorization = token.token_type+' '+token.access_token
return new Promise((resolve, reject) => {
const response = await axios.post(`${baseUrl}/servers/${serverId}/connect`, {'serverId':serverId},{headers: httpOptions})
console.log(response.data)
resolve(response.data)
})
}
So I need to know whether it is possible using nodejs to connect or create VPN?
Thank you in advance!!!
Install this npm
npm i node-openvpn --save
const openvpnmanager = require('node-openvpn');
const opts = {
host: '147.0.40.145',
port: 38473,
timeout: 1500, //timeout for connection - optional, will default to 1500ms if undefined
logpath: 'log.txt' //optional write openvpn console output to file, can be relative path or absolute
};
const auth = {
user: '{{add user name}}',
pass: '9c359ad1ebeec200',
};
const openvpn = openvpnmanager.connect(opts)
openvpn.on('connected', () => {
console.log("Connected to VPN successfully...");
});
For more info , please read this link
Another option
Link

Categories