Solved

Trying to use pusher.com to update my highchart spline instead of database polling

Posted on 2013-05-10
5
1,121 Views
Last Modified: 2013-05-12
I have a highchart spline that updates every second to show the incoming call rate per second. So naturally its polling my db each second and returning the amount of calls that have come in during the past second. Not that great. Bit of lag, missing calls, not too great.

function in highchart currently looks like this:
function requestData() { 
$.ajax({ 
    url: 'assets/db/incoming_callrate.php', 
    success: function(point) { 
        var series = chart.series[0], 
            shift = series.data.length > 20; // shift if the series is longer than 20

        // add the point 
        chart.series[0].addPoint(point, true, shift); 

        // call it again after one second 
        setTimeout(requestData, 1000); 
    }, 
    cache: false 
}); 

Open in new window

in my page that the chart resides I am currently using pusher to update what caller number I'm on and to increment a progress bar and trigger a datatable (read: works awesome)

Part of that is below:
channel.bind('newcall', function(data) { 
    if (data['currentcaller']){ 
     document.getElementById("incoming_callers").innerHTML = data['currentcaller']; 
     document.getElementById("bar9").setAttribute('title', data['currentpercent']); 
     var percent = $('#bar9').attr('title'); 
$('#bar9').animate({width: percent},1000);

Open in new window

So in my case if I could somehow trigger my chart each second with the total amount of calls that have occurred in the past second that would be great. Random thoughts were:

I was guessing I need to establish a new variable something like: var callrate = 0;

Then each time pusher sends a notice of a call, increment the call rate up: ++callrate;

and magically somehow: once a second goes by, trigger a function for the chart to update with the total amount of calls that have occurred in the past second and reset the callrate variable to zero for the next second.

Any idea on above?

My database request returns the x and y axis: x being the time() *1000 and y being the amount of callers in one second.
0
Comment
Question by:tjyoung
  • 3
  • 2
5 Comments
 
LVL 25

Expert Comment

by:clockwatcher
Comment Utility
Unless you need data about every single call and if you're going to be updating your chart every second rather than live anyway, it seems like it would make more sense to continue with your call/sec rate.  Use a server process to push the call/sec data to pusher app
    while True:
        data = [time.time() * 1000, randint(0,100) ]  # replace with your db call
        print data
        p['my-ee-app'].trigger('chart-event', data)
        time.sleep(1)

Open in new window

and instead of having your clients poll for it, have them subscribe to that event.  Then you really don't have to change much of anything-- just replace your ajax call with a pusher event.  It should be a lot more efficient than having your client poll.
        channel.bind('chart-event', function(data) {
                var series = chart.series[0];
                shift = series.data.length > 20; // shift if the series is longer than 20
                chart.series[0].addPoint(data, true, shift);
        });

Open in new window



I posted a sample at  http://mostlywrong.info/ee.htm

Full client code
<!DOCTYPE HTML>
<html>
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
		<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>

		<script src="http://js.pusher.com/2.0/pusher.min.js"></script>

		<script type="text/javascript">
var pusher = new Pusher('675505d46e4e94515943');
var channel = pusher.subscribe('my-ee-app');

$(function () {

        var chart = new Highcharts.Chart({
            chart: {
                type: 'spline',
		renderTo: 'container'

            },
            title: {
                text: 'Incoming Calls'
            },
            subtitle: {
                text: 'EE Pusher Test'
            },
            xAxis: {
                type: 'datetime',
		tickPixelInterval: 150,
		maxZoom: 20 * 1000

            },
            yAxis: {
                title: {
                    text: 'Call rate'
                },
                min: 0,
		max: 100,
                minorGridLineWidth: 0,
                gridLineWidth: 0,
            },
            tooltip: {
                valueSuffix: ' calls/sec'
            },
            plotOptions: {
                spline: {
                    lineWidth: 4
                }
            },
            series: [{
                name: 'Call Center',
		data: []
                } ]
            ,
            navigation: {
                menuItemStyle: {
                    fontSize: '10px'
                }
            }
        });

        channel.bind('chart-event', function(data) {
                var series = chart.series[0];
                shift = series.data.length > 20; // shift if the series is longer than 20
                chart.series[0].addPoint(data, true, shift);
        });

    });
    

		</script>
	</head>
	<body>
<script src="./js/highcharts.js"></script>
<script src="./js/modules/exporting.js"></script>

<div id="container" style="min-width: 400px; height: 400px; margin: 0 auto"></div>

	</body>
</html>

Open in new window


Full Server
import ConfigParser
import pusher
import time
from random import randint

def main():
    config = ConfigParser.ConfigParser()
    config.readfp(file('config.ini','r'))
    p = pusher.Pusher(app_id=config.get('pusher','app_id'),
                      key=config.get('pusher','key'),
                      secret=config.get('pusher','secret'))
    while True:
        data = [time.time() * 1000, randint(0,100) ] # replace with db query
        print data
        p['my-ee-app'].trigger('chart-event', data)
        time.sleep(1)

if __name__ == '__main__':
    main()

Open in new window

0
 
LVL 1

Author Comment

by:tjyoung
Comment Utility
This appears to  be brilliant.. so brilliant I dont have a clue about the server part. Where does that go?
Excited at the solution, but dumbfounded at the server part...
0
 
LVL 1

Author Comment

by:tjyoung
Comment Utility
if i understand you right your saying do the db query and send the result each second to pusher to send out.
that sound right?
wouldnt be able to show the server version as php by chance would you?
0
 
LVL 25

Accepted Solution

by:
clockwatcher earned 500 total points
Comment Utility
Here's a php version:
<?php

include './pusher-php-server-master/lib/Pusher.php';

$app_id = 'APP_ID';
$app_key = '675505d46e4e94515943';
$app_secret = 'APP_SECRET_KEY';

$pusher = new Pusher($app_key, $app_secret, $app_id);

while (1) {

        $time_stamp = time() * 1000;
        $calls_per_sec = rand(1,100); // replace with your db query
        $pusher->trigger('my-ee-app', 'chart-event', array($time_stamp, $calls_per_sec));
        sleep(1);
}

?>

Open in new window


The pusher php library is downloadable at https://github.com/pusher/pusher-php-server

You'd need to hook in your database code and would want to run that under php's command line interface (php-cli) on your server-- probably in a supervisord managed process so that it would restart if it goes down.
0
 
LVL 1

Author Closing Comment

by:tjyoung
Comment Utility
Love it
Many thanks!
0

Featured Post

Do You Know the 4 Main Threat Actor Types?

Do you know the main threat actor types? Most attackers fall into one of four categories, each with their own favored tactics, techniques, and procedures.

Join & Write a Comment

What is a Lightbox? A Lightbox is the effect you see when you click, for example, an image and the screen fades out and up pops the same image but in its full size dimensions. There are lots of Lightbox effects for jQuery. Problem is they are a…
Introduction A frequently asked question goes something like this:  "I am running a long process in the background and I want to alert my client when the process finishes.  How can I send a message to the browser?"  Unfortunately, the short answer …
The viewer will learn how to dynamically set the form action using jQuery.
The viewer will learn the basics of jQuery including how to code hide show and toggles. Reference your jQuery libraries: (CODE) Include your new external js/jQuery file: (CODE) Write your first lines of code to setup your site for jQuery…

743 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

16 Experts available now in Live!

Get 1:1 Help Now