SQS messages are coming back to DLQ? - javascript

I have written the following script to move messages from DLQ to MainQ.
'use strict'
import { readFileSync } from "fs";
import {
DeleteMessageCommand,
SQSClient,
GetQueueUrlCommand,
SendMessageCommand,
ReceiveMessageCommand,
GetQueueAttributesCommand
} from '#aws-sdk/client-sqs';
const REGION = 'us-east-1';
const sqs = new SQSClient({ region: REGION });
async function getMessageCount(queueUrl) {
const params = { AttributeNames: ['ApproximateNumberOfMessages'], QueueUrl: queueUrl };
try {
const data = await sqs.send(new GetQueueAttributesCommand(params));
// console.log(data);
return data.Attributes.ApproximateNumberOfMessages;
} catch (err) {
console.error(err);
}
}
async function reprocessMessages(dlqQueue, mainQueue) {
try {
const response1 = await sqs.send(new GetQueueUrlCommand({ QueueName: dlqQueue }));
const response2 = await sqs.send(new GetQueueUrlCommand({ QueueName: mainQueue }));
const dlqQueueUrl = response1.QueueUrl;
const mainQueueUrl = response2.QueueUrl;
const messageCount = await getMessageCount(dlqQueueUrl);
console.log(`Message count ${messageCount}`);
const visibiltyTimeout = Math.ceil(messageCount / 100) * 2;
let count = 0;
while (count <= 50) {
count += await moveMessage(mainQueueUrl, dlqQueueUrl, 5);
}
console.log(`Moved ${count} messages`);
return "Completed";
} catch (err) {
console.error(err);
}
}
async function moveMessage(mainQueueUrl, dlqQueueUrl, visibiltyTimeout) {
try {
const receiveMessageParams = {
MaxNumberOfMessages: 9,
MessageAttributeNames: ['All'],
QueueUrl: dlqQueueUrl,
VisibilityTimeout: visibiltyTimeout,
WaitTimeSeconds: 1
};
const receiveData = await sqs.send(new ReceiveMessageCommand(receiveMessageParams));
// console.log(receiveData);
if (!receiveData.Messages) {
// console.log("finished");
return 0;
}
const messages = [];
receiveData.Messages.forEach(msg => {
messages.push({ id: msg.MessageId, msgAttributes: msg.MessageAttributes, body: msg.Body, receiptHandle: msg.ReceiptHandle });
});
const sendMsg = async ({ id, msgAttributes, body, _ }) => {
const sendMessageParams = {
MessageId: id,
MessageAttributes: msgAttributes,
MessageBody: body,
QueueUrl: mainQueueUrl
};
const sentData = await sqs.send(new SendMessageCommand(sendMessageParams));
// console.log("Success, message sent. MessageID: ", sentData.MessageId);
return 'Success';
};
const deleteMsg = async ({ id, receiptHandle }) => {
const deleteMessageParams = {
MessageId: id,
QueueUrl: dlqQueueUrl,
ReceiptHandle: receiptHandle
};
const deleteData = await sqs.send(new DeleteMessageCommand(deleteMessageParams));
// console.log("Message deleted", deleteData);
return 'Deleted';
};
const sent = await Promise.all(messages.map(sendMsg));
console.log(sent);
const deleted = await Promise.all(messages.map(deleteMsg));
console.log(deleted);
console.log(sent.length);
return sent.length;
// return 1;
} catch (err) {
console.log(err);
}
}
function main() {
const queues = readFileSync('queues.txt', 'utf8').split('\n');
queues.map(async elem => {
const [dlqQueue, mainQueue] = elem.split(' ');
console.log(`Moving messages from ${dlqQueue} to ${mainQueue}`);
const response = await reprocessMessages(dlqQueue, mainQueue);
console.log(response);
});
}
main()
This script moves the message from DLQ to MainQ and shows the new count of the DLQ decreased by the number of messages. However, when those messages in MainQ fail they again come back to DLQ thus keeping the count same as before reprocessing. But, after a while I see that the messages in DLQ increase by the same amount as the number of messages processed.
For instance for the below case I moved 54 messages and the screenshots for the queue counts are attached after each stage.

Related

405 Error using slash command handler Discord.js

