Commit 7900f62c authored by Marco Flowers's avatar Marco Flowers

Added last_listener_count to the stream Api.

If the id passed in through starting_after or ending_before is
deleted, then the last_listener_count will allow the pagination
to use the last known value of listeners before the stream was
deleted.
parent 6051397b
This diff is collapsed.
This diff is collapsed.
define({ "name": "Icecast Stream Directory API", "version": "0.0.0", "description": "Stream directory api", "title": "Icecast Stream Directory API", "url": "", "order": [ "Streams", "Genres", "Formats" ], "sampleUrl": false, "apidoc": "0.2.0", "generator": { "name": "apidoc", "time": "2015-08-11T07:35:10.997Z", "url": "http://apidocjs.com", "version": "0.13.1" }});
\ No newline at end of file
define({ "name": "Icecast Stream Directory API", "version": "0.0.0", "description": "Stream directory api", "title": "Icecast Stream Directory API", "url": "", "order": [ "Streams", "Genres", "Formats" ], "sampleUrl": false, "apidoc": "0.2.0", "generator": { "name": "apidoc", "time": "2015-08-11T10:02:36.841Z", "url": "http://apidocjs.com", "version": "0.13.1" }});
\ No newline at end of file
......
{ "name": "Icecast Stream Directory API", "version": "0.0.0", "description": "Stream directory api", "title": "Icecast Stream Directory API", "url": "", "order": [ "Streams", "Genres", "Formats" ], "sampleUrl": false, "apidoc": "0.2.0", "generator": { "name": "apidoc", "time": "2015-08-11T07:35:10.997Z", "url": "http://apidocjs.com", "version": "0.13.1" }}
\ No newline at end of file
{ "name": "Icecast Stream Directory API", "version": "0.0.0", "description": "Stream directory api", "title": "Icecast Stream Directory API", "url": "", "order": [ "Streams", "Genres", "Formats" ], "sampleUrl": false, "apidoc": "0.2.0", "generator": { "name": "apidoc", "time": "2015-08-11T10:02:36.841Z", "url": "http://apidocjs.com", "version": "0.13.1" }}
\ No newline at end of file
......
......@@ -85,6 +85,8 @@ app.get('/reloadconfig/:password',function(req, res) {
* @apiParam {Number} limit Number of results to return.
* @apiParam {Number} starting_after ID of stream to return results after(Requires order, cannot have ending_before).
* @apiParam {Number} ending_before ID of stream to return results before(Requires order, cannot have starting_after).
* @apiParam {Number} last_listener_count listener count of the id passed in with starting_after or ending_before. Allows
* pagination to get close if the id passed in is deleted.
*
* @apiSuccess {List} streams List of stream objects(See get individual stream for an example)
* @apiSuccess {Object} data Contains starting_after and ending_before urls for this data
......@@ -106,7 +108,7 @@ app.get('/streams/', function(req,res){
res.set('Content-Type', 'application/json');
var params = req.query;
var json = 1;
streamsFindBy(params.format, params.genre, params.q, params.order, params.limit, params.starting_after, params.ending_before, json, function(err, rows){
streamsFindBy(params.format, params.genre, params.q, params.order, params.limit, params.starting_after, params.ending_before, params.last_listener_count, json, function(err, rows){
if(err) {
if(err.responsecode) {
res.status(err.responsecode);
......@@ -131,14 +133,20 @@ app.get('/streams/', function(req,res){
// delete the previous values
delete params.starting_after;
delete params.ending_before;
delete params.last_listener_count;
// add in the new values
var last_id = rows[0].streams[result.streams.length-1].id;
var last_count = rows[0].streams[result.streams.length-1].listeners;
params.starting_after = last_id;
params.last_listener_count = last_count;
qstring = querystring.stringify(params);
result.data.next_url = req.path+'?'+qstring;
delete params.starting_after;
var prev_id = rows[0].streams[0].id;
var prev_count = rows[0].streams[0].listeners;
params.ending_before = prev_id;
params.last_listener_count = prev_count;
qstring = querystring.stringify(params);
result.data.prev_url = req.path+'?'+qstring;
}
......
......@@ -16,8 +16,9 @@ function index(req, res) {
var limit = 10;
var starting_after = undefined;
var ending_before = undefined;
var last_listener_count = undefined;
var json = 0;
streamsFindBy(format, genre, q, order, limit, starting_after, ending_before, json, function(err, rows) {
streamsFindBy(format, genre, q, order, limit, starting_after, ending_before, last_listener_count, json, function(err, rows) {
if (err) {
res.send(503);
} else {
......
......@@ -18,7 +18,8 @@ function bySearch(req, res) {
var json = 0;
var starting_after = req.param("starting_after");
var ending_before = req.param("ending_before");
streamsFindBy(format, genre, q, order, limit, starting_after, ending_before, json, function(err, rows) {
var last_listener_count = req.param("last_listener_count")
streamsFindBy(format, genre, q, order, limit, starting_after, ending_before, last_listener_count, json, function(err, rows) {
if (err) {
res.send(503);
} else {
......@@ -36,6 +37,7 @@ function bySearch(req, res) {
// clear pagination params
delete params.ending_before;
delete params.starting_after;
delete params.last_count;
qstring = querystring.stringify(params);
home_url = req.path+'?'+qstring;
}
......@@ -43,8 +45,10 @@ function bySearch(req, res) {
// on the fist page and any page with max results show the next button
if(!(starting_after || ending_before) || (result.length == limit)) {
var last_id = rows[result.length-1].id;
var last_count = rows[result.length-1].listeners;
delete params.ending_before;
params.starting_after = last_id;
params.last_listener_count = last_count;
qstring = querystring.stringify(params);
next_url = req.path+'?'+qstring;
}
......@@ -53,8 +57,11 @@ function bySearch(req, res) {
// show the previous button
if((result.length == limit) || (result.length > 0 && starting_after)) {
var prev_id = rows[0].id;
var prev_count = rows[0].listeners;
delete params.starting_after;
params.ending_before = prev_id;
params.last_listener_count = prev_count;
qstring = querystring.stringify(params);
prev_url = req.path+'?'+qstring;
}
......
......@@ -9,12 +9,12 @@ function init(q, c) {
function getCachedStreams(format, genre, q, order, limit, starting_after, ending_before, json, cb) {
var cacheString = JSON.stringify({"format":format, "genre":genre, "q":q, "order":order, "limit":limit, "starting_after":starting_after, "ending_before":ending_before, "json":json});
function getCachedStreams(format, genre, q, order, limit, starting_after, ending_before,last_listener_count, json, cb) {
var cacheString = JSON.stringify({"format":format, "genre":genre, "q":q, "order":order, "limit":limit, "starting_after":starting_after, "ending_before":ending_before, "last_listener_count":last_listener_count, "json":json});
console.log(cacheString);
cache.wrap(cacheString, function (_cb) {
var params = JSON.parse(cacheString);
findBy(params.format, params.genre, params.q, params.order, params.limit, params.starting_after, params.ending_before, params.json, _cb);
findBy(params.format, params.genre, params.q, params.order, params.limit, params.starting_after, params.ending_before, params.last_listener_count, params.json, _cb);
}, 5, cb);
}
......@@ -57,7 +57,7 @@ function getCachedStreams(format, genre, q, order, limit, starting_after, ending
) t
*/
function findBy(format, genre, q, order, limit, starting_after, ending_before, json, resultCallback)
function findBy(format, genre, q, order, limit, starting_after, ending_before, last_listener_count, json, resultCallback)
{
// error handling for arguments
......@@ -105,6 +105,13 @@ function findBy(format, genre, q, order, limit, starting_after, ending_before, j
return;
}
}
if (last_listener_count instanceof String || typeof last_listener_count == "string") {
last_listener_count = parseInt(last_listener_count);
if(isNaN(last_listener_count)) {
resultCallback({"message":"last_listener_count must be numeric","responsecode":400},[]);
return;
}
}
var queryStringJsonBeg = 'SELECT array_to_json(array_agg(row_to_json(t))) AS streams FROM ( \n';
......@@ -204,12 +211,26 @@ function findBy(format, genre, q, order, limit, starting_after, ending_before, j
// add in the Group BY
queryString = queryString + queryStringGroup;
//subQuery to get # listeners for the starting_after/ending_before id
var subQuery = '(SELECT sum(sm.listeners) AS listeners FROM streams s ' +
'INNER JOIN server_mounts AS sm ON s.id = sm.stream_id ' +
'WHERE s.id = $'+ countItems +
'GROUP BY s.id ' +
'LIMIT 1)';
var subQuery;
if(ending_before || starting_after) {
if(last_listener_count != undefined) {
var idNum = countItems+1;
subQuery = 'COALESCE((SELECT sum(sm.listeners) AS listeners FROM streams s ' +
'INNER JOIN server_mounts AS sm ON s.id = sm.stream_id ' +
'WHERE s.id = $'+ idNum +
'GROUP BY s.id ' +
'LIMIT 1), $'+ countItems +' )';
items.push(last_listener_count);
countItems++;
} else {
//subQuery to get # listeners for the starting_after/ending_before id
subQuery = '(SELECT sum(sm.listeners) AS listeners FROM streams s ' +
'INNER JOIN server_mounts AS sm ON s.id = sm.stream_id ' +
'WHERE s.id = $'+ countItems +
'GROUP BY s.id ' +
'LIMIT 1)';
}
}
// pagination need to use HAVING because sum(sm.listeners) will return the
// correct value
......@@ -255,7 +276,6 @@ function findBy(format, genre, q, order, limit, starting_after, ending_before, j
if(json) {
queryString += queryStringJsonEnd;
}
query(queryString, items,function(err, rows){
var result;
if(rows == null) {
......@@ -286,7 +306,6 @@ function findBy(format, genre, q, order, limit, starting_after, ending_before, j
resultCallback(err, result);
return;
}
resultCallback(err, rows);
});
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment