I'm trying to workout how to receive messages from sails.js when a new entry is created via the rest api. I'm trying to receive this message outside of sails (but also for other reasons in sails)
In my sails app I can receive the message when a new entry is like so...
var socket = io.connect("http://localhost:1337");
socket.on("connect", function(){
socket.request("/job", {}, function(jobs){
console.log("jobs", jobs);
})
socket.on('message', function(message){
console.log('message', message);
})
})
When a new 'job' is created, the web app receives a message.
I would like to receive the same message outside of sails. I've used this gist https://gist.github.com/epadillas/5993856 as a guide.
Problem is I don't seem to be able to pick up messages. I tried to do the same socket.io("connect") followed by socket.request however it seems that request isn't part of the standard socket.io-client.
Hope this makes sense!
Cheers,
Related
First of all I'm an OG bare metal Java server side guy. That means I'm new to Docker, Node.js (JavaScript in general), socket.io and trying to learn all these things at once so please pardon me if I've made an obvious mistake. I've been working on a pro-bono project for some time in hope that in exchange I get to learn all of these things and move into the new way of doing things.
Now, having said that, moving along to my question - In the code snippet below (especially the last line)
io.on('connection', function (socket) {
console.log(`connection made from ${socket.id}`);
socket.on('disconnect', function () {
console.log(`connection ${socket.id} closed`);
});
socket.on(DOWNSTREAM_MESSAGE, function (msg) {
//console.log(`Received socket payload: ${msg} from ${socket.id}`);
iopubClient.publish(DOWNSTREAM_MESSAGE, msg);
});
iosubClient.subscribe(UPSTREAM_MESSAGE, message => {
//console.log(`Sending socket payload: ${message} to ${socket.id}`);
socket.emit(UPSTREAM_MESSAGE, message);
});
});
as far as I understand from all the internet sleuthing is that:
io.emit(....
broadcasts to all clients the server socket is connected to, and
socket.emit(....
sends to the call initiator (specifically referring to emit cheat sheet among other sources).
However, with the code snippet above, even when I'm using socket.emit, all subscribing socket.io clients receive the message as if it were a broadcast which isn't what I want. I really do want to send the response back to the io that initiated this particular request.
I've tried almost every way of achieving session stickiness from session stickiness (current implementation an attempt via cookie based stickiness with a HAProxy in front of the service).
In case it helps you help me, full code-base is here.
As I mentioned, I'm learning all of this on the fly so I will not be embarrassed (in fact would be quite thankful!) if you point me to something I'm doing wrong, but for the life of me, I cannot get the response to go only to the request initiator.
Please help?!
I have a service (find, get, create, remove) and I would like to call theme via socket.io
For example:
A user writes a message on the chat to another user. I would like to the data not sending via request but in realtime on socket because in this moment creating is a document of mongoose.
Is it posible? If yes, how can I do it?
Below is my snippet code: (Server side)
io.on('connect', function(socket){
socket.on('message', function(id, msg){
socket.to(id).emit('chat message', msg);
});
}))
http://localhost:3030/messages <-- URL of REST api to creating a document with mongoose. After sending data on the link is creating a document. I need that a document will be create via socket.io, not request.
I mean something like this:
io.on('connect', function(socket){
socket.on('message', function(id, msg){
socket.to(id).emit('chat message', msg);
// Socket call a create method of my service
socket.post('/messages', data);
});
}))
If you are not using Feathers as the client you can find the detailed documentation about how to call services via sockets here.
A messages for the /messages service can be created directly via a socket like this:
var socket = io();
socket.emit('messages::create', {
"text": "I really have to iron"
}, (error, message) => {
console.log('Todo created', message);
});
You can also listen to any created event like this:
var socket = io();
socket.on('messages created', data => console.log('Someone created a new message', data);
socket.emit('messages::create', {
"text": "I really have to iron"
}, (error, message) => {
console.log('Todo created', message);
});
Well, yes and no. There are no HTTP/REST-style verbs in Socket.io but since you can send anything you want, you can add the verbs yourself.
Additionally if you want to have a more structured way of building real-time APIs then you may want to take a look at frameworks like ActionHerp:
https://www.actionherojs.com/
In addition to HTTP, it can use WebSocket or TCP sockets as the underlying transport, and you can create custom "actions" that you can customize to your needs.
Now, if you want to use Feathers and you don't want to use anything else, then you may take a look at feathers-socketio:
https://www.npmjs.com/package/feathers-socketio
It's a Feathers Socket.io real-time API provider that exposes Feathers services through a Socket.io real-time API. It is compatible with Feathers 1.x and 2.x. And you can use Socket.io to interact with it.
I'm using node.js to create an app that gets a PUSH from Gmail each time an email is received, checks it against a third party database in a CRM and creates a new field in the CRM if the e-mail is contained there. I'm having trouble using Google's new Cloud Pub/Sub, which seems to be the only way to get push from Gmail without constant polling.
I've gone through the instructions here: https://cloud.google.com/pubsub/prereqs but I don't understand how exactly this is supposed to work from an app on my desktop. It seems that pub/sub can connect to a verified domain, but I can't get it to connect directly toto the .js script that I have on my computer. I've saved the api key in a json file and use the following:
var gcloud = require('gcloud');
var pubsub;
// From Google Compute Engine:
pubsub = gcloud.pubsub({
projectId: 'my-project',
});
// Or from elsewhere:
pubsub = gcloud.pubsub({
projectId: 'my-project',
keyFilename: '/path/to/keyfile.json'
});
// Create a new topic.
pubsub.createTopic('my-new-topic', function(err, topic) {});
// Reference an existing topic.
var topic = pubsub.topic('my-existing-topic');
// Publish a message to the topic.
topic.publish('New message!', function(err) {});
// Subscribe to the topic.
topic.subscribe('new-subscription', function(err, subscription) {
// Register listeners to start pulling for messages.
function onError(err) {}
function onMessage(message) {}
subscription.on('error', onError);
subscription.on('message', onMessage);
// Remove listeners to stop pulling for messages.
subscription.removeListener('message', onMessage);
subscription.removeListener('error', onError);
});
However, I get errors as if it isn't connecting to server and on the API list I see only errors, no actual successes. I'm clearly doing something wrong, any idea what it might be?
Thank you in advance!
TL;DR
Your cannot subscribe to push notifications from the client side.
Set up an HTTPS server to handle the messages. Messages will be sent
to the URL endpoint that you configure, representing that server's
location. Your server must be reachable via a DNS name and must
present a signed SSL certificate. (App Engine applications are
preconfigured with SSL certificates.)
Just subscribe to the push notifications on your server, and when you get the notification, you can figure out who it concerns. The data you will get from the notifications is what user that it concerns, and the relevant historyId, like so:
// This is all the data the notifications will give you.
{"emailAddress": "user#example.com", "historyId": "9876543210"}
Then you could e.g. emit an event through Socket.io to the relevant user if he is online, and have him do a sync with the supplied historyId on the client side.
I am currently building a new application which, at a basic level, lets users add a task which needs to be completed, and then lets a different group of users pick up the task and complete it.
Previously, I took over building a real-time chat application written with NodeJS and Socket.io and on that, all the messages were posted to a database over the socket connection.
In the current application I am doing the same, but was thinking if it might be better off to post the information to the database via the route instead, then emitting the socket event on success to update the list of available tasks.
I was just looking for advice, how would you guys do this? Commit info to the database through a route or over the socket?
If you go the route way things are pretty much laid out for you to be sure whether or not your update worked or not. Socket doesn't guarantee neither success nor failure, by default.
But you could program to make it. For e.g.
client: send data
socket.emit('update', data); // send data
server: receive data & send back an update as to whether the operation was successful or not
socket.on('update', function(data){
findOrUpdateOrWhateverAsync(function(err){
if(!err) socket.emit('update', null); // send back a "null" on success
else socket.emit('update', err.message); // or send back error message
});
});
client: receive update on error/success
socket.on('update', function(err){
if(err) alert(err);
});
I've ran into a fairly difficult to debug error with my node web server.
Background
I'm creating a node server with socket.io to provide a restful service, connected to mongodb which use web sockets(socket.io) for server-client messages.
Issue
In my node app, I've used an npm package called node-scheduler, in which I do some processing at set times(these are very dynamic times but work fairly well to date).
So I'll set off a job, using node-scheduler and when it ends you can provide a function.
In this function I emit a web socket message, exactly how I emit messages in the rest of the application but my client side never receives the message.
Checking the logs the client disconnections then re connections after the function has completed.
I've debugged a little further, and I send two messages to the client in this function. Only one of them is processed by the client. May be a client issue not a server issue.
Any ideas for solutions or suggestions would greatly be appreciated.
Well generally socket.io is only meant to be used as a "channel". You should have the Client exist as a separate entity in memory or something, and update the socket if and when it reconnects. Otherwise you're just sending to the past (disconnected) sockets.
Using passport you can identify a client as a user.
app.get('/', function(req, res){
// req.user;
});
Using passport.socketio you can get the same user in your socket
io.on('connection', function(socket){
// socket.request.user;
socket.request.user.socket = socket;
// this will be updated with the latest socket in case of a future reconnection
// So now you can be sure that user object will always have the latest socket
nodeScheduler(function(){
carryOutJobs(function callback(){
socket.request.user.socket.emit('done');
// will always emit to the "latest" socket.
});
});
});