Meteor Random package vs randomSeed - javascript

I'm trying to replicate the latency compensation done by Meteor and minimongo. For instance to create an id on the client and then the same id on the server after calling the method, so the client can update the UI without waiting for the server response.
For this I need to generate the same Id on both the client and the server.
So, in meteor if I do: Random.createWithSeeds('abc').id()
I always get:
WKrBPwCSbzNHmhacn
But if I connect from and external app, outside of metor using a ddp client:
self.send({msg: 'method', id:id, randomSeed: 'abc', method: name, params: params});
I get a different Id. It's repeatable, but not the same as the one generated by Random. Why?
I cannot understand. Are they using a different generationId algorithm?
Packages I'm using:
On Meteor: https://atmospherejs.com/meteor/random
On external Client (outside Meteor): https://github.com/eddflrs/meteor-ddp + source code of random.js

This may not be a complete answer (I'm still looking too), but the way you're using Random.createWithSeeds should read:
> let generator = Random.createWithSeeds('abc')
> generator.id()
'WKrBPwCSbzNHmhacn'
> generator.id()
'h6iLWkdEfZ7wXWpPQ'
Perhaps an edit might clarify that createWithSeeds('abc') is supposed to return an object you call .id() on multiple times. I've never tried passing the seed from another ddp client though, and I'll let you know when I do

Related

Socket in javascript

please what is different
var socket = new WebSocket('ws://localhost:8181');
var socket = new WebSocket('ws://localhost:8181/websession');
what is ( Websession )
websession is just the endpoint the websocket will connect to. It's just like normal HTTP servers or REST services: You can have multiple endpoints on one server, like:
ws://localhost:8181/customers
ws://localhost:8181/prices
ws://localhost:8181/items
... and so on. (This is just an example and does not necessarily make sense for a specific use case.) In old-style HTTP, you could image them as different directories on the same server, possibly offering very different contents.
In order to use the socket correctly, you have to know your desired endpoint and use it when creating the socket. So it depends on the server whether ws://localhost:8181 or ws://localhost:8181/websession is correct (or even both of them, depending on the purpose of the individual endpoint). It's generally a good practice to give the endpoint a meaningful name, so the first one would be discouraged.
As the application seems to be running on your localhost, you should take a look at the server running at port 8181 to find out the endpoints offered. And you could possibly get used to websockets, here is one of many possible starting points.

Client (JRE) read server (node) variables directly?

I am trying to set up a server where clients can connect and essentially "raise their hand", which lights up for every client, but only one at a time. I currently just use the express module to send a POST response on button-click. The server takes it as JSON and writes it to a file. All the clients are constantly requesting this file to check the status to see if the channel is clear.
I suspect there is a more streamlined approach for this, but I do not know what modules or methods might be best. Can the server push variables to the clients in some way, instead of the clients constantly requesting a file? Then the client script can receive the variable and change the page elements accordingly?
Usually, this kind of task is done by using WebSockets. Since you already have socket.io set up, it'd be great to reuse it.
From the server, start emitting different messages:
socket.emit("hand", { userId: <string> });
From the client, listen to the new event and invoke whatever the appropriate behavior is:
socket.on("hand", (payload) => {
// payload.userId contains user ID
});

How to create parameters in dialogflow using node.js

I want to create a parameter in node js that stays in the same intent for a life spam of 2.
It should ask for the first value then validates it, then second value and so on
what I have done
function test(agent) {
var first = agent.parameters.first;
var second = agent.parameters.second;
agent.context.set({
name: 'test',
lifespan: 2,
parameters: {
'first': first,
'second': second
},
});
agent.add("first parameter then second parameter");
}
Should I create the parameters in dialogflow as follows and implement it in node js or it should be done all in node js. If so how can I do it?
appreciate your help
I would say that in general the best option is to set all the intent's parameters via Dialogflow and then interact via Node.js client library.
Actually it would be also possible to do everything with Node.js, but in case you are using (or may use in the future) one of the integration options using fulfillment to manage agent’s responses you should set a webhook service and manage responses via API.
Therefore, I think setting the parameters in Dialogflow before interacting with Node.js would be the simplest and straightforward approach for any use case.
The code works fine, incase anyone facing the same issue, the request being sent must have the same session id to avoid overriding the values.

Meteor: How can I get useraccounts package to write a new user doc into a remote collection?

I'm using the packages accounts-password and useraccounts:bootstrap and it all works fine, meaning the sign-on form creates a new doc in the Meteor.users collection. But I don't want any collection on the client facing app, hence I do have a second app running to which I successfully connect via DDP.connect() and I can exchange all necessary docs/collections via pub/sub and calling methods on the remote app.
The only thing that doesn't work is the useraccount doc. I've used (on the client app):
remote.subscribe('users', Meteor.userId(), function() {
});
and (on the remote app):
Meteor.publish('users', function() {
return Meteor.users.find({});
});
even though I'm not sure if there is a pub/sub already included in the package. Still, the doc is written to the local (client) app and not to the remote app.
How can I achieve this?
useraccounts:core simply makes use of Accounts.createUser on the server side (see this line) within a method called from the client-side (see this another line).
So the new user object is created from the server side and not from the client (though it flows all the way down to the client thanks to the DDP and default users subscriptions...).
If you're really looking to change the defaul behaviour provided by the Meteor core Accounts packages (accounts-base, accounts-password in this case...) you should try to override the Accounts.createUser method which is were all begins...
In any case be warned that the current user is published to the client by default: see these lines
Finally, to prevent useraccounts:core to use the Accounts API you could try to override the AtCreateUserServer method and deal with the creation of a new user on a remote application inside there.
Package accounts-base provide such functionality.
The accounts-base package exports two constructors, called AccountsClient and AccountsServer, which are used to create the Accounts object that is available on the client and the server, respectively.
Nevertheless, these two constructors can be instantiated more than once, to create multiple independent connections between different accounts servers and their clients, in more complicated authentication situations.
Documentation: Accounts (multi-server)

Keeping a client-side sync of Sails.js collection, using sockets

I very much like Meteor's pub/sub. I wonder if there is a way to get a similar workflow, using sails.js or just a socket library in general.
In particular, what I would like to be able to do is something along the lines of:
// Server-side:
App.publish('myCollection', -> collection.find({}))
// Client-side:
let myCollection = App.subscribe('myCollection')
let bob = myCollection.find({name: 'Bob'})
myCollection.insert({name: 'Amelie'}, callback)
All interaction with the server should happen in the background.
I very much like Meteor's pub/sub. I wonder if there is a way to get a similar workflow, using sails.js or just a socket library in general
Basically yes, at least about realtime sync between backend and frontend. Let's review what meteor's have and answer point by point.
Pub/sub
The Pub / Sub concept, as stated by Sabbir, is also supported by sails.js. Though the basics are slightly different :
In meteor, the client can subscribes to everything he wants, and the server control what it receives by only publishing to who he wants;
whereas in sails.js, the server both does subscribe some clients sockets and publish to all binded sockets
Note that, by default:
meteor contains the autopublish package that just notify every client without any kind of filtering. To acheive some filtering, you have to meteor remove autopublish then you can handle what will your client receive by adding a mongo request to it, like explained here.
sails by default, on its automatic "select" blueprints actions, auto-subscribes the calling socket to the events on the objects returned by the "select".
As a server-side conclusion:
Subscribe: just call findor findOne blueprint default action, through a socket (attaching some where filters or not) and your socket will automatically be subscribed to every events concerning returned objects => you don't have to code anything on the server, in most cases, for the Subscribe logic.
Publish: every blueprint default actions (create, update, destroy, add, remove) auto-publish to subscribed sockets => you don't have to code anything on the server, in most cases, for the Publish logic.
(Though, if you find yourself implementing some manual controller actions, sails API helps you publishing and subscribing easily)
Client handling
Therefore, with both meteor and sails, clients only receive what they're supposed to receive. Time for front-end now.
Philosophy
meteor in one hand, with it's isomorphic dimension, does provide a front-end connector by nature, exposing it's data-bound collections.
sails on the other hand, is front-end agnostic, and can be attacked by any http REST connector (JS or not), such as $http, $resource, or more advanced ones like Restangular.
Though, being aware of the complexity using raw sockets on their API (when it comes to session, CORS, CSRF and stuff), they developped a javascript socket.io wrapper called sails.io.js designed to be REST-like-over-socket, and just works like a charm.
Basically, The main difference is that meteor is one step higher-level than sails, because it provides the logic of syncing collections and objects.
All interaction with the server should happen in the background.
sails.io.js, the official front-end component, is just not that high-level. When it comes to Angular.js.
Though, you can find some community connectors that aim to, kinda, provide the same feature as mongo data-bound collections and objects. There is sails-resource, spinnaker or angular resource sails. I tried both of them, and I should say that I was disapointed. The abstraction level is so high that it just becomes annoying, IMHO. For example, with not-very-RESTful-friendly custom actions, like a login, it becomes very hard to adapt it for your needs.
==> I would advice to use a low-level connector, such as angularSails or (my prefered) https://github.com/janpantel/angular-sails, or even raw sails.io.js if you're not using Angular.
Edit: just foun a backbone version, by the sails' creator
It just works great, and believe me, the "keep my collection in sync with that socket" code is so ridiculous, that finding a module for this is just not worth it.
Some code please, stop talking
In particular, what I would like to be able to do is something along the lines of:
Server
Meteor
# Server-side:
App.publish('myCollection', -> collection.find({}))
Sails
//Nothing to do, just sails generate api myCollection
Client
Meteor
# Client-side:
myCollection = App.subscribe('myCollection')
Sails, with sails.io.js
(Here using lodash for convenience)
var myCollection;
sails.io.get('/myCollection').then(
function(res) {
myCollection = res.data;
},
function(err) {
//Handle error
}
);
sails.io.on('myCollection').function(msg) {
switch(msg.verb) {
case 'created':
myCollection.push(msg.data);
break;
case 'updated':
_.extend(_.find(myCollection, 'id', msg.id), msg.data);
break;
case 'destroyed':
_.remove(myCollection, 'id', msg.id);
break;
};
});
(I leave the find where and create to your imagination with [the doc])
All interaction with the server should happen in the background.
Well, Sails, only for angular, with sails ressources
I'm not pretty used to that process, so I leave you reading here or here, but once again I'd choose manual .on()method.
Since I asked this question, I've learned a few things and some new projects have popped up. I decided against sails.io, because when developing with React.js, most of the community's weight is behind webpack, but sails.io uses gulp. I realize these can be used together and there is even an npm package for this, but I wasn't too keen on making my stack bigger than it had to be, so I went with a simple express.js server that I could tailor to my needs.
In order to sync my data, I'm using rethinkdb which allows me to asynchronously watch the database for changes and then publish the changes to the clients through websockets.
I've set up a simple script where I keep an instance of a baobab tree on both the client and the server.
When the tree gets modified on the server, it sends transaction data to the appropriate clients through the websocket
The client merges the transaction with the tree.
This method does not make use of local storage and keeps the data in memory in the node.js process. The data in the transaction is also quite redundant.
The future plan has always been to set something up using redis and local storage ...
... until yesterday when I found deepstream.io!
This is a tool that does exactly what I want and need! Nothing more, nothing less.
Another project worth mention is meatier: "like meteor, but meatier". It is composed of many other well supported open source projects, so you could even pick and choose.

Categories

Resources