How to make Sails.js app listen to events of ethereum blokchain to perform CRUD on persistence layer - node.js

I have a smart contract deployed on Ethereum blockchain and it emits some event with necessary data.
I have a sails.js application which needs to listen to this event.
Roughly, the javascript code looks like -
var event = contract.myEvent();
event.watch((err, res) => {
console.log(res); // event response
// API call to DB for persistence
});
My question is where should this code sit in sails.js application as sails.js follows MVC, is it a good idea to use sails.js ?
Suggestions about design pattern are appreciated.

This code should be excuted as a Service at the application start time.
for example you can create a file named EventsService.js :
let event = contract.myEvent();
exports.start = function () {
event.watch((err, res) => {
console.log(res); // event response
// API call to DB for persistence
});
}
and then you can start the service like this: (from the app.js file)
const eventService = require('path/to/EventService.js');
eventService.start();

Related

How to get updates from backend automatically in client side

I have 3 apps, mobile app (react native), web app (react js) and a Nodejs app.
the mobile app is an e-commerce mobile app, and the web app is the admin page (client side). The admin page get all data from NodeJs app (api) that use firebase admin sdk.
The problem is that i want everytime a user place an order using the mobile app, the admin page automatically fetch data from NodeJs app.
api code :
router.post("/orders", function(req, res, next) {
const {filterBy} = req.body;
let orders = [];
if(filterBy === "all"){
db.ref("orders").on('value',function(snap){
if(snap.val){
snap.forEach(function(child){
let items = child.val();
orders.push(items);
})
}
})
}else{
db.ref("orders").orderByChild("generalStatus").equalTo(filterBy)
.on('value',function(snap){
if(snap.val){
snap.forEach(function(child){
let items = child.val();
orders.push(items);
})
}
})
}
res.json(orders.reverse());
});
You can create a socket connection between your web-app and backend. Whenever someone places an order on the mobile app, you can fire an event in backend api which the client can listen too.
You can use socket.io https://socket.io/get-started/chat
You can also add listener on firebase document and use the method on to check for any changes in DB eg if you want to get updates from chat db you can use this code e.g.
const chatRef = database().ref(firebaseMessages.CHAT);
let listener = chatRef.on('value', snapshot => {
console.log('User data: ', snapshot.val());
});
//...
// Later when you no longer need the listener
chatRef.off('value', listener);

Data goes null after few successful requests - Node service App pool caching

I have a service built using Node and Express and MongoDB as database. Service is hosted on IIS.
There is a side filter panel section in the application. Since that filters' master information does not change often (Data Size is in KBs), I use basic Node caching technique(no npm package) to avoid going to database on each page load request. Below is the sample Node code:
//main index.js file
SetFiltersList() function is called as Node service is first initialized on IIS, or, when app pool recycles.
(async () => {
await init.SetFiltersList();
})();
//init.js (utility file)
let filtersList = null; // filterList object that keeps list of Filters as cached object
const SetFiltersList = async (_error) => {
//This is a MongoDB database call
result = await defaultState.DEFAULT_STATE.GET("FiltersList");
filtersList = result.filters;
}
//Get filters call
const getFiltersList = () => filtersList;
module.exports = {
FiltersList: getFiltersList
};
//Controller.js
const GETFILTERLIST = async (req, res, next) => {
res.send(init.FiltersList());
}
//Controller Route
approuter.route('/GetFilterList/')
.get(Controller.GETFILTERLIST);
Problem
After few calls, Filters start returning null and strangely when I recycle the Application pool, the Filters starts coming again for sometime and this repeats after period of time.
Any thoughts whats going wrong here and how I can overcome this?

sails.io.js - nodejs - Resourceful PubSub not receiving model events

