)]}'
{"nova/context.py":[{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"a387578f205bf5f0b5e7620716770fdc11718a4f","unresolved":false,"context_lines":[{"line_number":430,"context_line":"                 the RequestContext"},{"line_number":431,"context_line":"    :param kwargs: The kwargs for the function to call for each cell"},{"line_number":432,"context_line":"    :param skips: Iterable of cell UUIDs to skip during the scatter gather"},{"line_number":433,"context_line":"    \"\"\""},{"line_number":434,"context_line":"    # We can\u0027t do f(*args, kw\u003dNone, **kwargs) in python 2.x"},{"line_number":435,"context_line":"    skips \u003d kwargs.pop(\u0027skips\u0027, None)"},{"line_number":436,"context_line":"    cell_mappings \u003d objects.CellMappingList.get_all(context)"}],"source_content_type":"text/x-python","patch_set":4,"id":"5f201791_52951932","line":433,"updated":"2017-06-26 19:41:40.000000000","message":":returns:?","commit_id":"81510a893ba285b3e9c669ee4ce54ae476c2047c"},{"author":{"_account_id":4690,"name":"melanie witt","display_name":"melwitt","email":"melwittt@gmail.com","username":"melwitt"},"change_message_id":"28790f2afe3b839776b1aedacb9ce5c0332b3a48","unresolved":false,"context_lines":[{"line_number":430,"context_line":"                 the RequestContext"},{"line_number":431,"context_line":"    :param kwargs: The kwargs for the function to call for each cell"},{"line_number":432,"context_line":"    :param skips: Iterable of cell UUIDs to skip during the scatter gather"},{"line_number":433,"context_line":"    \"\"\""},{"line_number":434,"context_line":"    # We can\u0027t do f(*args, kw\u003dNone, **kwargs) in python 2.x"},{"line_number":435,"context_line":"    skips \u003d kwargs.pop(\u0027skips\u0027, None)"},{"line_number":436,"context_line":"    cell_mappings \u003d objects.CellMappingList.get_all(context)"}],"source_content_type":"text/x-python","patch_set":4,"id":"5f201791_b560d7d0","line":433,"in_reply_to":"5f201791_52951932","updated":"2017-06-26 20:06:22.000000000","message":"Will do.","commit_id":"81510a893ba285b3e9c669ee4ce54ae476c2047c"},{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"a387578f205bf5f0b5e7620716770fdc11718a4f","unresolved":false,"context_lines":[{"line_number":432,"context_line":"    :param skips: Iterable of cell UUIDs to skip during the scatter gather"},{"line_number":433,"context_line":"    \"\"\""},{"line_number":434,"context_line":"    # We can\u0027t do f(*args, kw\u003dNone, **kwargs) in python 2.x"},{"line_number":435,"context_line":"    skips \u003d kwargs.pop(\u0027skips\u0027, None)"},{"line_number":436,"context_line":"    cell_mappings \u003d objects.CellMappingList.get_all(context)"},{"line_number":437,"context_line":"    greenthreads \u003d []"},{"line_number":438,"context_line":"    for cell_mapping in cell_mappings:"}],"source_content_type":"text/x-python","patch_set":4,"id":"5f201791_b2746d37","line":435,"updated":"2017-06-26 19:41:40.000000000","message":"Personally I hate this pattern as I think it\u0027s just asking for a conflict with something you\u0027re trying to run, and it makes it unclear at the call site whether skips goes to the function or this helper.\n\nCould we define two helpers, one that skips cell0 and one that doesn\u0027t, each of which calls an inner helper that takes the cells to skip as a proper param? If you make the latter also public, then someone needing to skip a specific non-cell0 cell could also call that to scratch their itch.","commit_id":"81510a893ba285b3e9c669ee4ce54ae476c2047c"},{"author":{"_account_id":4690,"name":"melanie witt","display_name":"melwitt","email":"melwittt@gmail.com","username":"melwitt"},"change_message_id":"28790f2afe3b839776b1aedacb9ce5c0332b3a48","unresolved":false,"context_lines":[{"line_number":432,"context_line":"    :param skips: Iterable of cell UUIDs to skip during the scatter gather"},{"line_number":433,"context_line":"    \"\"\""},{"line_number":434,"context_line":"    # We can\u0027t do f(*args, kw\u003dNone, **kwargs) in python 2.x"},{"line_number":435,"context_line":"    skips \u003d kwargs.pop(\u0027skips\u0027, None)"},{"line_number":436,"context_line":"    cell_mappings \u003d objects.CellMappingList.get_all(context)"},{"line_number":437,"context_line":"    greenthreads \u003d []"},{"line_number":438,"context_line":"    for cell_mapping in cell_mappings:"}],"source_content_type":"text/x-python","patch_set":4,"id":"5f201791_d567d3e8","line":435,"in_reply_to":"5f201791_b2746d37","updated":"2017-06-26 20:06:22.000000000","message":"I could see that. I thought about making this just take the list of cells to use but that would make people have to do more work. So your suggestion is a good way around.","commit_id":"81510a893ba285b3e9c669ee4ce54ae476c2047c"},{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"360307d9e092ad8d88fd591d653f647d77aa8412","unresolved":false,"context_lines":[{"line_number":432,"context_line":"    :param skips: Iterable of cell UUIDs to skip during the scatter gather"},{"line_number":433,"context_line":"    \"\"\""},{"line_number":434,"context_line":"    # We can\u0027t do f(*args, kw\u003dNone, **kwargs) in python 2.x"},{"line_number":435,"context_line":"    skips \u003d kwargs.pop(\u0027skips\u0027, None)"},{"line_number":436,"context_line":"    cell_mappings \u003d objects.CellMappingList.get_all(context)"},{"line_number":437,"context_line":"    greenthreads \u003d []"},{"line_number":438,"context_line":"    for cell_mapping in cell_mappings:"}],"source_content_type":"text/x-python","patch_set":4,"id":"5f201791_35da874a","line":435,"in_reply_to":"5f201791_d567d3e8","updated":"2017-06-26 20:16:18.000000000","message":"Yeah, having this just do the right thing is good I think. A list of exclusions is the right thing, but make it explicit and then provide some wrappers to make the two cases that will be 99% of the calls easier.","commit_id":"81510a893ba285b3e9c669ee4ce54ae476c2047c"},{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"360307d9e092ad8d88fd591d653f647d77aa8412","unresolved":false,"context_lines":[{"line_number":433,"context_line":"    \"\"\""},{"line_number":434,"context_line":"    # We can\u0027t do f(*args, kw\u003dNone, **kwargs) in python 2.x"},{"line_number":435,"context_line":"    skips \u003d kwargs.pop(\u0027skips\u0027, None)"},{"line_number":436,"context_line":"    cell_mappings \u003d objects.CellMappingList.get_all(context)"},{"line_number":437,"context_line":"    greenthreads \u003d []"},{"line_number":438,"context_line":"    for cell_mapping in cell_mappings:"},{"line_number":439,"context_line":"        if skips and cell_mapping.uuid in skips:"}],"source_content_type":"text/x-python","patch_set":4,"id":"5f201791_d5e4730f","line":436,"updated":"2017-06-26 20:16:18.000000000","message":"Just another thing: we probably want to cache these like we do elsewhere. If we do, we can probably replace a lot of our other static lists with calls to this helper, and then we\u0027ll have fewer places that we cache (and thus need a reset).","commit_id":"81510a893ba285b3e9c669ee4ce54ae476c2047c"},{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"a387578f205bf5f0b5e7620716770fdc11718a4f","unresolved":false,"context_lines":[{"line_number":440,"context_line":"            continue"},{"line_number":441,"context_line":"        with target_cell(context, cell_mapping) as cctxt:"},{"line_number":442,"context_line":"            greenthreads.append(utils.spawn(fn, cctxt, *args, **kwargs))"},{"line_number":443,"context_line":"    return greenthreads"}],"source_content_type":"text/x-python","patch_set":4,"id":"5f201791_92bf31a9","line":443,"updated":"2017-06-26 19:41:40.000000000","message":"So, I wonder if it makes more sense to do the joins here, and just return a list of results. For most operations, I think we\u0027ll want to have a deadline after which we stop waiting, kill the thread, etc. Unifying all that logic in one place makes the most sense to me.\n\nMaybe we return a dict of cell_uuid:result, and specifically set the result for a cell to some DidNotRespond sentinel to indicate that we gave up?","commit_id":"81510a893ba285b3e9c669ee4ce54ae476c2047c"},{"author":{"_account_id":4690,"name":"melanie witt","display_name":"melwitt","email":"melwittt@gmail.com","username":"melwitt"},"change_message_id":"28790f2afe3b839776b1aedacb9ce5c0332b3a48","unresolved":false,"context_lines":[{"line_number":440,"context_line":"            continue"},{"line_number":441,"context_line":"        with target_cell(context, cell_mapping) as cctxt:"},{"line_number":442,"context_line":"            greenthreads.append(utils.spawn(fn, cctxt, *args, **kwargs))"},{"line_number":443,"context_line":"    return greenthreads"}],"source_content_type":"text/x-python","patch_set":4,"id":"5f201791_d5da3376","line":443,"in_reply_to":"5f201791_92bf31a9","updated":"2017-06-26 20:06:22.000000000","message":"I wondered the same thing, so thanks for chiming in. I thought returning greenthreads might be kind of weird but then I thought what if people wanted the flexibility to do the wait however they wanted. And also joining the results here means people would have to do a second loop through N cells to do something with each result. But, I agree usability pattern is better to join the results in here, that way the caller doesn\u0027t need to know anything about it. And they might probably expect them to be joined already.","commit_id":"81510a893ba285b3e9c669ee4ce54ae476c2047c"},{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"360307d9e092ad8d88fd591d653f647d77aa8412","unresolved":false,"context_lines":[{"line_number":440,"context_line":"            continue"},{"line_number":441,"context_line":"        with target_cell(context, cell_mapping) as cctxt:"},{"line_number":442,"context_line":"            greenthreads.append(utils.spawn(fn, cctxt, *args, **kwargs))"},{"line_number":443,"context_line":"    return greenthreads"}],"source_content_type":"text/x-python","patch_set":4,"id":"5f201791_d51fd305","line":443,"in_reply_to":"5f201791_d5da3376","updated":"2017-06-26 20:16:18.000000000","message":"Yeah, I think in almost all cases we\u0027ll just want to provide a timeout and have it do the joining/timeout behavior itself. If we come up with a complicated case that needs the threads itself, we could refactor.","commit_id":"81510a893ba285b3e9c669ee4ce54ae476c2047c"},{"author":{"_account_id":4690,"name":"melanie witt","display_name":"melwitt","email":"melwittt@gmail.com","username":"melwitt"},"change_message_id":"970a355c4c0c5d60626c54237f0278e9788a2ae9","unresolved":false,"context_lines":[{"line_number":451,"context_line":"    results \u003d {}"},{"line_number":452,"context_line":"    for cell_uuid, greenthread in greenthreads.items():"},{"line_number":453,"context_line":"        results[cell_uuid] \u003d eventlet.timeout.with_timeout("},{"line_number":454,"context_line":"            timeout, greenthread.wait, timeout_value\u003ddid_not_respond_sentinel)"},{"line_number":455,"context_line":"    return results"},{"line_number":456,"context_line":""},{"line_number":457,"context_line":""}],"source_content_type":"text/x-python","patch_set":5,"id":"5f201791_a67aebb6","line":454,"updated":"2017-06-26 22:47:06.000000000","message":"I found this method which seems to fit better than the other example of \"with eventlet.timeout.Timeout\" I found in nova/compute/manager.py. Documentation is here:\n\nhttp://eventlet.net/doc/modules/timeout.html#eventlet.timeout.with_timeout","commit_id":"4f6ba29433777001b9eb6cb5da613b4364b624d2"},{"author":{"_account_id":4690,"name":"melanie witt","display_name":"melwitt","email":"melwittt@gmail.com","username":"melwitt"},"change_message_id":"4e1416c88ed5a4e80ef51bd3f89437c514d9c91b","unresolved":false,"context_lines":[{"line_number":451,"context_line":"    results \u003d {}"},{"line_number":452,"context_line":"    for cell_uuid, greenthread in greenthreads.items():"},{"line_number":453,"context_line":"        results[cell_uuid] \u003d eventlet.timeout.with_timeout("},{"line_number":454,"context_line":"            timeout, greenthread.wait, timeout_value\u003ddid_not_respond_sentinel)"},{"line_number":455,"context_line":"    return results"},{"line_number":456,"context_line":""},{"line_number":457,"context_line":""}],"source_content_type":"text/x-python","patch_set":5,"id":"5f201791_bb330162","line":454,"in_reply_to":"5f201791_3b1a5116","updated":"2017-06-27 18:12:35.000000000","message":"I think so ... I had been thinking I needed to do this to know which cells didn\u0027t respond (one timeout per) but now that you say that, I realize I can use the Timeout context manager, loop inside of it, and then if it times out, I just fill in the missing results with \"did not respond.\" So I\u0027ll try that next.","commit_id":"4f6ba29433777001b9eb6cb5da613b4364b624d2"},{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"9cb71d9a99ce0019c50deedfbfc8308acbf6c9cf","unresolved":false,"context_lines":[{"line_number":451,"context_line":"    results \u003d {}"},{"line_number":452,"context_line":"    for cell_uuid, greenthread in greenthreads.items():"},{"line_number":453,"context_line":"        results[cell_uuid] \u003d eventlet.timeout.with_timeout("},{"line_number":454,"context_line":"            timeout, greenthread.wait, timeout_value\u003ddid_not_respond_sentinel)"},{"line_number":455,"context_line":"    return results"},{"line_number":456,"context_line":""},{"line_number":457,"context_line":""}],"source_content_type":"text/x-python","patch_set":5,"id":"5f201791_3b1a5116","line":454,"in_reply_to":"5f201791_a67aebb6","updated":"2017-06-27 18:04:53.000000000","message":"Isn\u0027t this going to serialize us again?","commit_id":"4f6ba29433777001b9eb6cb5da613b4364b624d2"},{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"5435f2f259ebb099cfb9820d86b585274a95a18d","unresolved":false,"context_lines":[{"line_number":451,"context_line":"    results \u003d {}"},{"line_number":452,"context_line":"    for cell_uuid, greenthread in greenthreads.items():"},{"line_number":453,"context_line":"        results[cell_uuid] \u003d eventlet.timeout.with_timeout("},{"line_number":454,"context_line":"            timeout, greenthread.wait, timeout_value\u003ddid_not_respond_sentinel)"},{"line_number":455,"context_line":"    return results"},{"line_number":456,"context_line":""},{"line_number":457,"context_line":""}],"source_content_type":"text/x-python","patch_set":5,"id":"5f201791_fe784790","line":454,"in_reply_to":"5f201791_bb330162","updated":"2017-06-27 18:35:48.000000000","message":"Well, we need to spawn them all in parallel, and then wait for them all to complete with a single timeout.\n\nSo something like (this completely fictitious pseudocode):\n\n  for cell in cells:\n      threads.append((cell, spawn(...)))\n\n  with timeout():\n      for cell, thread in threads:\n          results[cell] \u003d thread.join()\n\n  return results\n\nReally we need to collect all the results that finished, so we can\u0027t do exactly the above, which would block on one thread and avoid collecting the results from later ones that did finish. But you get the idea.\n\nThis conversation is a good demonstration of why it\u0027s a good idea to put this logic in the helper I think :)","commit_id":"4f6ba29433777001b9eb6cb5da613b4364b624d2"},{"author":{"_account_id":4690,"name":"melanie witt","display_name":"melwitt","email":"melwittt@gmail.com","username":"melwitt"},"change_message_id":"1e3a54663e500bebbea0e8c1d639ea8a59ed39f4","unresolved":false,"context_lines":[{"line_number":451,"context_line":"    results \u003d {}"},{"line_number":452,"context_line":"    for cell_uuid, greenthread in greenthreads.items():"},{"line_number":453,"context_line":"        results[cell_uuid] \u003d eventlet.timeout.with_timeout("},{"line_number":454,"context_line":"            timeout, greenthread.wait, timeout_value\u003ddid_not_respond_sentinel)"},{"line_number":455,"context_line":"    return results"},{"line_number":456,"context_line":""},{"line_number":457,"context_line":""}],"source_content_type":"text/x-python","patch_set":5,"id":"5f201791_c47ff563","line":454,"in_reply_to":"5f201791_fe784790","updated":"2017-06-27 22:41:44.000000000","message":"Yeah, I was thinking of the same approach as your example but indeed that would prevent collecting results from other cells if one cell is unresponsive in the middle.\n\nAnd yes, totally agree this is best in the helper. I had fun times learning some new things with the greenthreads. :)","commit_id":"4f6ba29433777001b9eb6cb5da613b4364b624d2"},{"author":{"_account_id":4690,"name":"melanie witt","display_name":"melwitt","email":"melwittt@gmail.com","username":"melwitt"},"change_message_id":"e2a4b8f392c60484c5ab0c371945e6edc5af2aad","unresolved":false,"context_lines":[{"line_number":446,"context_line":"    timeout \u003d 300"},{"line_number":447,"context_line":"    greenthreads \u003d []"},{"line_number":448,"context_line":"    # Keep track of the cells that have results pending."},{"line_number":449,"context_line":"    cell_uuids \u003d set()"},{"line_number":450,"context_line":"    for cell_mapping in cell_mappings:"},{"line_number":451,"context_line":"        cell_uuids.add(cell_mapping.uuid)"},{"line_number":452,"context_line":"        with target_cell(context, cell_mapping) as cctxt:"}],"source_content_type":"text/x-python","patch_set":6,"id":"5f201791_64902196","line":449,"range":{"start_line":449,"start_character":4,"end_line":449,"end_character":14},"updated":"2017-06-27 22:41:52.000000000","message":"Maybe I could have named this better, like \"waiting_for\" or \"pending_cell_uuids\"","commit_id":"a6d53bc7c824d0567cd72cc89827c118bbe8207e"},{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"d8233736641223567ec58b1e497e9d2e9e42950b","unresolved":false,"context_lines":[{"line_number":464,"context_line":"    with eventlet.timeout.Timeout(timeout, exception.CellTimeout):"},{"line_number":465,"context_line":"        try:"},{"line_number":466,"context_line":"            for cell_uuid, greenthread in greenthreads:"},{"line_number":467,"context_line":"                greenthread.link(gather_results, cell_uuid)"},{"line_number":468,"context_line":"                # This is needed to schedule the thread."},{"line_number":469,"context_line":"                time.sleep(0)"},{"line_number":470,"context_line":"            # Wait for all the results."}],"source_content_type":"text/x-python","patch_set":6,"id":"5f201791_39b91578","line":467,"updated":"2017-06-28 16:22:43.000000000","message":"I had to go look at what this does, which might mean it\u0027s more obscure than necessary. However, it does look like it generally does what we want. However, I worry there might be a race condition doing it this way. If you  spawn 8 threads, all initially aren\u0027t linked to a finish function. Then you march through them and link them, but what happens if thread 8 finishes before you get to the linking step? Does the linked method get called even if the thread has finished when you go to link it? I would expect not, since the docs say this gets run \"in the thread\u0027s context\". So, I think you could end up with cases where we end up waiting until the timeout and throwing away some of the results because we raced to setup the link.\n\nInstead, maybe we should just do this ourselves, with a function that wraps the fn and stashes the results when it\u0027s done. Like:\n\n cell_uuids \u003d set()\n def wrapper(cell, fn, args, kwargs):\n     try:\n         cell_uuids[cell] \u003d fn(*args, **kwargs)\n     except:\n         cell_uuids[cell] \u003d None  # or a failed sentinel\n\n for cell in cells:\n     utils.spawn(wrapper, cell, fn, args, kwargs)\n\n with timeout:\n     wait()","commit_id":"a6d53bc7c824d0567cd72cc89827c118bbe8207e"},{"author":{"_account_id":4690,"name":"melanie witt","display_name":"melwitt","email":"melwittt@gmail.com","username":"melwitt"},"change_message_id":"c63f9c1a3bd3a705fd7c7a69d681ee0e59dbd210","unresolved":false,"context_lines":[{"line_number":464,"context_line":"    with eventlet.timeout.Timeout(timeout, exception.CellTimeout):"},{"line_number":465,"context_line":"        try:"},{"line_number":466,"context_line":"            for cell_uuid, greenthread in greenthreads:"},{"line_number":467,"context_line":"                greenthread.link(gather_results, cell_uuid)"},{"line_number":468,"context_line":"                # This is needed to schedule the thread."},{"line_number":469,"context_line":"                time.sleep(0)"},{"line_number":470,"context_line":"            # Wait for all the results."}],"source_content_type":"text/x-python","patch_set":6,"id":"5f201791_68ee9422","line":467,"in_reply_to":"5f201791_39b91578","updated":"2017-06-28 16:59:37.000000000","message":"As discussed on IRC, the link step could be made reliable by moving the yield out of the loop (since it would start all of the threads). But it\u0027s true we can\u0027t rely on the function spawned not to itself yield and start all of the threads early before we\u0027ve linked all of them.\n\nSo, I think I must abandon my link idea. The only way it would work is if I could create the greenthreads ahead without specifying what to spawn, do the link, then give the go-ahead to spawn the function. And I don\u0027t see that ability in the API.","commit_id":"a6d53bc7c824d0567cd72cc89827c118bbe8207e"},{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"d8233736641223567ec58b1e497e9d2e9e42950b","unresolved":false,"context_lines":[{"line_number":472,"context_line":"                if len(cell_uuids) \u003d\u003d 0:"},{"line_number":473,"context_line":"                    break"},{"line_number":474,"context_line":"                # Yield."},{"line_number":475,"context_line":"                time.sleep(0)"},{"line_number":476,"context_line":"        except exception.CellTimeout:"},{"line_number":477,"context_line":"            # Fill in the missing results with the DidNotRespond sentinel."},{"line_number":478,"context_line":"            for cell_uuid, greenthread in greenthreads:"}],"source_content_type":"text/x-python","patch_set":6,"id":"5f201791_59129163","line":475,"updated":"2017-06-28 16:22:43.000000000","message":"This will spin in a hard loop yielding and checking. It\u0027ll be rather expensive CPU-wise. If all the threads block on the database socket, you\u0027ll be the only thing running, and you will burn CPU like you\u0027re in a tight loop.\n\nI think you should use an event or condition variable. That will keep you blocked until the instant that the condition comes true (or the timeout fires) and won\u0027t make you compete for resources with the threads you\u0027re waiting on.","commit_id":"a6d53bc7c824d0567cd72cc89827c118bbe8207e"},{"author":{"_account_id":4690,"name":"melanie witt","display_name":"melwitt","email":"melwittt@gmail.com","username":"melwitt"},"change_message_id":"c63f9c1a3bd3a705fd7c7a69d681ee0e59dbd210","unresolved":false,"context_lines":[{"line_number":472,"context_line":"                if len(cell_uuids) \u003d\u003d 0:"},{"line_number":473,"context_line":"                    break"},{"line_number":474,"context_line":"                # Yield."},{"line_number":475,"context_line":"                time.sleep(0)"},{"line_number":476,"context_line":"        except exception.CellTimeout:"},{"line_number":477,"context_line":"            # Fill in the missing results with the DidNotRespond sentinel."},{"line_number":478,"context_line":"            for cell_uuid, greenthread in greenthreads:"}],"source_content_type":"text/x-python","patch_set":6,"id":"5f201791_74367405","line":475,"in_reply_to":"5f201791_59129163","updated":"2017-06-28 16:59:37.000000000","message":"I wondered about that (spinning in a tight loop). Yeah, condition variable would be the appropriate thing.","commit_id":"a6d53bc7c824d0567cd72cc89827c118bbe8207e"},{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"a4feabb403e1d6aa74fe2887b9688a2848a0c769","unresolved":false,"context_lines":[{"line_number":472,"context_line":"                if len(cell_uuids) \u003d\u003d 0:"},{"line_number":473,"context_line":"                    break"},{"line_number":474,"context_line":"                # Yield."},{"line_number":475,"context_line":"                time.sleep(0)"},{"line_number":476,"context_line":"        except exception.CellTimeout:"},{"line_number":477,"context_line":"            # Fill in the missing results with the DidNotRespond sentinel."},{"line_number":478,"context_line":"            for cell_uuid, greenthread in greenthreads:"}],"source_content_type":"text/x-python","patch_set":6,"id":"5f201791_b45c0c19","line":475,"in_reply_to":"5f201791_59129163","updated":"2017-06-28 16:56:10.000000000","message":"Meant to go look this up before committing my comments, but here:\n\n http://eventlet.net/doc/modules/event.html","commit_id":"a6d53bc7c824d0567cd72cc89827c118bbe8207e"},{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"40dfd3d75354e857ca85789da99a14b9e49c8929","unresolved":false,"context_lines":[{"line_number":451,"context_line":"        def put_result():"},{"line_number":452,"context_line":"            try:"},{"line_number":453,"context_line":"                results[cell_uuid] \u003d fn(*args, **kwargs)"},{"line_number":454,"context_line":"            except exception.CellTimeout:"},{"line_number":455,"context_line":"                results[cell_uuid] \u003d did_not_respond_sentinel"},{"line_number":456,"context_line":"        put_result()"},{"line_number":457,"context_line":""}],"source_content_type":"text/x-python","patch_set":7,"id":"5f201791_3e97b63c","line":454,"updated":"2017-06-28 18:13:13.000000000","message":"This will never get raised by anything we\u0027re going to use this for.\n\nI think you still want to catch any exception and log it, potentially setting a different sentinel to indicate failure or something.","commit_id":"6d9c7ad60f55cbe0e8bfbbbc748ec7472fa359f5"},{"author":{"_account_id":4690,"name":"melanie witt","display_name":"melwitt","email":"melwittt@gmail.com","username":"melwitt"},"change_message_id":"d9b2b59bba5004122775b2016416d3c7d082d002","unresolved":false,"context_lines":[{"line_number":451,"context_line":"        def put_result():"},{"line_number":452,"context_line":"            try:"},{"line_number":453,"context_line":"                results[cell_uuid] \u003d fn(*args, **kwargs)"},{"line_number":454,"context_line":"            except exception.CellTimeout:"},{"line_number":455,"context_line":"                results[cell_uuid] \u003d did_not_respond_sentinel"},{"line_number":456,"context_line":"        put_result()"},{"line_number":457,"context_line":""}],"source_content_type":"text/x-python","patch_set":7,"id":"5f201791_de69e224","line":454,"in_reply_to":"5f201791_3e97b63c","updated":"2017-06-28 18:30:45.000000000","message":"This will be raised for the Timeout case because I passed it on L463. But it\u0027s true other exceptions won\u0027t be caught. I guess I had been thinking if they are going to raise, let them bubble upward and get handled however they would have before parallelizing. But that could lose/mask other failures in other threads. So really we need a different sentinel and to store the exception per thread to return too.","commit_id":"6d9c7ad60f55cbe0e8bfbbbc748ec7472fa359f5"},{"author":{"_account_id":4690,"name":"melanie witt","display_name":"melwitt","email":"melwittt@gmail.com","username":"melwitt"},"change_message_id":"caa22ddefbc87769f32a0ac7b37a7d52bb798643","unresolved":false,"context_lines":[{"line_number":451,"context_line":"        def put_result():"},{"line_number":452,"context_line":"            try:"},{"line_number":453,"context_line":"                results[cell_uuid] \u003d fn(*args, **kwargs)"},{"line_number":454,"context_line":"            except exception.CellTimeout:"},{"line_number":455,"context_line":"                results[cell_uuid] \u003d did_not_respond_sentinel"},{"line_number":456,"context_line":"        put_result()"},{"line_number":457,"context_line":""}],"source_content_type":"text/x-python","patch_set":7,"id":"5f201791_410df3e5","line":454,"in_reply_to":"5f201791_417cd370","updated":"2017-06-28 18:40:44.000000000","message":"Oh. I thought \"current greenthread\" meant in the greenthread we spawned. I really misunderstood that.","commit_id":"6d9c7ad60f55cbe0e8bfbbbc748ec7472fa359f5"},{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"f5e9a2ebac4666a571bc81c544dbbd6a56536383","unresolved":false,"context_lines":[{"line_number":451,"context_line":"        def put_result():"},{"line_number":452,"context_line":"            try:"},{"line_number":453,"context_line":"                results[cell_uuid] \u003d fn(*args, **kwargs)"},{"line_number":454,"context_line":"            except exception.CellTimeout:"},{"line_number":455,"context_line":"                results[cell_uuid] \u003d did_not_respond_sentinel"},{"line_number":456,"context_line":"        put_result()"},{"line_number":457,"context_line":""}],"source_content_type":"text/x-python","patch_set":7,"id":"5f201791_417cd370","line":454,"in_reply_to":"5f201791_8178ab8f","updated":"2017-06-28 18:35:37.000000000","message":"Yeah, Timeout says:\n\n Raises exception in the current greenthread after timeout seconds:\n\nfrom here:\n\nhttp://eventlet.net/doc/modules/timeout.html\n\nThat means we (the caller) receive the timeout exception somewhere in L463-L465 if the timeout expires. Since we don\u0027t catch it, we\u0027ll just propagate CellTimeout to our parent and not return anything.","commit_id":"6d9c7ad60f55cbe0e8bfbbbc748ec7472fa359f5"},{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"0ff9b05fe3b0f6c3cca74341b4118039d87a29ab","unresolved":false,"context_lines":[{"line_number":451,"context_line":"        def put_result():"},{"line_number":452,"context_line":"            try:"},{"line_number":453,"context_line":"                results[cell_uuid] \u003d fn(*args, **kwargs)"},{"line_number":454,"context_line":"            except exception.CellTimeout:"},{"line_number":455,"context_line":"                results[cell_uuid] \u003d did_not_respond_sentinel"},{"line_number":456,"context_line":"        put_result()"},{"line_number":457,"context_line":""}],"source_content_type":"text/x-python","patch_set":7,"id":"5f201791_8178ab8f","line":454,"in_reply_to":"5f201791_de69e224","updated":"2017-06-28 18:33:49.000000000","message":"I don\u0027t think that\u0027s how this works. Pretty sure that L463 will raise CellTimeout, not the thread itself. This code could have already run by the time you run L463 if you did something to yield on L462.","commit_id":"6d9c7ad60f55cbe0e8bfbbbc748ec7472fa359f5"},{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"40dfd3d75354e857ca85789da99a14b9e49c8929","unresolved":false,"context_lines":[{"line_number":462,"context_line":""},{"line_number":463,"context_line":"    with eventlet.timeout.Timeout(timeout, exception.CellTimeout):"},{"line_number":464,"context_line":"        for greenthread in greenthreads:"},{"line_number":465,"context_line":"            greenthread.wait()"},{"line_number":466,"context_line":""},{"line_number":467,"context_line":"    return results"},{"line_number":468,"context_line":""}],"source_content_type":"text/x-python","patch_set":7,"id":"5f201791_3eb0d6dc","line":465,"updated":"2017-06-28 18:13:13.000000000","message":"If you spawn eight threads, and thread three stalls, you\u0027ll never collect the results for the later threads. You\u0027ll wait here until your timeout on L463 explodes, which will raise to our caller, not returning any results at all.","commit_id":"6d9c7ad60f55cbe0e8bfbbbc748ec7472fa359f5"},{"author":{"_account_id":4690,"name":"melanie witt","display_name":"melwitt","email":"melwittt@gmail.com","username":"melwitt"},"change_message_id":"d9b2b59bba5004122775b2016416d3c7d082d002","unresolved":false,"context_lines":[{"line_number":462,"context_line":""},{"line_number":463,"context_line":"    with eventlet.timeout.Timeout(timeout, exception.CellTimeout):"},{"line_number":464,"context_line":"        for greenthread in greenthreads:"},{"line_number":465,"context_line":"            greenthread.wait()"},{"line_number":466,"context_line":""},{"line_number":467,"context_line":"    return results"},{"line_number":468,"context_line":""}],"source_content_type":"text/x-python","patch_set":7,"id":"5f201791_3ee8d679","line":465,"in_reply_to":"5f201791_3eb0d6dc","updated":"2017-06-28 18:30:45.000000000","message":"Yeah ... I was thinking maybe the wrapper approach somehow addressed that and I didn\u0027t quite get it. I went with the link approach earlier because I could let all the threads callback when they were done.\n\nAs discussed on IRC, I was not in the know on Queue and LightQueue. Will change over to that.","commit_id":"6d9c7ad60f55cbe0e8bfbbbc748ec7472fa359f5"},{"author":{"_account_id":4690,"name":"melanie witt","display_name":"melwitt","email":"melwittt@gmail.com","username":"melwitt"},"change_message_id":"abfb23389f278d93610e9220093926f290898797","unresolved":false,"context_lines":[{"line_number":508,"context_line":"    should be of type RequestContext. There is a 60 second timeout for waiting"},{"line_number":509,"context_line":"    on all results to be gathered."},{"line_number":510,"context_line":""},{"line_number":511,"context_line":"    :param context: The RequestContext for querying all CellMappings"},{"line_number":512,"context_line":"    :param fn: The function to call for each cell"},{"line_number":513,"context_line":"    :param args: The args for the function to call for each cell, not including"},{"line_number":514,"context_line":"                 the RequestContext"}],"source_content_type":"text/x-python","patch_set":8,"id":"5f201791_d5365ce8","line":511,"range":{"start_line":511,"start_character":52,"end_line":511,"end_character":68},"updated":"2017-06-28 22:04:36.000000000","message":"I guess this isn\u0027t really correct anymore. Should just be \"cells\"","commit_id":"17fcd1e6020471a8cf528c38d58ffc9f96157774"},{"author":{"_account_id":4690,"name":"melanie witt","display_name":"melwitt","email":"melwittt@gmail.com","username":"melwitt"},"change_message_id":"abfb23389f278d93610e9220093926f290898797","unresolved":false,"context_lines":[{"line_number":532,"context_line":"    should be of type RequestContext. There is a 60 second timeout for waiting"},{"line_number":533,"context_line":"    on all results to be gathered."},{"line_number":534,"context_line":""},{"line_number":535,"context_line":"    :param context: The RequestContext for querying all CellMappings"},{"line_number":536,"context_line":"    :param fn: The function to call for each cell"},{"line_number":537,"context_line":"    :param args: The args for the function to call for each cell, not including"},{"line_number":538,"context_line":"                 the RequestContext"}],"source_content_type":"text/x-python","patch_set":8,"id":"5f201791_9530e4ea","line":535,"range":{"start_line":535,"start_character":52,"end_line":535,"end_character":68},"updated":"2017-06-28 22:04:36.000000000","message":"Same.","commit_id":"17fcd1e6020471a8cf528c38d58ffc9f96157774"},{"author":{"_account_id":4690,"name":"melanie witt","display_name":"melwitt","email":"melwittt@gmail.com","username":"melwitt"},"change_message_id":"9fea364afcc55fc77d9f58747809b4e392e7f75c","unresolved":false,"context_lines":[{"line_number":46,"context_line":"did_not_respond_sentinel \u003d object()"},{"line_number":47,"context_line":"# NOTE(melwitt): Used for the scatter-gather utility to indicate an exception"},{"line_number":48,"context_line":"# was raised gathering a result from a cell."},{"line_number":49,"context_line":"raised_exception_sentinel \u003d object()"},{"line_number":50,"context_line":"# FIXME(danms): Keep a global cache of the cells we find the"},{"line_number":51,"context_line":"# first time we look. This needs to be refreshed on a timer or"},{"line_number":52,"context_line":"# trigger."}],"source_content_type":"text/x-python","patch_set":10,"id":"3f1d235d_41f5d3ca","line":49,"updated":"2017-06-29 19:49:15.000000000","message":"Upon using scatter_gather_all_cells() in the next patch, I\u0027m not sure we should bother returning sentinels for results that didn\u0027t respond or raised exceptions. The caller has to check for them (\"if result not in (sentinels)\") before using a result, and there\u0027s not much I can think of that they can act upon if they get a sentinel. We\u0027re logging errors/warnings in here to avoid callers having to duplicate logging for DidNotRespond/RaisedException wherever they use the utility. If the caller forgets to check for (\"if result not in (sentinels)\") before using a result, they can get TypeErrors from assuming the result they get back will be e.g. an InstanceList or some other usable object.","commit_id":"c7e3149d7203b4753175d873822369f0e3fb4e54"},{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"db0ecb797abc6e87c0c82d84c63a8b5f3a13cb51","unresolved":false,"context_lines":[{"line_number":46,"context_line":"did_not_respond_sentinel \u003d object()"},{"line_number":47,"context_line":"# NOTE(melwitt): Used for the scatter-gather utility to indicate an exception"},{"line_number":48,"context_line":"# was raised gathering a result from a cell."},{"line_number":49,"context_line":"raised_exception_sentinel \u003d object()"},{"line_number":50,"context_line":"# FIXME(danms): Keep a global cache of the cells we find the"},{"line_number":51,"context_line":"# first time we look. This needs to be refreshed on a timer or"},{"line_number":52,"context_line":"# trigger."}],"source_content_type":"text/x-python","patch_set":10,"id":"3f1d235d_773f6dd6","line":49,"in_reply_to":"3f1d235d_41f5d3ca","updated":"2017-06-29 21:38:49.000000000","message":"I think the caller needs to know if either situation happened, although *maybe* not distinguish between failure and no response.\n\nImagine list instances. It will definitely need to do something different if all cells reply, vs. if one doesn\u0027t. Like return a \"Partial result\" code and/or put some instance shells into the result for the missing ones.","commit_id":"c7e3149d7203b4753175d873822369f0e3fb4e54"},{"author":{"_account_id":4690,"name":"melanie witt","display_name":"melwitt","email":"melwittt@gmail.com","username":"melwitt"},"change_message_id":"3f747e62c3ca93447fd349a4635dbb40270287d5","unresolved":false,"context_lines":[{"line_number":46,"context_line":"did_not_respond_sentinel \u003d object()"},{"line_number":47,"context_line":"# NOTE(melwitt): Used for the scatter-gather utility to indicate an exception"},{"line_number":48,"context_line":"# was raised gathering a result from a cell."},{"line_number":49,"context_line":"raised_exception_sentinel \u003d object()"},{"line_number":50,"context_line":"# FIXME(danms): Keep a global cache of the cells we find the"},{"line_number":51,"context_line":"# first time we look. This needs to be refreshed on a timer or"},{"line_number":52,"context_line":"# trigger."}],"source_content_type":"text/x-python","patch_set":10,"id":"3f1d235d_b2663351","line":49,"in_reply_to":"3f1d235d_773f6dd6","updated":"2017-06-29 21:56:06.000000000","message":"Okay, that\u0027s cool. I just wanted to hear some reasons they\u0027re helpful since I was drawing a blank.\n\nFor example, I\u0027ll use it to get quota counts (usage) and if some cells don\u0027t respond, then that usage doesn\u0027t get included. But I don\u0027t know of any way to communicate that to anyone other than in the logs.","commit_id":"c7e3149d7203b4753175d873822369f0e3fb4e54"},{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"db0ecb797abc6e87c0c82d84c63a8b5f3a13cb51","unresolved":false,"context_lines":[{"line_number":474,"context_line":"            while len(results) !\u003d len(greenthreads):"},{"line_number":475,"context_line":"                cell_uuid, result \u003d queue.get()"},{"line_number":476,"context_line":"                results[cell_uuid] \u003d result"},{"line_number":477,"context_line":"        except exception.CellTimeout:"},{"line_number":478,"context_line":"            # NOTE(melwitt): We\u0027ll fill in did_not_respond_sentinels at the"},{"line_number":479,"context_line":"            # same time we kill/wait for the green threads."},{"line_number":480,"context_line":"            pass"}],"source_content_type":"text/x-python","patch_set":10,"id":"3f1d235d_b22cf399","line":477,"updated":"2017-06-29 21:38:49.000000000","message":"I guess this is technically okay, although it makes a lot more sense to me to wrap the with in the try..except block. If you look at this, you\u0027d kinda imagine the timeout coming from L472, which looks like it wouldn\u0027t be caught. In reality, the with alters the thread-switching code to raise on the next switch event if the timeout has expired, which means it\u0027ll actually come from queue.get() in practice.\n\nSo I think this is technically right, but at first glance it didn\u0027t look right to me.","commit_id":"c7e3149d7203b4753175d873822369f0e3fb4e54"},{"author":{"_account_id":4690,"name":"melanie witt","display_name":"melwitt","email":"melwittt@gmail.com","username":"melwitt"},"change_message_id":"3f747e62c3ca93447fd349a4635dbb40270287d5","unresolved":false,"context_lines":[{"line_number":474,"context_line":"            while len(results) !\u003d len(greenthreads):"},{"line_number":475,"context_line":"                cell_uuid, result \u003d queue.get()"},{"line_number":476,"context_line":"                results[cell_uuid] \u003d result"},{"line_number":477,"context_line":"        except exception.CellTimeout:"},{"line_number":478,"context_line":"            # NOTE(melwitt): We\u0027ll fill in did_not_respond_sentinels at the"},{"line_number":479,"context_line":"            # same time we kill/wait for the green threads."},{"line_number":480,"context_line":"            pass"}],"source_content_type":"text/x-python","patch_set":10,"id":"3f1d235d_b2f4f35c","line":477,"in_reply_to":"3f1d235d_b22cf399","updated":"2017-06-29 21:56:06.000000000","message":"Yeah, I guess I could see that. I think I did it this way because of what I read in the documentation and the examples show the Timeout object outside the try-except blocks.","commit_id":"c7e3149d7203b4753175d873822369f0e3fb4e54"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"3c0bbf475fe34e9d99e4dd5c0152441448c06e64","unresolved":false,"context_lines":[{"line_number":474,"context_line":"            while len(results) !\u003d len(greenthreads):"},{"line_number":475,"context_line":"                cell_uuid, result \u003d queue.get()"},{"line_number":476,"context_line":"                results[cell_uuid] \u003d result"},{"line_number":477,"context_line":"        except exception.CellTimeout:"},{"line_number":478,"context_line":"            # NOTE(melwitt): We\u0027ll fill in did_not_respond_sentinels at the"},{"line_number":479,"context_line":"            # same time we kill/wait for the green threads."},{"line_number":480,"context_line":"            pass"}],"source_content_type":"text/x-python","patch_set":10,"id":"3f1d235d_84ae47e5","line":477,"in_reply_to":"3f1d235d_b2f4f35c","updated":"2017-06-30 09:25:44.000000000","message":"I don\u0027t see an example or clarification on this behavior in:\n\nhttp://eventlet.net/doc/modules/timeout.html\n\nBut it says \"Raises exception in the current greenthread after timeout seconds:\" and the queue.get() is blocking, so I guess it makes sense that if get times out it\u0027s going to raise CellTimeout.","commit_id":"c7e3149d7203b4753175d873822369f0e3fb4e54"},{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"db0ecb797abc6e87c0c82d84c63a8b5f3a13cb51","unresolved":false,"context_lines":[{"line_number":485,"context_line":"            greenthread.kill()"},{"line_number":486,"context_line":"            results[cell_uuid] \u003d did_not_respond_sentinel"},{"line_number":487,"context_line":"            LOG.warning(\u0027Timed out waiting for response from cell %s\u0027,"},{"line_number":488,"context_line":"                        cell_uuid)"},{"line_number":489,"context_line":"        else:"},{"line_number":490,"context_line":"            greenthread.wait()"},{"line_number":491,"context_line":""}],"source_content_type":"text/x-python","patch_set":10,"id":"3f1d235d_5240ff35","line":488,"updated":"2017-06-29 21:38:49.000000000","message":"If you put the mapping in greenthreads, you could use cell.identity here, and same on L461. While debugging, it\u0027s so much easier to get the name of the cell (if present) so I assume the same will be true for operators.","commit_id":"c7e3149d7203b4753175d873822369f0e3fb4e54"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"3c0bbf475fe34e9d99e4dd5c0152441448c06e64","unresolved":false,"context_lines":[{"line_number":485,"context_line":"            greenthread.kill()"},{"line_number":486,"context_line":"            results[cell_uuid] \u003d did_not_respond_sentinel"},{"line_number":487,"context_line":"            LOG.warning(\u0027Timed out waiting for response from cell %s\u0027,"},{"line_number":488,"context_line":"                        cell_uuid)"},{"line_number":489,"context_line":"        else:"},{"line_number":490,"context_line":"            greenthread.wait()"},{"line_number":491,"context_line":""}],"source_content_type":"text/x-python","patch_set":10,"id":"3f1d235d_042eb742","line":488,"in_reply_to":"3f1d235d_129287f7","updated":"2017-06-30 09:25:44.000000000","message":"Could do this in a follow up, but agree identity is nice for getting the name in the logs.","commit_id":"c7e3149d7203b4753175d873822369f0e3fb4e54"},{"author":{"_account_id":4690,"name":"melanie witt","display_name":"melwitt","email":"melwittt@gmail.com","username":"melwitt"},"change_message_id":"3f747e62c3ca93447fd349a4635dbb40270287d5","unresolved":false,"context_lines":[{"line_number":485,"context_line":"            greenthread.kill()"},{"line_number":486,"context_line":"            results[cell_uuid] \u003d did_not_respond_sentinel"},{"line_number":487,"context_line":"            LOG.warning(\u0027Timed out waiting for response from cell %s\u0027,"},{"line_number":488,"context_line":"                        cell_uuid)"},{"line_number":489,"context_line":"        else:"},{"line_number":490,"context_line":"            greenthread.wait()"},{"line_number":491,"context_line":""}],"source_content_type":"text/x-python","patch_set":10,"id":"3f1d235d_129287f7","line":488,"in_reply_to":"3f1d235d_5240ff35","updated":"2017-06-29 21:56:06.000000000","message":"Okay, I didn\u0027t know what cell.identity did until now.","commit_id":"c7e3149d7203b4753175d873822369f0e3fb4e54"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"3c0bbf475fe34e9d99e4dd5c0152441448c06e64","unresolved":false,"context_lines":[{"line_number":512,"context_line":"    on all results to be gathered."},{"line_number":513,"context_line":""},{"line_number":514,"context_line":"    :param context: The RequestContext for querying cells"},{"line_number":515,"context_line":"    :param fn: The function to call for each cell"},{"line_number":516,"context_line":"    :param args: The args for the function to call for each cell, not including"},{"line_number":517,"context_line":"                 the RequestContext"},{"line_number":518,"context_line":"    :param kwargs: The kwargs for the function to call for each cell"}],"source_content_type":"text/x-python","patch_set":10,"id":"3f1d235d_b3f74bf6","line":515,"range":{"start_line":515,"start_character":45,"end_line":515,"end_character":49},"updated":"2017-06-30 09:25:44.000000000","message":"for each non-cell0 cell","commit_id":"c7e3149d7203b4753175d873822369f0e3fb4e54"}],"nova/tests/functional/db/test_connection_switch.py":[{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"db0ecb797abc6e87c0c82d84c63a8b5f3a13cb51","unresolved":false,"context_lines":[{"line_number":165,"context_line":"        results \u003d context.scatter_gather_all_cells("},{"line_number":166,"context_line":"            self.context, objects.InstanceList.get_by_filters, filters,"},{"line_number":167,"context_line":"            sort_dir\u003d\u0027asc\u0027)"},{"line_number":168,"context_line":"        instances \u003d objects.InstanceList()"},{"line_number":169,"context_line":"        for result in results.values():"},{"line_number":170,"context_line":"            instances \u003d instances + result"},{"line_number":171,"context_line":""},{"line_number":172,"context_line":"        # Should have 3 instances across cells"},{"line_number":173,"context_line":"        self.assertEqual(3, len(instances))"}],"source_content_type":"text/x-python","patch_set":10,"id":"3f1d235d_f2e26b2f","line":170,"range":{"start_line":168,"start_character":0,"end_line":170,"end_character":42},"updated":"2017-06-29 21:38:49.000000000","message":"itertools.chain.from_iterable(results.values())","commit_id":"c7e3149d7203b4753175d873822369f0e3fb4e54"},{"author":{"_account_id":4690,"name":"melanie witt","display_name":"melwitt","email":"melwittt@gmail.com","username":"melwitt"},"change_message_id":"aa68cdcdc5f6eb04194d93b9ae97a0eddaae1674","unresolved":false,"context_lines":[{"line_number":165,"context_line":"        results \u003d context.scatter_gather_all_cells("},{"line_number":166,"context_line":"            self.context, objects.InstanceList.get_by_filters, filters,"},{"line_number":167,"context_line":"            sort_dir\u003d\u0027asc\u0027)"},{"line_number":168,"context_line":"        instances \u003d objects.InstanceList()"},{"line_number":169,"context_line":"        for result in results.values():"},{"line_number":170,"context_line":"            instances \u003d instances + result"},{"line_number":171,"context_line":""},{"line_number":172,"context_line":"        # Should have 3 instances across cells"},{"line_number":173,"context_line":"        self.assertEqual(3, len(instances))"}],"source_content_type":"text/x-python","patch_set":10,"id":"3f1d235d_f2a82b78","line":170,"range":{"start_line":168,"start_character":0,"end_line":170,"end_character":42},"in_reply_to":"3f1d235d_f2e26b2f","updated":"2017-06-29 21:47:21.000000000","message":"Thanks.","commit_id":"c7e3149d7203b4753175d873822369f0e3fb4e54"}],"nova/tests/unit/test_context.py":[{"author":{"_account_id":4690,"name":"melanie witt","display_name":"melwitt","email":"melwittt@gmail.com","username":"melwitt"},"change_message_id":"970a355c4c0c5d60626c54237f0278e9788a2ae9","unresolved":false,"context_lines":[{"line_number":335,"context_line":"                                       transport_url\u003d\u0027fake://mq1\u0027,"},{"line_number":336,"context_line":"                                       uuid\u003duuids.cell1)"},{"line_number":337,"context_line":"        mappings \u003d objects.CellMappingList(objects\u003d[mapping0, mapping1])"},{"line_number":338,"context_line":"        # Simulate the second cell not responding"},{"line_number":339,"context_line":"        mock_timeout.side_effect \u003d [context.did_not_respond_sentinel,"},{"line_number":340,"context_line":"                                    mock_get.return_value]"},{"line_number":341,"context_line":""}],"source_content_type":"text/x-python","patch_set":5,"id":"5f201791_861b6f7f","line":338,"range":{"start_line":338,"start_character":23,"end_line":338,"end_character":29},"updated":"2017-06-26 22:47:06.000000000","message":"This should be \"first\"","commit_id":"4f6ba29433777001b9eb6cb5da613b4364b624d2"},{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"40dfd3d75354e857ca85789da99a14b9e49c8929","unresolved":false,"context_lines":[{"line_number":338,"context_line":""},{"line_number":339,"context_line":"        # Simulate cell1 not responding."},{"line_number":340,"context_line":"        mock_get.side_effect \u003d [mock.sentinel.instances,"},{"line_number":341,"context_line":"                                exception.CellTimeout()]"},{"line_number":342,"context_line":""},{"line_number":343,"context_line":"        results \u003d context.scatter_gather_cells("},{"line_number":344,"context_line":"            ctxt, mappings, objects.InstanceList.get_by_filters)"}],"source_content_type":"text/x-python","patch_set":7,"id":"5f201791_9ea5aaa1","line":341,"updated":"2017-06-28 18:13:13.000000000","message":"get_by_filters() would never raise this, so this is kinda unrealistic. Also, this doesn\u0027t really test the actual timeout case, where we are blocked on thread.wait() and the eventlet.Timeout fires.","commit_id":"6d9c7ad60f55cbe0e8bfbbbc748ec7472fa359f5"},{"author":{"_account_id":4690,"name":"melanie witt","display_name":"melwitt","email":"melwittt@gmail.com","username":"melwitt"},"change_message_id":"d9b2b59bba5004122775b2016416d3c7d082d002","unresolved":false,"context_lines":[{"line_number":338,"context_line":""},{"line_number":339,"context_line":"        # Simulate cell1 not responding."},{"line_number":340,"context_line":"        mock_get.side_effect \u003d [mock.sentinel.instances,"},{"line_number":341,"context_line":"                                exception.CellTimeout()]"},{"line_number":342,"context_line":""},{"line_number":343,"context_line":"        results \u003d context.scatter_gather_cells("},{"line_number":344,"context_line":"            ctxt, mappings, objects.InstanceList.get_by_filters)"}],"source_content_type":"text/x-python","patch_set":7,"id":"5f201791_fe0ffe33","line":341,"in_reply_to":"5f201791_9ea5aaa1","updated":"2017-06-28 18:30:45.000000000","message":"Yeah, I know. I guess I was too lazy here. Will improve it the next go.","commit_id":"6d9c7ad60f55cbe0e8bfbbbc748ec7472fa359f5"},{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"db0ecb797abc6e87c0c82d84c63a8b5f3a13cb51","unresolved":false,"context_lines":[{"line_number":331,"context_line":"                                          mock_get_result, mock_timeout,"},{"line_number":332,"context_line":"                                          mock_log_warning):"},{"line_number":333,"context_line":"        # This is needed because we\u0027re mocking get_by_filters."},{"line_number":334,"context_line":"        self.useFixture(nova_fixtures.SpawnIsSynchronousFixture())"},{"line_number":335,"context_line":"        ctxt \u003d context.get_context()"},{"line_number":336,"context_line":"        mapping0 \u003d objects.CellMapping(database_connection\u003d\u0027fake://db0\u0027,"},{"line_number":337,"context_line":"                                       transport_url\u003d\u0027none:///\u0027,"}],"source_content_type":"text/x-python","patch_set":10,"id":"3f1d235d_32cc6388","line":334,"updated":"2017-06-29 21:38:49.000000000","message":"I don\u0027t really see how you can test this code with SpawnIsSynchronous. I think you need to keep normal spawn behavior and arrange to avoid blocking for the timeout for the test.","commit_id":"c7e3149d7203b4753175d873822369f0e3fb4e54"},{"author":{"_account_id":4690,"name":"melanie witt","display_name":"melwitt","email":"melwittt@gmail.com","username":"melwitt"},"change_message_id":"aa68cdcdc5f6eb04194d93b9ae97a0eddaae1674","unresolved":false,"context_lines":[{"line_number":331,"context_line":"                                          mock_get_result, mock_timeout,"},{"line_number":332,"context_line":"                                          mock_log_warning):"},{"line_number":333,"context_line":"        # This is needed because we\u0027re mocking get_by_filters."},{"line_number":334,"context_line":"        self.useFixture(nova_fixtures.SpawnIsSynchronousFixture())"},{"line_number":335,"context_line":"        ctxt \u003d context.get_context()"},{"line_number":336,"context_line":"        mapping0 \u003d objects.CellMapping(database_connection\u003d\u0027fake://db0\u0027,"},{"line_number":337,"context_line":"                                       transport_url\u003d\u0027none:///\u0027,"}],"source_content_type":"text/x-python","patch_set":10,"id":"3f1d235d_d2dc0f1a","line":334,"in_reply_to":"3f1d235d_32cc6388","updated":"2017-06-29 21:47:21.000000000","message":"This is tricky because the real spawn won\u0027t work if we mock the function we\u0027re spawning (get_by_filters) because it wants the __name__ of the module or class (I can\u0027t remember) and the MagicMock doesn\u0027t have that. \n\nMy thinking in these tests is to assume the spawn behavior and let the functional test cover the real spawning.\n\nTo get around the MagicMock problem, we could not mock get_by_filters and let it do real DB calls, since it looks like this test class is set up for real DB.","commit_id":"c7e3149d7203b4753175d873822369f0e3fb4e54"},{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"db0ecb797abc6e87c0c82d84c63a8b5f3a13cb51","unresolved":false,"context_lines":[{"line_number":344,"context_line":"        # Simulate cell1 not responding."},{"line_number":345,"context_line":"        mock_get_result.side_effect \u003d [(mapping0.uuid,"},{"line_number":346,"context_line":"                                        mock.sentinel.instances),"},{"line_number":347,"context_line":"                                       exception.CellTimeout()]"},{"line_number":348,"context_line":""},{"line_number":349,"context_line":"        results \u003d context.scatter_gather_cells("},{"line_number":350,"context_line":"            ctxt, mappings, 30, objects.InstanceList.get_by_filters)"}],"source_content_type":"text/x-python","patch_set":10,"id":"3f1d235d_b20993de","line":347,"updated":"2017-06-29 21:38:49.000000000","message":"I don\u0027t think this is testing what you think it is. With SpawnIsSynchronous, this will be raised on the spawn line, not later. That means your wrapper is eating your timeout exception, and you never actually run the timeout-handling code in your queue consumption loop.","commit_id":"c7e3149d7203b4753175d873822369f0e3fb4e54"},{"author":{"_account_id":4690,"name":"melanie witt","display_name":"melwitt","email":"melwittt@gmail.com","username":"melwitt"},"change_message_id":"aa68cdcdc5f6eb04194d93b9ae97a0eddaae1674","unresolved":false,"context_lines":[{"line_number":344,"context_line":"        # Simulate cell1 not responding."},{"line_number":345,"context_line":"        mock_get_result.side_effect \u003d [(mapping0.uuid,"},{"line_number":346,"context_line":"                                        mock.sentinel.instances),"},{"line_number":347,"context_line":"                                       exception.CellTimeout()]"},{"line_number":348,"context_line":""},{"line_number":349,"context_line":"        results \u003d context.scatter_gather_cells("},{"line_number":350,"context_line":"            ctxt, mappings, 30, objects.InstanceList.get_by_filters)"}],"source_content_type":"text/x-python","patch_set":10,"id":"3f1d235d_9234574c","line":347,"in_reply_to":"3f1d235d_b20993de","updated":"2017-06-29 21:47:21.000000000","message":"No, this is mock_get_result, which is eventlet.queue.LightQueue.get, so that\u0027s where it\u0027s raising from. I should have named the variable better.","commit_id":"c7e3149d7203b4753175d873822369f0e3fb4e54"},{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"d3eafe71098ca67f17fb361803e66664453f8965","unresolved":false,"context_lines":[{"line_number":344,"context_line":"        # Simulate cell1 not responding."},{"line_number":345,"context_line":"        mock_get_result.side_effect \u003d [(mapping0.uuid,"},{"line_number":346,"context_line":"                                        mock.sentinel.instances),"},{"line_number":347,"context_line":"                                       exception.CellTimeout()]"},{"line_number":348,"context_line":""},{"line_number":349,"context_line":"        results \u003d context.scatter_gather_cells("},{"line_number":350,"context_line":"            ctxt, mappings, 30, objects.InstanceList.get_by_filters)"}],"source_content_type":"text/x-python","patch_set":10,"id":"3f1d235d_72b65bdc","line":347,"in_reply_to":"3f1d235d_b20993de","updated":"2017-06-29 21:43:13.000000000","message":"Oh nevermind, after downloading I see this is the queue.get() not the InstanceList.get().","commit_id":"c7e3149d7203b4753175d873822369f0e3fb4e54"},{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"db0ecb797abc6e87c0c82d84c63a8b5f3a13cb51","unresolved":false,"context_lines":[{"line_number":350,"context_line":"            ctxt, mappings, 30, objects.InstanceList.get_by_filters)"},{"line_number":351,"context_line":"        self.assertEqual(2, len(results))"},{"line_number":352,"context_line":"        self.assertIn(mock.sentinel.instances, results.values())"},{"line_number":353,"context_line":"        self.assertIn(context.did_not_respond_sentinel, results.values())"},{"line_number":354,"context_line":"        mock_timeout.assert_called_once_with(30, exception.CellTimeout)"},{"line_number":355,"context_line":"        self.assertTrue(mock_log_warning.called)"},{"line_number":356,"context_line":""}],"source_content_type":"text/x-python","patch_set":10,"id":"3f1d235d_12f047c9","line":353,"updated":"2017-06-29 21:38:49.000000000","message":"Although this is in here, which is confusing to me.","commit_id":"c7e3149d7203b4753175d873822369f0e3fb4e54"}]}
