)]}'
{"oslo_db/sqlalchemy/update_match.py":[{"author":{"_account_id":9555,"name":"Matthew Booth","email":"mbooth@redhat.com","username":"MatthewBooth"},"change_message_id":"9d8bc0bf1ddcd5637a2594b541ae939bc92fcf26","unresolved":false,"context_lines":[{"line_number":147,"context_line":"       statement, then it fetched immediately following by using"},{"line_number":148,"context_line":"       ``SELECT LAST_INSERT_ID()``."},{"line_number":149,"context_line":"       http://dev.mysql.com/doc/refman/5.0/en/information-\\"},{"line_number":150,"context_line":"       functions.html#function_last-insert-id"},{"line_number":151,"context_line":""},{"line_number":152,"context_line":"    4. Otherwise, for composite keys on MySQL or other backends such"},{"line_number":153,"context_line":"       as SQLite, the row as UPDATED must be re-fetched in order to"}],"source_content_type":"text/x-python","patch_set":1,"id":"3a961159_ea2de7fe","line":150,"updated":"2015-01-12 13:57:10.000000000","message":"Pet peeve: URLS are as long as they are. If you add line breaks, the result is... broken.","commit_id":"48a4f37289de42458439a7c65a8b180d97589fc1"},{"author":{"_account_id":9555,"name":"Matthew Booth","email":"mbooth@redhat.com","username":"MatthewBooth"},"change_message_id":"9d8bc0bf1ddcd5637a2594b541ae939bc92fcf26","unresolved":false,"context_lines":[{"line_number":184,"context_line":""},{"line_number":185,"context_line":"    # TODO (zzzeek): if we need to support IN of multiple values,"},{"line_number":186,"context_line":"    # with or without NULL in it, we can add that here using some"},{"line_number":187,"context_line":"    # additional directives."},{"line_number":188,"context_line":""},{"line_number":189,"context_line":"    criteria \u003d sql.and_(*["},{"line_number":190,"context_line":"        (mapper.column_attrs[key].expression \u003d\u003d value)"}],"source_content_type":"text/x-python","patch_set":1,"id":"3a961159_64904e97","line":187,"updated":"2015-01-12 13:57:10.000000000","message":"This is required if it\u0027s to be used for instance compare and swap in Nova. For examples, check out https://github.com/openstack/nova/blob/master/nova/compute/api.py and search for \u0027expected_task_state\u0027.","commit_id":"48a4f37289de42458439a7c65a8b180d97589fc1"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"3e159e9d24bc847474d2e84387de7dbe2ac811f5","unresolved":false,"context_lines":[{"line_number":33,"context_line":""},{"line_number":34,"context_line":"    E.g.::"},{"line_number":35,"context_line":""},{"line_number":36,"context_line":"        with enginefacade.writer() as session:"},{"line_number":37,"context_line":"            specimen \u003d MyInstance("},{"line_number":38,"context_line":"                uuid\u003d\u0027ccea54f\u0027,"},{"line_number":39,"context_line":"                interface_id\u003d\u0027ad33fea\u0027,"}],"source_content_type":"text/x-python","patch_set":5,"id":"3a961159_d23c72c3","line":36,"updated":"2015-01-19 20:18:42.000000000","message":"SQL statements issued in a compare-and-swap strategy actually should be in separate transactions entirely.","commit_id":"87d2cf2ee4d6239af4f4b15ba2e7b8af57f2c036"},{"author":{"_account_id":11816,"name":"mike bayer","display_name":"Mike Bayer","email":"mike_mp@zzzcomputing.com","username":"zzzeek","status":"Red Hat"},"change_message_id":"6141ec494bb9856b092289520d3b286b67280283","unresolved":false,"context_lines":[{"line_number":33,"context_line":""},{"line_number":34,"context_line":"    E.g.::"},{"line_number":35,"context_line":""},{"line_number":36,"context_line":"        with enginefacade.writer() as session:"},{"line_number":37,"context_line":"            specimen \u003d MyInstance("},{"line_number":38,"context_line":"                uuid\u003d\u0027ccea54f\u0027,"},{"line_number":39,"context_line":"                interface_id\u003d\u0027ad33fea\u0027,"}],"source_content_type":"text/x-python","patch_set":5,"id":"1a930d6b_2bc1d9e4","line":36,"in_reply_to":"3a961159_d23c72c3","updated":"2015-01-20 20:07:03.000000000","message":"yes.  but funny thing, am already in a flamish war about this kind of thing from folks who really don\u0027t want to open new transactions for things with special isolation needs: https://review.openstack.org/#/c/148339/","commit_id":"87d2cf2ee4d6239af4f4b15ba2e7b8af57f2c036"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"3e159e9d24bc847474d2e84387de7dbe2ac811f5","unresolved":false,"context_lines":[{"line_number":51,"context_line":"            hostname_query \u003d model_query("},{"line_number":52,"context_line":"                    context, models.Instance, session\u003dsession,"},{"line_number":53,"context_line":"                    read_deleted\u003d\u0027no\u0027)."},{"line_number":54,"context_line":"                filter(func.lower(models.Instance.hostname) \u003d\u003d \u0027SOMEHOSTNAME\u0027)"},{"line_number":55,"context_line":""},{"line_number":56,"context_line":"            surrogate_key \u003d (\u0027uuid\u0027, )"},{"line_number":57,"context_line":""}],"source_content_type":"text/x-python","patch_set":5,"id":"3a961159_6746a280","line":54,"updated":"2015-01-19 20:18:42.000000000","message":"I think you meant func.upper() :)","commit_id":"87d2cf2ee4d6239af4f4b15ba2e7b8af57f2c036"},{"author":{"_account_id":11816,"name":"mike bayer","display_name":"Mike Bayer","email":"mike_mp@zzzcomputing.com","username":"zzzeek","status":"Red Hat"},"change_message_id":"6141ec494bb9856b092289520d3b286b67280283","unresolved":false,"context_lines":[{"line_number":51,"context_line":"            hostname_query \u003d model_query("},{"line_number":52,"context_line":"                    context, models.Instance, session\u003dsession,"},{"line_number":53,"context_line":"                    read_deleted\u003d\u0027no\u0027)."},{"line_number":54,"context_line":"                filter(func.lower(models.Instance.hostname) \u003d\u003d \u0027SOMEHOSTNAME\u0027)"},{"line_number":55,"context_line":""},{"line_number":56,"context_line":"            surrogate_key \u003d (\u0027uuid\u0027, )"},{"line_number":57,"context_line":""}],"source_content_type":"text/x-python","patch_set":5,"id":"1a930d6b_8baf2d2b","line":54,"in_reply_to":"3a961159_6746a280","updated":"2015-01-20 20:07:03.000000000","message":"fair enough","commit_id":"87d2cf2ee4d6239af4f4b15ba2e7b8af57f2c036"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"3e159e9d24bc847474d2e84387de7dbe2ac811f5","unresolved":false,"context_lines":[{"line_number":76,"context_line":"                surrogate_key,"},{"line_number":77,"context_line":"                values\u003dvalues,"},{"line_number":78,"context_line":"                process_query\u003dprocess_query,"},{"line_number":79,"context_line":"                handle_failure\u003dhandle_failure"},{"line_number":80,"context_line":"            )"},{"line_number":81,"context_line":""},{"line_number":82,"context_line":"    The UPDATE statement is constructed against the given specimen"}],"source_content_type":"text/x-python","patch_set":5,"id":"3a961159_72d1fe55","line":79,"updated":"2015-01-19 20:18:42.000000000","message":"I would actually call the callback \"on_concurrent_change\" and not \"handle_failure\", because at its source, we are actually considering the return of 0 rows_affected to be an expected and forecasted event scenario, not a failure mode at all.\n\nThe failure mode is when repeated loops of the \"SELECT this record, UPDATE this record and ensure the state at time of update is what we expected\" block continues to return 0 rows updated due to thread congestion or starvation.","commit_id":"87d2cf2ee4d6239af4f4b15ba2e7b8af57f2c036"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"3e159e9d24bc847474d2e84387de7dbe2ac811f5","unresolved":false,"context_lines":[{"line_number":101,"context_line":"    The initial check for \"success\" from the UPDATE statement is that the"},{"line_number":102,"context_line":"    number of rows returned matches 1.  If zero rows are matched, then"},{"line_number":103,"context_line":"    the UPDATE statement is assumed to have \"failed\", and the failure handling"},{"line_number":104,"context_line":"    phase begins."},{"line_number":105,"context_line":""},{"line_number":106,"context_line":"    The failure handling phase involves invoking the given ``handle_failure``"},{"line_number":107,"context_line":"    function, if any.  This handler can perform additional queries to attempt"}],"source_content_type":"text/x-python","patch_set":5,"id":"3a961159_92782a80","line":104,"updated":"2015-01-19 20:18:42.000000000","message":"s/the UPDATE statement is assumed to have \"failed\", and the failure handling phase begins/another thread updated the target row in between our initial SELECT of the row and our attempted UPDATE, and we should begin our retry of the SELECT and UPDATE code/","commit_id":"87d2cf2ee4d6239af4f4b15ba2e7b8af57f2c036"},{"author":{"_account_id":7,"name":"Jay Pipes","email":"jaypipes@gmail.com","username":"jaypipes"},"change_message_id":"3e159e9d24bc847474d2e84387de7dbe2ac811f5","unresolved":false,"context_lines":[{"line_number":113,"context_line":""},{"line_number":114,"context_line":"    If the failure handler is not present, or returns False after ``attempts``"},{"line_number":115,"context_line":"    number of attempts, then the function overall raises CantUpdateException."},{"line_number":116,"context_line":"    If the handler returns True, then the function returns with no error."},{"line_number":117,"context_line":""},{"line_number":118,"context_line":"    The return value of the function is the given specimen, which upon success"},{"line_number":119,"context_line":"    will have the given values populated into the object."}],"source_content_type":"text/x-python","patch_set":5,"id":"3a961159_3265b6af","line":116,"updated":"2015-01-19 20:18:42.000000000","message":"I would actually advise having an additional on_retry_failure callback that is executed when the retry loops are exhausted. That way, we can choose to either raise an exception or do something different...","commit_id":"87d2cf2ee4d6239af4f4b15ba2e7b8af57f2c036"},{"author":{"_account_id":9555,"name":"Matthew Booth","email":"mbooth@redhat.com","username":"MatthewBooth"},"change_message_id":"0851224d439b2f8543678d8fe2b5b2d547115c98","unresolved":false,"context_lines":[{"line_number":166,"context_line":"    query \u003d query.filter(criteria)"},{"line_number":167,"context_line":""},{"line_number":168,"context_line":"    if process_query:"},{"line_number":169,"context_line":"        query \u003d process_query(query)"},{"line_number":170,"context_line":""},{"line_number":171,"context_line":"    surrogate_key_arg \u003d ("},{"line_number":172,"context_line":"        surrogate_key, entity.attrs[surrogate_key].loaded_value)"}],"source_content_type":"text/x-python","patch_set":6,"id":"da86d52c_237858c3","line":169,"updated":"2015-02-23 15:18:22.000000000","message":"Can\u0027t the caller just do this before passing in the query?","commit_id":"9bed56cd77a78d6aec3b8fb79c1e9918aceae363"},{"author":{"_account_id":9555,"name":"Matthew Booth","email":"mbooth@redhat.com","username":"MatthewBooth"},"change_message_id":"0851224d439b2f8543678d8fe2b5b2d547115c98","unresolved":false,"context_lines":[{"line_number":172,"context_line":"        surrogate_key, entity.attrs[surrogate_key].loaded_value)"},{"line_number":173,"context_line":"    pk_value \u003d None"},{"line_number":174,"context_line":""},{"line_number":175,"context_line":"    for attempt in range(attempts):"},{"line_number":176,"context_line":"        try:"},{"line_number":177,"context_line":"            pk_value \u003d query.update_returning_pk(values, surrogate_key_arg)"},{"line_number":178,"context_line":"        except MultiRowsMatched:"}],"source_content_type":"text/x-python","patch_set":6,"id":"da86d52c_83dd84df","line":175,"updated":"2015-02-23 15:18:22.000000000","message":"I know my original did this, but I\u0027ve gone off it. This loop is only useful in an extremely obtuse corner case involving 2 consecutive and data-specific races. This will probably never happen in production, but if it even did it would just result in an unnecessary exception. i.e. it\u0027s still safe.\n\nIncluding the loop means we need to pass error handling in as a callback, which is clunky. I think this would be more readable all round if this function simply raised the exception and left the caller to handle it.","commit_id":"9bed56cd77a78d6aec3b8fb79c1e9918aceae363"},{"author":{"_account_id":9555,"name":"Matthew Booth","email":"mbooth@redhat.com","username":"MatthewBooth"},"change_message_id":"ae89b17741ced6b88ac232375ab82bbfbe0ff211","unresolved":false,"context_lines":[{"line_number":239,"context_line":"            raise ValueError(\"full primary key must be present\")"},{"line_number":240,"context_line":""},{"line_number":241,"context_line":"    orm.make_transient_to_detached(specimen)"},{"line_number":242,"context_line":"    session.add(specimen)"},{"line_number":243,"context_line":""},{"line_number":244,"context_line":""},{"line_number":245,"context_line":"def manufacture_entity_criteria(entity, include_only\u003dNone, exclude\u003dNone):"}],"source_content_type":"text/x-python","patch_set":6,"id":"ba7be1f8_b8c91e28","line":242,"updated":"2015-02-24 15:59:10.000000000","message":"So close! Unfortunately this fails if the object being added is already in the session.","commit_id":"9bed56cd77a78d6aec3b8fb79c1e9918aceae363"},{"author":{"_account_id":9555,"name":"Matthew Booth","email":"mbooth@redhat.com","username":"MatthewBooth"},"change_message_id":"3cb00eb214f44005921701a127f29c26161dad8f","unresolved":false,"context_lines":[{"line_number":239,"context_line":"            raise ValueError(\"full primary key must be present\")"},{"line_number":240,"context_line":""},{"line_number":241,"context_line":"    orm.make_transient_to_detached(specimen)"},{"line_number":242,"context_line":"    session.add(specimen)"},{"line_number":243,"context_line":""},{"line_number":244,"context_line":""},{"line_number":245,"context_line":"def manufacture_entity_criteria(entity, include_only\u003dNone, exclude\u003dNone):"}],"source_content_type":"text/x-python","patch_set":6,"id":"ba7be1f8_53fac375","line":242,"in_reply_to":"ba7be1f8_b8c91e28","updated":"2015-02-24 16:14:26.000000000","message":"Specifically I get an error here trying to do Nova Instance compare and swap. Error is this one in WeakInstanceDict.add:\n\n    raise AssertionError(\n        \"A conflicting state is already \"\n        \"present in the identity map for key %r\"\n        % (key, ))\n\nI\u0027m trying to work out what\u0027s going on so I can create a test case, but this seems to be the instance returned by a previous select.","commit_id":"9bed56cd77a78d6aec3b8fb79c1e9918aceae363"},{"author":{"_account_id":9555,"name":"Matthew Booth","email":"mbooth@redhat.com","username":"MatthewBooth"},"change_message_id":"0851224d439b2f8543678d8fe2b5b2d547115c98","unresolved":false,"context_lines":[{"line_number":327,"context_line":"            _sql_crit(expression, set(values).difference(_none_set))"},{"line_number":328,"context_line":"        )"},{"line_number":329,"context_line":"    else:"},{"line_number":330,"context_line":"        return expression.in_(values)"},{"line_number":331,"context_line":""},{"line_number":332,"context_line":""},{"line_number":333,"context_line":"def update_returning_pk(query, values, surrogate_key):"}],"source_content_type":"text/x-python","patch_set":6,"id":"da86d52c_b2bbb8e3","line":330,"updated":"2015-02-23 15:18:22.000000000","message":"I enjoyed reading that :) Elegant use of sets.","commit_id":"9bed56cd77a78d6aec3b8fb79c1e9918aceae363"},{"author":{"_account_id":9555,"name":"Matthew Booth","email":"mbooth@redhat.com","username":"MatthewBooth"},"change_message_id":"7ec4e91f3454b18720f0148ab18a53fd3d472919","unresolved":false,"context_lines":[{"line_number":239,"context_line":"            raise ValueError(\"full primary key must be present\")"},{"line_number":240,"context_line":""},{"line_number":241,"context_line":"    orm.make_transient_to_detached(specimen)"},{"line_number":242,"context_line":"    session.add(specimen)"},{"line_number":243,"context_line":""},{"line_number":244,"context_line":""},{"line_number":245,"context_line":"def manufacture_entity_criteria(entity, include_only\u003dNone, exclude\u003dNone):"}],"source_content_type":"text/x-python","patch_set":7,"id":"ba7be1f8_0e982469","line":242,"updated":"2015-02-24 16:28:24.000000000","message":"I\u0027ve added a test which demonstrates the failure here:\n\nhttps://review.openstack.org/158768","commit_id":"4f1af0cb85e60cb22a6315f2b8b3e0b7c41cbc57"},{"author":{"_account_id":11816,"name":"mike bayer","display_name":"Mike Bayer","email":"mike_mp@zzzcomputing.com","username":"zzzeek","status":"Red Hat"},"change_message_id":"a3b9f7f23e31ffdfb4de16ab602b24a8c8774094","unresolved":false,"context_lines":[{"line_number":239,"context_line":"            raise ValueError(\"full primary key must be present\")"},{"line_number":240,"context_line":""},{"line_number":241,"context_line":"    orm.make_transient_to_detached(specimen)"},{"line_number":242,"context_line":"    session.add(specimen)"},{"line_number":243,"context_line":""},{"line_number":244,"context_line":""},{"line_number":245,"context_line":"def manufacture_entity_criteria(entity, include_only\u003dNone, exclude\u003dNone):"}],"source_content_type":"text/x-python","patch_set":7,"id":"ba7be1f8_d38b281c","line":242,"in_reply_to":"ba7be1f8_0e982469","updated":"2015-03-02 16:49:25.000000000","message":"Done","commit_id":"4f1af0cb85e60cb22a6315f2b8b3e0b7c41cbc57"}]}
