def _reserve_resource(resource_id): """ When you wish you queue a task that needs to reserve a resource, you should make a call to this function() first, queueing it in the RESOURCE_MANAGER_QUEUE. This Task will return the name of the queue you should put your task in. Please be sure to also add a task to run _queue_release_resource() in the same queue name that this function returns to you. It is important that _release_resource() is called after your task is completed, regardless of whether your task completes successfully or not. :param resource_id: The name of the resource you wish to reserve for your task. The system will ensure that no other tasks that want that same reservation will run concurrently with yours. :type resource_id: basestring :return: The name of a queue that you should put your task in :rtype: basestring """ reserved_resource = resources.get_or_create_reserved_resource(resource_id) if reserved_resource.assigned_queue is None: # The assigned_queue will be None if the reserved_resource was just created, so we'll # need to assign a queue to it reserved_resource.assigned_queue = resources.get_least_busy_worker( ).queue_name reserved_resource.save() else: # The assigned_queue is set, so we just need to increment the num_reservations on the # reserved resource reserved_resource.increment_num_reservations() return reserved_resource.assigned_queue
def _reserve_resource(resource_id): """ When you wish you queue a task that needs to reserve a resource, you should make a call to this function() first, queueing it in the RESOURCE_MANAGER_QUEUE. This Task will return the name of the queue you should put your task in. Please be sure to also add a task to run _queue_release_resource() in the same queue name that this function returns to you. It is important that _release_resource() is called after your task is completed, regardless of whether your task completes successfully or not. :param resource_id: The name of the resource you wish to reserve for your task. The system will ensure that no other tasks that want that same reservation will run concurrently with yours. :type resource_id: basestring :return: The name of a queue that you should put your task in :rtype: basestring """ reserved_resource = resources.get_or_create_reserved_resource(resource_id) if reserved_resource.assigned_queue is None: # The assigned_queue will be None if the reserved_resource was just created, so we'll # need to assign a queue to it reserved_resource.assigned_queue = resources.get_least_busy_worker().queue_name reserved_resource.save() else: # The assigned_queue is set, so we just need to increment the num_reservations on the # reserved resource reserved_resource.increment_num_reservations() return reserved_resource.assigned_queue
def test_ignores_queues_that_arent_workers(self): """ It is possible for the assigned_queue in a ReservedResource to reference a queue that is not in the workers collection. This test ensures that this queue is properly ignored, even if it is the most "enticing" choice. """ # Set up three Workers, with the least busy one in the middle so that we can # demonstrate that it did pick the least busy and not the last or first. now = datetime.utcnow() worker_1 = Worker('busy_worker', now) worker_2 = Worker('less_busy_worker', now) worker_3 = Worker('most_busy_worker', now) for worker in (worker_1, worker_2, worker_3): worker.save() # Now we need to make some reservations against these Workers' queues. We'll give worker_1 # 8 reservations, putting it in the middle of busyness. rr_1 = ReservedResource(name='resource_1', assigned_queue=worker_1.queue_name, num_reservations=8) # These next two will give worker_2 a total of 7 reservations, so it should get picked. rr_2 = ReservedResource(name='resource_2', assigned_queue=worker_2.queue_name, num_reservations=3) rr_3 = ReservedResource(name='resource_3', assigned_queue=worker_2.queue_name, num_reservations=4) # These next three will give worker_3 a total of 9 reservations, so it should be the most # busy. rr_4 = ReservedResource(name='resource_4', assigned_queue=worker_3.queue_name, num_reservations=2) rr_5 = ReservedResource(name='resource_5', assigned_queue=worker_3.queue_name, num_reservations=3) rr_6 = ReservedResource(name='resource_6', assigned_queue=worker_3.queue_name, num_reservations=4) # Now we will make a ReservedResource that references a queue that does not correspond to a # Worker and has the lowest reservation count. This RR should be ignored. rr_7 = ReservedResource(name='resource_7', assigned_queue='doesnt_exist', num_reservations=1) for rr in (rr_1, rr_2, rr_3, rr_4, rr_5, rr_6, rr_7): rr.save() worker = resources.get_least_busy_worker() self.assertEqual(type(worker), Worker) self.assertEqual(worker.name, 'less_busy_worker')
def test_picks_least_busy_worker(self): """ Test that the function picks the least busy worker. """ # Set up three Workers, with the least busy one in the middle so that we can # demonstrate that it did pick the least busy and not the last or first. now = datetime.utcnow() worker_1 = Worker('busy_worker', now) worker_2 = Worker('less_busy_worker', now) worker_3 = Worker('most_busy_worker', now) for worker in (worker_1, worker_2, worker_3): worker.save() # Now we need to make some reservations against these Workers' queues. We'll give worker_1 # 8 reservations, putting it in the middle of busyness. rr_1 = ReservedResource(name='resource_1', assigned_queue=worker_1.queue_name, num_reservations=8) # These next two will give worker_2 a total of 7 reservations, so it should get picked. rr_2 = ReservedResource(name='resource_2', assigned_queue=worker_2.queue_name, num_reservations=3) rr_3 = ReservedResource(name='resource_3', assigned_queue=worker_2.queue_name, num_reservations=4) # These next three will give worker_3 a total of 9 reservations, so it should be the most # busy. rr_4 = ReservedResource(name='resource_4', assigned_queue=worker_3.queue_name, num_reservations=2) rr_5 = ReservedResource(name='resource_5', assigned_queue=worker_3.queue_name, num_reservations=3) rr_6 = ReservedResource(name='resource_6', assigned_queue=worker_3.queue_name, num_reservations=4) for rr in (rr_1, rr_2, rr_3, rr_4, rr_5, rr_6): rr.save() worker = resources.get_least_busy_worker() self.assertEqual(type(worker), Worker) self.assertEqual(worker.name, 'less_busy_worker')