Skip to content

Commit

Permalink
Merge pull request #20 from mWater/issue19
Browse files Browse the repository at this point in the history
fixing Issue19
  • Loading branch information
grassick committed Feb 17, 2016
2 parents 6be6107 + f5e6d13 commit cf4f4bb
Show file tree
Hide file tree
Showing 6 changed files with 102 additions and 14 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
"canonical-json": "0.0.4",
"chai": "^3.4.0",
"coffeeify": "^1.1.0",
"coffee-script": "^1.7.1",
"gulp": "git://github.com/gulpjs/gulp.git#4.0",
"gulp-coffee": "^2.3.1",
"gulp-concat": "^2.6.0",
Expand Down
14 changes: 0 additions & 14 deletions src/DataSource.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,6 @@ async = require 'async'

# Fetches data for queries
module.exports = class DataSource
# Gets the data for a lookup of queries
# e.g. { a: <some jsonql>, b: <some jsonql> }
# Calls cb with (null, { a: <rows for a query>, b: <rows for b query> }
# or (error) if there was an error
performQueries: (queries, cb) ->
async.map _.pairs(queries), (item, callback) =>
@performQuery(item[1], (err, rows) =>
callback(err, [item[0], rows])
)
, (err, items) =>
if err
return cb(err)
else
cb(null, _.object(items))

# Performs a single query. Calls cb with rows
performQuery: (query, cb) ->
Expand Down
30 changes: 30 additions & 0 deletions src/PriorityDataQueue.coffee
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
async = require 'async'

PriorityDataSource = require './PriorityDataSource'

# Creates PriorityDataSource from DataSource
module.exports = class PriorityDataQueue

constructor: (dataSource, concurrency) ->
@dataSource = dataSource
# Creates a priorityQueue that calls performQuery
worker = (query, callback) ->
dataSource.performQuery(query, callback)
@performQueryPriorityQueue = new async.priorityQueue(worker, concurrency)

# Creates a PriorityDataSource that will then be used like a DataSource but with a priority
createPriorityDataSource : (priority) ->
return new PriorityDataSource(this, priority)

# Designed to be called by PriorityDataSource
performQuery: (query, cb, priority) ->
# Push to the priorityQueue
@performQueryPriorityQueue.push query, priority, cb

# Simply call the dataSource since this is not an async function
getImageUrl: (imageId, height) ->
@dataSource.getImageUrl(imageId, height)

kill: () ->
if @performQueryPriorityQueue?
@performQueryPriorityQueue.kill()
15 changes: 15 additions & 0 deletions src/PriorityDataSource.coffee
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@

# Behaves like a DataSource
# Created by a PriorityDataQueue
# Forwards performQuery call to the PriorityDataQueue that will forward them to the DataSource
module.exports = class PriorityDataSource

constructor: (priorityDataQueue, priority) ->
@priorityDataQueue = priorityDataQueue
@priority = priority

performQuery: (query, cb) ->
@priorityDataQueue.performQuery(query, cb, @priority)

getImageUrl: (imageId, height) ->
@priorityDataQueue.getImageUrl(imageId, height)
1 change: 1 addition & 0 deletions src/index.coffee
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
exports.Schema = require './Schema'
exports.DataSource = require './DataSource'
exports.PriorityDataQueue = require './PriorityDataQueue'

exports.ExprCleaner = require './ExprCleaner'
exports.ExprUtils = require './ExprUtils'
Expand Down
55 changes: 55 additions & 0 deletions test/PriorityDataQueueTests.coffee
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
assert = require('chai').assert

PriorityDataQueue = require '../src/PriorityDataQueue'
DataSource = require '../src/DataSource'

# Very simple DataSource implementation used for testing
class TestDataSource extends DataSource
performQuery: (query, cb) ->
# Simply does an async callback passing back the query
call = () ->
cb(query)
setTimeout(call, 1)

describe "PriorityDataQueue", ->
beforeEach ->
testDataSource = new TestDataSource()
@priorityDataQueue = new PriorityDataQueue(testDataSource, 1)

it "calling performQuery reaches the DataSource", (testCallback) ->
priorityDataSource = @priorityDataQueue.createPriorityDataSource(1)
priorityDataSource.performQuery('test', (data) ->
# Make sure that TestDataSource called back with the right data
assert.equal('test', data)
testCallback()
)

it "priorityDataQueue properly prioritize the calls", (testCallback) ->
counter = 0
callDone = (priority) ->
counter++
# Make sure that the priority is called in the right order
assert.equal priority, counter
if counter == 4
testCallback()

priorityDataSource1 = @priorityDataQueue.createPriorityDataSource(1)
priorityDataSource2 = @priorityDataQueue.createPriorityDataSource(2)
priorityDataSource3 = @priorityDataQueue.createPriorityDataSource(3)
priorityDataSource4 = @priorityDataQueue.createPriorityDataSource(4)
# First one needs to be done first since the query is empty and the first call will have best priority
priorityDataSource1.performQuery(1, (data) ->
callDone(1)
)
# Then call with 3
priorityDataSource3.performQuery(3, (data) ->
callDone(3)
)
# Then call with 4
priorityDataSource4.performQuery(4, (data) ->
callDone(4)
)
# Then with 2
priorityDataSource2.performQuery(2, (data) ->
callDone(2)
)

0 comments on commit cf4f4bb

Please sign in to comment.