I got a 405: Method Not Allowed error when I was running the slash command builder.
There's the code:
const { glob } = require("glob");
const { promisify } = require("util");
const { Client } = require("discord.js");
const mongoose = require("mongoose");
const globPromise = promisify(glob);
/**
* #param {Client} client
*/
module.exports = async (client) => {
// Commands
const commandFiles = await globPromise(`${process.cwd()}/commands/**/*.js`);
commandFiles.map((value) => {
const file = require(value);
const splitted = value.split("/");
const directory = splitted[splitted.length - 2];
if (file.name) {
const properties = { directory, ...file };
client.commands.set(file.name, properties);
}
});
// Events
const eventFiles = await globPromise(`${process.cwd()}/events/*.js`);
eventFiles.map((value) => require(value));
// Slash Commands
const slashCommands = await globPromise(
`${process.cwd()}/SlashCommands/*/*.js`
);
const arrayOfSlashCommands = [];
slashCommands.map((value) => {
const file = require(value);
if (!file?.name) return;
client.slashCommands.set(file.name, file);
if (["MESSAGE", "USER"].includes(file.type)) delete file.description;
if (file.userPermissions) file.defaultPermission = false;
arrayOfSlashCommands.push(file);
});
client.on("ready", async () => {
// Register for a single guild
const guild = client.guilds.cache.get("1014471738844790844");
await guild.commands.set(arrayOfSlashCommands).then((cmd) => {
const getRoles = (commandName) => {
const permissions = arrayOfSlashCommands.find((x) => x.name === commandName).userPermissions;
if (!permissions) return null;
return guild.roles.cache.filter(x => x.permissions.has(permissions) && !x.managed);
};
const fullPermissions = cmd.reduce((accumulator, x) => {
const roles = getRoles(x.name);
if (!roles) return accumulator;
const permissions = roles.reduce((a, v) => {
return [
...a,
{
id: v.id,
type: 'ROLE',
permission: true,
}
];
}, []);
return [
...accumulator,
{
id: x.id,
permission: permissions,
}
];
}, []);
guild.commands.permissions.set({ fullPermissions });
});
// Register for all the guilds the bot is in
// await client.application.commands.set(arrayOfSlashCommands);
});
// mongoose
const { mongooseConnectionString } = require('../config.json')
if (!mongooseConnectionString) return;
mongoose.connect(mongooseConnectionString).then(() => console.log('Connected to mongodb'));
};
There's the interactionCreate.js file:
const client = require("../index");
client.on("interactionCreate", async (interaction) => {
// Slash Command Handling
if (interaction.isCommand()) {
await interaction.deferReply({ ephemeral: false }).catch(() => { });
const cmd = client.slashCommands.get(interaction.commandName);
if (!cmd)
return interaction.followUp({ content: "An error has occurred " });
const args = [];
for (let option of interaction.options.data) {
if (option.type === "SUB_COMMAND") {
if (option.name) args.push(option.name);
option.options?.forEach((x) => {
if (x.value) args.push(x.value);
});
} else if (option.value) args.push(option.value);
}
interaction.member = interaction.guild.members.cache.get(interaction.user.id);
if (!interaction.member.permissions.has(cmd.userPermissions || [])) return interaction.followUp({ content: `Error: Mission Permissions.` });
cmd.run(client, interaction, args);
}
// Context Menu Handling
if (interaction.isContextMenu()) {
await interaction.deferReply({ ephemeral: false });
const command = client.slashCommands.get(interaction.commandName);
if (command) command.run(client, interaction);
}
});
And there's the error I got:
C:\Users\pines\OneDrive\桌面\ROBO_Head-v2\node_modules\discord.js\src\rest\RequestHandler.js:350
throw new DiscordAPIError(data, res.status, request);
^
DiscordAPIError: 405: Method Not Allowed
at RequestHandler.execute (C:\Users\pines\OneDrive\桌面\ROBO_Head-v2\node_modules\discord.js\src\rest\RequestHandler.js:350:13)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at async RequestHandler.push (C:\Users\pines\OneDrive\桌面\ROBO_Head-v2\node_modules\discord.js\src\rest\RequestHandler.js:51:14)
at async ApplicationCommandPermissionsManager.set (C:\Users\pines\OneDrive\桌面\ROBO_Head-v2\node_modules\discord.js\src\managers\ApplicationCommandPermissionsManager.js:186:18) {
method: 'put',
path: '/applications/991997852538634311/guilds/1014471738844790844/commands/permissions',
code: 0,
httpStatus: 405,
requestData: { json: [], files: [] }
}
Discord.js version is 13.11.0, bot has administrator permission on the server.
Please help me solve this.

innerText value is undefined when returned from promise despite being there on the console

I'm using Node JS, here's the code
import fetch from 'node-fetch';
import { JSDOM } from 'jsdom';
import {Appartment} from "./models/Appartment.mjs"
let applist = []
let multipleDivs = []
async function kijAppartments() {
try {
const kijCall = await fetch(`https://www.kijiji.ca/b-ville-de-montreal/appartement-4-1-2/k0l1700281?rb=true&dc=true`);
if(!kijCall.ok) {
throw new Error (
`HTTP error: ${kijCall.status}`
)
}
const response = await kijCall.text()
const dom = new JSDOM(response)
multipleDivs = dom.window.document.querySelectorAll(".info-container")
// console.log(multipleDivs)
return multipleDivs
}
catch(error) {
console.log("Error Made")
console.log(error)
}
}
async function arrayOfApps() {
await kijAppartments()
.then(data => {
data.forEach(div => {
const newApp = new Appartment
newApp.price = div.childNodes[1].innerText
newApp.title = div.childNodes[3].innerText
newApp.description = div.childNodes[7].innerText
console.log(newApp)
})
})
}
await arrayOfApps()
If you go on this link and try the following const aList = document.querySelectorAll(".info-container"), you get access to all of the nodes, innerHTML and innerText all work and give you access to the actual value but for some reason, when I try to run this code in the terminal, the value of all my objects is undefined.
You should use textContent instead of innerText.
Here's my solution:
const fetch = (...args) => import('node-fetch').then(({default: fetch}) => fetch(...args));
const jsdom = require('jsdom');
const { JSDOM } = jsdom;
class Appartment {
price
title
description
location
}
let multipleDivs = []
const appartments = []
function trim(text){
return text.replace(/(\r\n|\n|\r)/gm, "").trim()
}
async function fetchKijijiAppartments() {
const url = `https://www.kijiji.ca/b-ville-de-montreal/appartement-4-1-2/k0l1700281?rb=true&dc=true`
try {
const kijijiRes = await fetch(url);
if (!kijijiRes.ok) {
throw new Error(
`HTTP error: ${kijijiRes.status}`
)
}
const response = await kijijiRes.text()
// console.log("DB: ", response)
const dom = new JSDOM(response)
multipleDivs = dom.window.document.querySelectorAll(".info-container")
//console.log("DB: " multipleDivs)
return multipleDivs
} catch (error) {
console.log("Error Made")
console.log(error)
}
}
async function scrapeAppartments() {
await fetchKijijiAppartments()
.then(data => {
data.forEach(div => {
const appartement = new Appartment
appartement.price = trim(div.querySelector(".price").textContent)
appartement.title = trim(div.querySelector(".title").textContent)
appartement.description = trim(div.querySelector(".description").textContent)
console.log("DB: ", appartement)
appartments.push(appartement)
})
})
}
scrapeAppartments()

How to test firebase callable function with firestore

I have a firebase callable function like
exports.getUserInfo = functions.https.onCall(async (data, context) => {
const userIdRef = store.collection('UserID').doc('Document');
let res = null;
try {
res = await store.runTransaction(async t => {
const doc = await t.get(userIdRef);
currentUserId = doc.data().ID;
const newUserIdNum = currentUserId + 1;
await t.update(userIdRef, {ID: newUserIdNum});
let initUserData = {
'userID': newUserId,
}
return initUserData ;
});
console.log('Transaction success');
} catch (e) {
console.error('Transaction failure:', e);
}
return res;
})
but I am not sure how to create unit test about this. I want to mock UserID/Documment before I call
test.wrap(getUserInfo), like
const myFunctions = require('../index.js')
const getUserInfoWrapped = test.wrap(myFunctions.getUserInfo);
var assert = require('assert');
describe('User', function() {
describe('getUserInfo()', function() {
it('should create user', async function() {
// sample code, this won't work
const snapshot = test.firestore.makeDocumentSnapshot({ID: 1001}, 'UserID/Document');
const data = {}
const result = await getUserInfoWrapped (data, {});
assert.equal(result.userID, "1002");
});
});
});
seems this case not covered by firebase document
Reference:
https://firebase.google.com/docs/functions/unit-testing
https://github.com/firebase/firebase-functions-test/blob/c77aa92d345b8e4fb5ad98534989eb8dcf7d9bc4/spec/providers/https.spec.ts

How to fetch resource thorugh Expo/React Native

Using this code:
handleShortCapture = async () => {
try {
const photoData = await this.camera.takePictureAsync();
this.setState({ capturing: false, captures: [photoData, ...this.state.captures] })
} catch (e) {
ToastAndroid.show(e)
}
const shibeAmount = Math.floor(Math.random() * 3 + 1);
Speech.speak(`shibe amount: ${shibeAmount}`)
try {
const shibes = await fetch(`https://cors-anywhere.herokuapp.com/https://shibe.online/api/shibes?count=${shibeAmount}urls=false&httpsUrls=false`)
const jsonShibes = await shibes.json()
Speech.speak(jsonShibes.length)
} catch(e) {
Speech.speak(e.message)
}
};
I can hear the shibe amount phrase but can't hear the response from the fetch request; What am I missing?

Objects in array are empty when return statement is included in function

I have a function that I want to return the array of objects parsedContacts. With the return statement there, the console.log above it prints an array of empty objects. When I remove the return statement, each object has three properties as expected.
How can I return the parsedContacts and include the properties?
/* eslint-disable no-console */
/* eslint-disable no-unused-vars */
import { PermissionsAndroid } from 'react-native';
import Contacts from 'react-native-contacts';
export const getAndProcessPhoneContacts = async () => {
PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.READ_CONTACTS,
{
'title': 'Contacts',
'message': 'Xxxxxxxx would like to view your contacts.'
}
)
const contacts = await getContacts();
const parsedContacts = parseContacts(contacts);
sortContacts(parsedContacts);
console.log(parsedContacts);
return parsedContacts; // this line needs to be removed for parsedContacts to have properties in the objects inside it.
}
const getContacts = () => {
return new Promise((resolve, reject) => {
Contacts.getAll((error, contacts) => {
contacts ? resolve(contacts) : reject(error)
})
})
}
const parseContacts = contacts => {
return contacts.map(contact => {
let parsedContact = {}
Object.keys(contact).forEach(key => {
switch (key) {
case 'givenName':
parsedContact.firstName = contact[key]
break
case 'familyName':
parsedContact.surname = contact[key]
break
case 'phoneNumbers':
parsedContact.phoneNumber = contact[key].length ? contact[key][0].number : ''
}
})
return parsedContact
})
}
const sortContacts = contacts => {
contacts.sort((a, b) => {
let contactA = a.firstName;
let contactB = b.firstName;
return (contactA < contactB) ? -1 : (contactA > contactB) ? 1 : 0;
});
}
Update
As requested in the comments below, here is the calling function of getAndProcessPhoneContacts. I know that this is ugly and needs refactoring, any advice on this gratefully accepted too!
async componentDidMount() {
ConnectyCube.init(...config)
try {
const accessToken = await getFirebaseToken();
if (accessToken) {
await authorizeConnectyCube(accessToken);
if (this.props.user.parsedContacts) {
const registeredUsers = await retrieveRegisteredUsers();
this.props.updateRegisteredContacts(registeredUsers);
Actions.Dashboard();
} else {
const parsedContacts = await getParsedContactsFromStorage();
if (parsedContacts) {
this.props.updateParsedContacts(parsedContacts);
Actions.Dashboard();
} else {
const parsedContacts = await getAndProcessPhoneContacts();
console.log(parsedContacts); // prints an array of empty objects
await writeParsedContactsToStorage(parsedContacts);
this.props.updateParsedContacts(parsedContacts);
const registeredUsers = await retrieveRegisteredUsers();
this.props.updateRegisteredContacts(registeredUsers);
Actions.Dashboard();
}
}
} else {
Actions.PhoneNumberInput();
}
} catch (error) {
Alert.alert(error);
}
}
Update 2
I have an inelegant solution by using a callback:
const cb = (ct) => {
console.log(ct); // Objects now have properties
}
const parsedContacts = await getAndProcessPhoneContacts(cb);
await writeParsedContactsToStorage(parsedContacts);
this.props.updateParsedContacts(parsedContacts);
const registeredUsers = await retrieveRegisteredUsers();
this.props.updateRegisteredContacts(registeredUsers);
Actions.Dashboard();
}
}
} else {
Actions.PhoneNumberInput();
}
} catch (error) {
Alert.alert(error);
}
}
And the called function:
export const getAndProcessPhoneContacts = async (cb) => {
PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.READ_CONTACTS,
{
'title': 'Contacts',
'message': 'Xxxxxxx would like to view your contacts.'
}
)
const contacts = await getContacts();
const parsedContacts = parseContacts(contacts);
sortContacts(parsedContacts);
console.log(parsedContacts);
cb(parsedContacts)
}

Categories