I am trying to subscribe a nodejs application to model events in sails. Here is my code:
var socketIOClient = require('socket.io-client'),
sailsIOClient = require('sails.io.js');
var io = sailsIOClient(socketIOClient);
io.sails.url = 'http://localhost:1337';
io.socket.on("agent", function(event) {
console.log(event);
})
io.socket.get("/agent", function(resData, jwres) {})
Here is a link to all of the output on the sails server when the client(nodejs) connects:
https://gist.github.com/CiscoKidxx/e5af93ebcc24702ba4f8
My understanding is that when I create a new agent it should trigger a console.log(event) which lists the changes. This is not happening. I do get a "now connected to sails" upon script start up. Any thoughts?
Here is my call to create a new agent in my UserController:
Agent.create({
syncToken: token,
owner: user.id
}).exec(function (err, newAgent) {
Agent.publishUpdate(newAgent.id, {syncToken: newAgent.syncToken});
The server side code snippet above doesn't show a call to Agent.publishCreate in the callback, but rather a publishUpdate.
From what I understand, the publishCreate is only automatically triggered when using the blueprints - but not for programatic calls like your Agent.create above.
So changing it from publishUpdate to publishCreate might fix it in your context.

NodeJS Express Dependency Injection and Database Connections

Coming from a non Node background, my first instinct is to define my service as such
MyService.js
module.exports = new function(dbConnection)
{
// service uses the db
}
Now, I want one open db connection per request, so I define in middleware:
res.locals.db = openDbConnection();
And in some consuming Express api code:
api.js
var MyService = require(./services/MyService')
...
router.get('/foo/:id?', function (req, res) {
var service = new MyService(res.locals.db);
});
Now, being that Node's preferred method of dependency injection is via the require(...) statement, it seems that I shouldn't be using the constructor of MyService for injection of the db.
So let's say I want to have
var db = require('db');
at the top of MyService and then use somehow like db.current....but how would I tie the db to the current res.locals object now that db is a module itself? What's a recommended way of handling this kind of thin in Node?
Updated Answer: 05/02/15
If you want to attach a DB connection to each request object, then use that connection in your service, the connection will have to be passed to myService some how. The example below shows one way of doing that. If we try to use db.current or something to that effect, we'll be storing state in our DB module. In my experience, that will lead to trouble.
Alternatively, I lay out the approach I've used (and still use) in this previous answer. What this means for this example is the following:
// api.js
var MyService = require(./services/MyService')
...
router.get('/foo/:id?', function (req, res) {
MyService.performTask(req.params.id);
});
// MyService.js
var db = require('db');
module.exports = {
performTask: function(id)
{
var connection = db.getOpenConnection();
// Do whatever you want with the connection.
}
}
With this approach, we've decoupled the DB module from the api/app/router modules and only the module that actually uses it will know it exists.
Previous Answer: 05/01/15
What you're talking about could be done using an express middleware. Here's what it might look like:
var db = require('db');
// Attach a DB connection to each request coming in
router.use(req, res, next){
req.locals.db = db.getOpenConnection();
next();
}
// Later on..
router.get('/foo/:id?', function (req, res) {
// We should now have something attached to res.locals.db!
var service = new MyService(res.locals.db);
});
I personally have never seen something like new MyService before in express applications. That doesn't mean it can't be done, but you might consider an approach like this
// router.js
var MyService = require('MyService');
router.get('/foo/:id?', function (req, res) {
MyService.foo(res.locals.db);
});
// MyService.js
module.exports.foo(connection){
// I have a connection!
}

Object oriented style app with express.js and socket.io

I'm building an application in node, using express for simplify things and socket.io for sockets manipulation.
So, while I'm writing my code I realize that it works, but is not the best and elegant solution.
The only thing I want to do is to wrap all the code of the sockets events, and then reuse in more than one page request, so:
app.js
var express = require('express')
, io;
var app = express()
, PORT = 7777;
io = require('socket.io').listen(app.listen(PORT));
app.get("/", function ( req, res ) {
io.socket.on('connection', function ( socket ) {
socket.on('user', function () {
});
socket.on('message', function () {
});
socket.on('getConversation', function ( socket ) {
});
});
res.render('index');
});
But what happens if I want to assign to the /foo and /bar files the same approach?
i.e. I need to get it in a modular or object oriented way, as can be possible.
There is a pattern to do it?
All you're doing here is attaching event listeners to socket.io after someone makes a page request. Then every single request after that would be attaching new event listeners and your server slowly begins to run out of memory as you clog it with new event listeners every time someone makes a page request. It makes no sense to put socket.io code in your route handlers. Take a look at this:
https://www.npmjs.com/package/express.io

Resources