Oracle CQN Event Issue - oracle

I am using nodejs to listen to my table's data change using oracle CQN.
I do have the grant permission and vice versa connection from my DB server to my production server. The below code is working fine from a DB server and APP Hosting server
function myCallback(message) {
console.log(`myCallback:: Listened new data insertion`);
runFunction();
}
const options = {
callback: myCallback,
sql: `SELECT * FROM ${schemaName}.${tableName} where STATUS=0`,
qos : oracledb.SUBSCR_QOS_ROWIDS,
clientInitiated: true,
};
async function listener() {
//Create Connection Pool
try {
await oracledb.createPool({
user: `${userName}`,
password: `${userPass}`,
connectString: `${connString}`,
externalAuth: false,
events: true,
poolMax: parseInt(`${poolMax}`),
poolMin: parseInt(`${poolMin}`),
// poolTimeout: parseInt(`${poolTimeout}`),
// queueMax: parseInt(`${queueMax}`),
// queueTimeout: parseInt(`${queueTimeout}`),
});
//Create Connection
const connection = await oracledb.getConnection();
await connection.subscribe('mysub', options);
console.log("App is Listening ");
} catch (e) {
console.log("Error on Listening" + e);
}
}
But while changing to a new DB hosting server I don't receive the change notification. I have used the query to check whether the event registration is working or not.
SELECT * from USER_CHANGE_NOTIFICATION_REGS
I do get many regid which means the event registration is working fine.
So why the CallBack function is not working.
Thanks.

Related

AWS Websocket doesnt receive previous message until new message is sent

Most of the time the messages are passed normally, but a couple messages in particular arent recieved until the recieving client sends a message. This happens everytime for specific methods/messages, but not at all for others.
Example: user1 sends a message, user2 then sends a message to receive message from user1.
Related Material
Deleted question: websocket receives previous message only when new message is sent
Github issue: webSocket client does not receive messages before sending...
We ran into this issue and the solution had to do with how we wrote our promises. We initially used the sample code provided by Amazon
https://github.com/aws-samples/simple-websockets-chat-app/blob/master/sendmessage/app.js#L26
const postCalls = connectionData.Items.map(async ({ connectionId }) => {
try {
await apigwManagementApi.postToConnection({ ConnectionId: connectionId, Data: postData }).promise();
} catch (e) {
if (e.statusCode === 410) {
console.log(`Found stale connection, deleting ${connectionId}`);
await ddb.delete({ TableName: TABLE_NAME, Key: { connectionId } }).promise();
} else {
throw e;
}
}
});
And I'm pretty sure having an async function as a map function doesn't work properly or reliably (for whatever reason. maybe this is documented somewhere), so we changed it to a simple for loop and it fixed the issue.
for(const connection of connectionData.Items) {
const connectionId = connection.connectionId;
...same logic goes here
}

REST API insert is not working using node-oracledb

I try to make RESTFUL API with node js and oracle database for my first time
I make a table in the database named "EMPLOYEES" and I add some data there
I make my backend file and I try to get the information in the database and it's worked successfuly
but when I try to make POST to add a new employee I don't get an error and the employee is not added to the database
when I try to test it with POSTMAN I got this result a null object like this {}
I know that I'm missing something
const express = require('express')
const oracledb = require('oracledb');
const bodyPerser=require("body-parser")
const app = express();
const port = 3000;
var password = 'mypassword';
app.use(bodyPerser.json());
async function selectAllEmployees(req, res) {
try {
connection = await oracledb.getConnection({
user: "system",
password: password,
connectString: "localhost:1521/XE"
});
console.log('connected to database');
// run query to get all employees
result = await connection.execute(`SELECT * FROM EMPLOYEES`);
} catch (err) {
//send error message
return res.send(err.message);
} finally {
if (connection) {
try {
// Always close connections
await connection.close();
console.log('close connection success');
} catch (err) {
console.error(err.message);
}
}
if (result.rows.length == 0) {
//query return zero employees
return res.send('query send no rows');
} else {
//send all employees
//return res.send(result.rows);
console.log(JSON.stringify(result.rows));
console.log(result.metaData[0].name);
let list=[]
result.rows.forEach(element => {
let agent = {
"ID": element[0],
"EMPNAME": element[1],
"EMPLASTNAME": element[2],
"AGE":element[3]
}
list.push(agent)
});
return res.send(JSON.stringify(list));
}
}
}
//get /employess
app.get('/employees', function (req, res) {
selectAllEmployees(req, res);
})
//////////////////post//////////////////////
app.post("/addNewEmployee", async (req, res) => {
try {
connection = await oracledb.getConnection({
user: "system",
password: password,
connectString: "localhost:1521/XE"
});
console.log('connected to database');
// I don't know what i'm missing here
result=connection.execute(`INSERT INTO EMPLOYEES VALUES ('${req.body.ID}','${req.body.EMPNAME}','${req.body.EMPLASTNAME}','${req.body.AGE}')`);
res.send(result)
} catch (err) {
//send error message
return res.send(err.message);
}
})
app.listen(port, () => console.log("nodeOracleRestApi app listening on port %s!", port))
Review node-oracledb examples and make sure you have basic techniques covered e.g. using bind variables. (The way you build your INSERT is open to SQL injection security attacks). Look at how webapp.js uses a connection pool - which you'll need if you have more than one person accessing your service.
Make sure you commit the data after inserting.
Add an 'await' before your connection.execute() for INSERT, something like:
result = await connection.execute(`INSERT INTO EMPLOYEES VALUES (:id, :empname, :emplastname, :age)`,
[req.body.ID, req.body.EMPNAME, req.body.EMPLASTNAME, req.body.AGE],
{autoCommit: true}
);
Do some debugging and see what is not working.
Avoid using SYSTEM for testing. Create a 'normal' (non privileged) user:
https://blogs.oracle.com/sql/how-to-create-users-grant-them-privileges-and-remove-them-in-oracle-database
Finally check out this series on creating a REST service with node-oracledb:
https://blogs.oracle.com/oraclemagazine/build-rest-apis-for-nodejs-part-1
https://github.com/oracle/oracle-db-examples/tree/master/javascript/rest-api

