title: How to add new item to asyncio queue as soon as a slot is available?
body: <p>This code works like this:</p>
  <p>List named 'ids' contains id numbers. By id numbers I download specific messages.
  'nDownload' is the list index. The size value of the queue is equal to 5.</p>
  <p>I pick up item from list ,download message one at time and add it to queue.
  When nDownload is equal to 6 :</p>
  <ol>
  <li>QueueFull exception occours.</li>
  <li>Create 5 workers.</li>
  <li>Workers extract metadata from message for other purposes.</li>
  <li>await queue.join() Blocks until all items in the queue have been gotten and processed.</li>
  <li>End -&gt; delete workers.</li>
  </ol>
  <p>The code works, I have no issue until now.</p>
  <pre><code>                nDownload = 0
                  workers = []
                  while (nDownload &lt;= len(ids)):                        
                      try:
                          async for msg in get_messages(channel,ids=ids[nDownload]):
                             nDownload = nDownload + 1
                              try:   
                                  queue.put_nowait(msg)
                              except (asyncio.QueueFull,IndexError) as qErr:
                                  nDownload = nDownload - 1 
                                  workers = [asyncio.create_task(worker(queue)) for _ in range(5)] 
                                  await queue.join() 
                                  for cancel in workers:
                                      cancel.cancel()                                    
                      except IndexError as iErr:
                          break    
  </code></pre>
  <p>Question:
  Sometimes message has different size. For example :</p>
  <p>message 1 =  100MB  downloaded in 8 minutes</p>
  <p>message 2 =  1MB  downloaded in  5 seconds</p>
  <p>Once it has downloaded the shortest message (message 2) , I get a free 'slot' in queue.
  Unfortunately, I have to wait for message 1 because queue.join()</p>
  <p>How do add new item to queue at that time?</p>
  <p>Why Do I use queue.join() ?
  Because I dont know how to add max 5 messages to queue, wait for download it and resume
  I really need download group of messages and not all at once
  Thanks</p>
  <p>EDIT :
  Yes, my worker is defined like this (simplified)</p>
  <pre><code>async def worker(queue):
  while True:
      queue_msg = await queue.get()
      loop = asyncio.get_event_loop()
      try:
          task = loop.create_task(extract(queue_msg))
          await asyncio.wait_for(task, timeout=timeout)
  
      except errors.Fail:
    #Here I have to requeue the message when it fails,
    #so it requeues the ID in order to download the same msg later
       await queue.put(queue_msg.id)
      except asyncio.TimeoutError: 
       #requeue the msg etcc...
  
      finally:    
          queue.task_done()
  </code></pre>
  <p>Your answer is very smart, thanks
  However I choose queue 'size &gt; 1' because I need to refetch the message when it fails the 'extract' task. ( sry I didn't tell you)
  I do not know what's going to happen if queue size = 1 and I try to add item. It's a bit hard this</p>