3
votes

The program I am writing is a status display screen for alarms, each of which is represented by a channel.

When the server is started (run on a vagrant virtual machine), an Influx database is accessed, the data (comprising of 1574 'channels') is processed and put into a Redis database. This runs fine and the GUI is displayed with no issues when the webpage is refreshed, although it takes a long time to load (up to 20s), and nearly all of this time is spent in the method below.

However, after a few refreshes/moving around the site, it often crashes with the following error:

{ AbortError: Redis connection lost and command aborted. It might have been processed. at RedisClient.flush_and_error (/vagrant/node_modules/redis/index.js:362:23) at RedisClient.connection_gone (/vagrant/node_modules/redis/index.js:664:14) at RedisClient.on_error (/vagrant/node_modules/redis/index.js:410:10) at Socket. (/vagrant/node_modules/redis/index.js:279:14) at emitOne (events.js:116:13) at Socket.emit (events.js:211:7) at onwriteError (_stream_writable.js:417:12) at onwrite (_stream_writable.js:439:5) at _destroy (internal/streams/destroy.js:39:7) at Socket._destroy (net.js:568:3) code: 'UNCERTAIN_STATE', command: 'HGETALL', args: [ 'vista:hash:Result:44f59707-c873-11e8-93b9-7f551d0bdd1f' ], origin: { Error: Redis connection to 127.0.0.1:6379 failed - write EPIPE at WriteWrap.afterWrite (net.js:868:14) errno: 'EPIPE', code: 'EPIPE', syscall: 'write' } }

This error is displayed 1574 times (once for each channel), and occurs when the program reaches this function:

 Result.getFormattedResults = async function (cycle) {
    const channels = await Channel.findAndLoad()
    const formattedResults = await mapAsyncParallel(channels, async channel => {
        const result = await this.findAndLoadByChannel(channel, cycle)
        const formattedResult = await result.format(channel)
        return formattedResult
    })
    return formattedResults
} 

mapAsyncParallel() is as follows:

export const mapAsyncParallel = (arr, fn, thisArg) => {
    return Promise.all(arr.map(fn, thisArg))
}

findAndLoadByChannel() finds the channel and loads it with this line:

const resultModel = await this.load(resultId)

And format() takes the model and outputs the data as in a JSON format

There are two 'fetch(...)' commands (which are needed and cannot be combined) in the front end, and the problem rarely occurs when I comment out one of them (either one). This is making me think it could be a max memory or max connections problem? (increasing maxmemory in the config file didn't help). Or a problem with using so many promises (a concept I am fairly new to).

This has only started to occur as I have added more functionality and I assume the function needs optimizing but I have taken over this project from someone else and am still quite new to node.js and redis.

Versions:

  • Vagrant: 2.0.1
  • Ubuntu: 16.04.5
  • Redis: 4.0.9
  • Node: 8.12.0
  • npm: 5.7.1
1
did you get exact reason for this problem?Nikhil Manapure
What do you mean by a reason? As I said, my theory is that the loss of connection is due to too much work being done in the asynchronous function, but I was hoping someone else could tell me the reason for certainCharlie

1 Answers

0
votes

I've now moved all the 'getting' of the data (from redis) to the server side channels.controller file.

So, where before I would have:

renderPage: async (req, res) => {
    res.render('page')
},

I now have a method like:

renderPage: async (req, res) => {
        const data1 = getData1()
        const data2 = getData2()
        res.render('page',  {data1, data2})
}, 

(Don't worry, these aren't my actual variable names)

Where the two 'data' variables were previously retrieved using the 'fetch' method.

I export the data once it's loaded into redis, and import it in the controller file, where I have the getters to combine it all into one return array.

The pages now take milliseconds to refresh and I haven't had any crashes