Add identifier to websocket

I am using the Node.js ws library, to listen to events in user accounts on a 3rd party API. For each user, I open a websocket to listen to the events in the user's account.
Turns out, the 3rd-party API doesn't provide a userID for each event, so if I have 10 websocket connections to user-accounts, I cannot determine which account an event came from.
I have access to a unique userId prior to starting each of my connections.
Is there a way to append or wrap the websocket connection with the userId identifier, to each connection I make, such that when I receive an event, I can access the custom identifier, and subsequently know which user's account the event came from?
The code below is a mix of real code, and pseudocode (i.e customSocket)
const ws = new WebSocket('wss://thirdparty-api.com/accounts', {
port: 8080,
});
ws.send(
JSON.stringify({
action: 'authenticate',
data: {
oauth_token: access_token,
},
})
);
// wrap and attach data here (pseudocode at top-level)
customSocket.add({userId,
ws.send(
JSON.stringify({
action: 'listen',
data: {
streams: ['action_updates'],
},
})
)
})
// listen for wrapper data here, pseudocode at top level
customSocket.emit((customData) {
ws.on('message', function incoming(data) {
console.log('incoming -> data', data.toString());
})
console.log('emit -> customData', customData);
})
Looking at the socket.io library, the namespace feature may solve for this, but I can't determine if that's true or not. Below is an example in their documentation:
// your application has multiple tenants so you want to dynamically create one namespace per tenant
const workspaces = io.of(/^\/\w+$/);
workspaces.on('connection', socket => {
const workspace = socket.nsp;
workspace.emit('hello');
});
// this middleware will be assigned to each namespace
workspaces.use((socket, next) => {
// ensure the user has access to the workspace
next();
});
I found a solution to this which is fairly simple. First create a message handler function:
const eventHandler = (uid, msg) => {
console.log(`${uid} did ${msg}`);
};
Then, when you create the websocket for the given user, wrap the .on event with the handler:
const createSocketForUser = (uid, eventHandler) => {
const socket = new WebSocket(/* ... */);
socket.onmessage = (msg) => {
eventHandler(uid, msg)
};
return socket;
}

Issue Broadcasting to Socket.io Rooms of A Namespace

I'm trying to set up a server that can dynamically create many rooms for many namespaces. I'm currently just trying to broadcast to sockets of a room, when a new socket has joined that room.
So far I have been able to broadcast to a specific namespace and my event listeners on the client receives the message. However when I try to broadcast to a room, of a specific namespace, my event listener doesn't receive that message.
I've turned on the Debugger mode and see the socket.io-client:socket emitting the event with the right payload and event type. So I am not sure what I am missing since the documentation also seems fairly straightforward. Any help would be much appreciated. Below is my code.
Server
const colorNs = io.of('/color');
colorNs.on('connection', (socket) => {
const { id } = socket.handshake.query;
const { id:connId } = socket.conn;
if(id) {
socket.join(id);
socket.broadcast.to(id).emit('user:connect', { id: connId });
}
socket.on('disconnect', () => {
const { id } = socket.handshake.query;
const { id:connId } = socket.conn;
socket.broadcast.to(id).emit('user:disconnect', { id: connId });
});
});
Client
const socket = io('/color?id="123"');
socket.on('user:connect', () => console.log('data', data));
Client - Debug Trace
socket.io-parser decoded 2/color,["user:connect",{"id":"IZTTPidF121JCzf9AAAO"}] as {"type":2,"nsp":"/color","data":["user:connect",{"id":"IZTTPidF121JCzf9AAAO"}]} +1ms
browser.js:133
socket.io-client:socket emitting event ["user:connect",{"id":"IZTTPidF121JCzf9AAAO"}] +3ms

Await signalr message in client

Is it possible for a SignalR client send a message to the server and then to await for a seperate message (not a return value) from the server?
The theory;
Client1 send message1 to Server and "waits" for the response.
Server processes some logic
Server sends message2 to Client1 and Client1 executes the waiting code.
Call to the server:
$.connection.myhub.server.myRequest(id).done(()==>{
// myRequest is done;
// the server has received the request but hasn't processed it yet.
// I want put some *async* code here to do something when the server has triggered $.connection.myhub.client.myResponse(id, someParam);
});
Callback to the client:
$.connection.myhub.client.myResponse(originalId, somePassedBackValue);
Can I use Async/Await, or wrap this in a Promise somehow?
If this isn't acheivable in SignalR are there anyother socket libraries that might be used instead?
You can do something, like the following:
Imagine you have a client that joins a group, updates a table and then notifies the client that it has joined.
Client
msgHub.server.joinGroup(id).done(function () {
console.log("Joined Group");
serverCallFinished = true;
})
msgHub.client.displayTable = function (table) {
display(table);
}
Hub
public async Task JoinGroup(string practiceId)
{
try
{
await Groups.Add(Context.ConnectionId, practiceId);
//Add new table
var table = new Table(practiceId)
await UpdateTable("SomeGroup", table);
}
catch (Exception e)
{
throw;
}
}
public async Task UpdateInfo(string groupName, string table)
{
//await some logic
Clients.Group(groupName).updateTable(table);
}
Update info will call the client with message2 in this case a table that it wants to display to the client. When it finishes the it will return from its awaited state by JoinGroup which will return and alert that a new user has joined a group.

Resources