Delayed::Job.work_off not processing items in the queue in the order in which they were added #15

Open
klingerf opened this Issue Nov 17, 2009 · 4 comments

2 participants

@klingerf

Perhaps the Delayed::Job queue is order agnostic, but I would expect it to process jobs of the same priority in the same order as they were added to the queue.

Here's a failing test that I wrote against one of my models:

def test_delayed_job
comment = Comment.create!(:body => 'This is a comment')
assert_equal 0, Delayed::Job.find(:all).size
comment.send_later(:update_attribute, :body, 'Comment the first')
comment.send_later(:update_attribute, :body, 'Comment the second')
assert_equal [2, 0], Delayed::Job.work_off
assert_equal 'Comment the second', comment.reload.body
end

Unfortunately, that test fails with the following output:

<"Comment the second"> expected but was <"Comment the first">.

The order in which the two updates are dequeued differs from the order in which the two updates were enqueued. Is this the expected behavior?

@nsxdavid

Looking at the code, it is correct that it tries to do this in random order. Over the code to randomize the ordering is probably ill-advised (as a strategy), but even if it is the implementation is buggy.

records.sort { rand() }

This does not do a random sort like you'd expect. Worst case it'll do nothing or even worst worst case it'll be an infinite loop.

I'm going to create a new issue on this.

@nsxdavid

Oops, nope on second thought this does work in terms of being random. I forgot how sort first does a map/collect first.

But does this strategy make sense?

@klingerf

I would disagree that the correct behavior is to dequeue items of the same priority in random order; calling it a queue implies that order should be maintained.

http://en.wikipedia.org/wiki/Queue_%28data_structure%29

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment