)]}'
{"neutron/db/api.py":[{"author":{"_account_id":17491,"name":"Lujin Luo","email":"luo.lujin@jp.fujitsu.com","username":"Lujin"},"change_message_id":"29dc04b5d819c2a9db7c4f2aec7c42756a9a0bfa","unresolved":false,"context_lines":[{"line_number":320,"context_line":"            if sqlalchemy.inspect(target).persistent:"},{"line_number":321,"context_line":"                sess.expire(target, [relationship_prop.key])"},{"line_number":322,"context_line":""},{"line_number":323,"context_line":"        if relationship_prop.direction is orm.interfaces.ONETOMANY:"},{"line_number":324,"context_line":"            insp \u003d sqlalchemy.inspect(target)"},{"line_number":325,"context_line":"            assert relationship_prop.back_populates"},{"line_number":326,"context_line":"            attr \u003d insp.manager[relationship_prop.back_populates]"},{"line_number":327,"context_line":""},{"line_number":328,"context_line":"            # perform a many-to-one get for the parent.  the"},{"line_number":329,"context_line":"            # PASSIVE_NO_FETCH is so that we do not emit SQL."}],"source_content_type":"text/x-python","patch_set":4,"id":"bf659307_136ad018","line":326,"range":{"start_line":323,"start_character":8,"end_line":326,"end_character":65},"updated":"2018-04-04 08:26:40.000000000","message":"I am testing this patch recently and I found this part of codes I really do not understand. \n\nWhen running python -m testtools.run neutron.tests.unit.agent.test_securitygroups_rpc.SGServerRpcCallBackTestCase.test_security_group_info_for_devices_only_ipv6_rule, it will fail. \n\nThe error message says \u0027Reservation\u0027 does not contain \u0027reservation\u0027 in insp.manager. \n\nSo I checked\ninsp.manager \u003d [\u0027resource_deltas\u0027, \u0027project_id\u0027, \u0027expiration\u0027, \u0027id\u0027, \u0027tenant_id\u0027]\nand relationship_prop.back_populates is \u0027reservation\u0027, because relationship_prop is ResourceDelta (it back populates to reservation). \n\nReservation and ResourceDelta has one-to-many relationship, but \u0027Reservation\u0027 does not refer to itself, then we do not have \u0027reservation\u0027 in insp.manager. Thus it looks to me that these codes work for many-to-many relationship. \n\nI also checked this happens to \u0027Port\u0027 and \u0027IPAllocation\u0027 relationship. But since I have not checked if it works for many-to-many relationship(SecurityGroup and DefaultSecurityGroup?), I am not 100% sure....","commit_id":"dbf0a7a6b067fae12a91ec17804f03162858602f"},{"author":{"_account_id":4694,"name":"Miguel Lavalle","email":"miguel@mlavalle.com","username":"minsel"},"change_message_id":"39f00a369d9abe08e822a54f44a354d6002e8a7e","unresolved":false,"context_lines":[{"line_number":308,"context_line":"#"},{"line_number":309,"context_line":"# TODO(ihrachys) at some point these event handlers should be extended to also"},{"line_number":310,"context_line":"# automatically refresh values for expired attributes"},{"line_number":311,"context_line":"def expire_for_fk_change(target, fk_value, relationship_prop, column_attr):"},{"line_number":312,"context_line":"    sess \u003d orm.object_session(target)"},{"line_number":313,"context_line":""},{"line_number":314,"context_line":"    if sess is not None:"}],"source_content_type":"text/x-python","patch_set":20,"id":"9f6a8fd7_e4e1312c","line":311,"updated":"2018-04-18 22:23:23.000000000","message":"I found the comments Mike wrote in his version of this function very useful in helping me to understand what is going on. IMO, in this change you are using SQLAlchemy that are close to esoteric. Why not help future Neutron devs and preserve or even improve Mike\u0027s comments?","commit_id":"97fbda9c66e7d3ca549525b93c76a08d6315c76d"},{"author":{"_account_id":4694,"name":"Miguel Lavalle","email":"miguel@mlavalle.com","username":"minsel"},"change_message_id":"39f00a369d9abe08e822a54f44a354d6002e8a7e","unresolved":false,"context_lines":[{"line_number":329,"context_line":"                if sqlalchemy.inspect(new).persistent:"},{"line_number":330,"context_line":"                    sess.expire(new, [relationship_prop.back_populates])"},{"line_number":331,"context_line":"    else:"},{"line_number":332,"context_line":"        if target not in _emit_on_pending:"},{"line_number":333,"context_line":"            _emit_on_pending[target] \u003d []"},{"line_number":334,"context_line":"        _emit_on_pending[target].append("},{"line_number":335,"context_line":"            (fk_value, relationship_prop, column_attr))"}],"source_content_type":"text/x-python","patch_set":20,"id":"9f6a8fd7_04f9c5c6","line":332,"updated":"2018-04-18 22:23:23.000000000","message":"In the same spirit of my comment to L311 above, it would be helpful to future readers of this code to indicate that we get to this path as a consequence of L387 below, which in turn is set up when an object is instrumented and L371 is executed?","commit_id":"97fbda9c66e7d3ca549525b93c76a08d6315c76d"},{"author":{"_account_id":4694,"name":"Miguel Lavalle","email":"miguel@mlavalle.com","username":"minsel"},"change_message_id":"39f00a369d9abe08e822a54f44a354d6002e8a7e","unresolved":false,"context_lines":[{"line_number":330,"context_line":"                    sess.expire(new, [relationship_prop.back_populates])"},{"line_number":331,"context_line":"    else:"},{"line_number":332,"context_line":"        if target not in _emit_on_pending:"},{"line_number":333,"context_line":"            _emit_on_pending[target] \u003d []"},{"line_number":334,"context_line":"        _emit_on_pending[target].append("},{"line_number":335,"context_line":"            (fk_value, relationship_prop, column_attr))"},{"line_number":336,"context_line":""}],"source_content_type":"text/x-python","patch_set":20,"id":"9f6a8fd7_04af85e3","line":333,"updated":"2018-04-18 22:23:23.000000000","message":"As usual, it might be very well that I need to be educated on how WeakKeyDictionary and SQLAlchemy work, but I have a concern here. I took your code from this module and the \u0027main\u0027 method from Mike\u0027s code (https://bitbucket.org/zzzeek/sqlalchemy/wiki/UsageRecipes/ExpireRelationshipOnFKChange), to play with it and help me understand the patch. No major changes were necessary, other than adjusting the base model in L361 below and a few imports. You can see the result here: https://gist.github.com/miguellavalle/3a2e02fd6a275a2d8d972392974c9b88. \n\nIf I understand correctly, we are going to get to this line in the patch whenever we change a column in a SQLAlchemy object that represents a relationship. In other words, we get here from L386 below as a result of the execution of something like https://gist.github.com/miguellavalle/3a2e02fd6a275a2d8d972392974c9b88#file-test_sqlalchemy_events-py-L122. What I did in that line was to simulate the case that a column (relationship) is set and then, due to some exception in the Neutron server, the corresponding object never transitions from pending to persistent. The column gets added to the _emit_on_pending dictionary but it never gets removed from it in L345 below. So in my little experiment code, at the end of the program (L156) I can see that we are left with an item in _emit_on_pending:\n\n\n(Pdb) _emit_on_pending.items()\n[(\u003c__main__.Article object at 0x7fcb48ad3050\u003e, [(23, \u003cRelationshipProperty at 0x7fcb4907eaf0; user\u003e, \u0027user_id\u0027)])]\n\n\nIsn\u0027t there the danger that the _emit_on_pending dictionary grows a lot and either accessing it becomes progressively slower and / or we run out of memory?","commit_id":"97fbda9c66e7d3ca549525b93c76a08d6315c76d"},{"author":{"_account_id":4694,"name":"Miguel Lavalle","email":"miguel@mlavalle.com","username":"minsel"},"change_message_id":"39f00a369d9abe08e822a54f44a354d6002e8a7e","unresolved":false,"context_lines":[{"line_number":339,"context_line":""},{"line_number":340,"context_line":""},{"line_number":341,"context_line":"@event.listens_for(orm.session.Session, \"pending_to_persistent\")"},{"line_number":342,"context_line":"def _pending_callables(session, obj):"},{"line_number":343,"context_line":"    if obj is None:"},{"line_number":344,"context_line":"        return"},{"line_number":345,"context_line":"    args \u003d _emit_on_pending.pop(obj, [])"}],"source_content_type":"text/x-python","patch_set":20,"id":"9f6a8fd7_0ea324a0","line":342,"range":{"start_line":342,"start_character":4,"end_line":342,"end_character":22},"updated":"2018-04-18 22:23:23.000000000","message":"nit: Why not \"_pending_to_persistent\"?","commit_id":"97fbda9c66e7d3ca549525b93c76a08d6315c76d"},{"author":{"_account_id":4694,"name":"Miguel Lavalle","email":"miguel@mlavalle.com","username":"minsel"},"change_message_id":"c0bb0453fec42332eb3188640f6a53a42da06415","unresolved":false,"context_lines":[{"line_number":313,"context_line":""},{"line_number":314,"context_line":"    sess \u003d orm.object_session(target)"},{"line_number":315,"context_line":""},{"line_number":316,"context_line":"    # Use subnets and network\u0027s many-to-one relationship as an example"},{"line_number":317,"context_line":"    if sess is not None:"},{"line_number":318,"context_line":"        # optional behavior #1 - expire the \"Network.subnets\""},{"line_number":319,"context_line":"        # collection on the existing \"network\" object"}],"source_content_type":"text/x-python","patch_set":22,"id":"9f6a8fd7_252b6b30","line":316,"updated":"2018-04-20 20:34:31.000000000","message":"I think it was actually a good idea to use the example :-) I\u0027ll just adjust the comment a little bit","commit_id":"3345a0691279512bdab1c5c986902b25bd483121"},{"author":{"_account_id":4694,"name":"Miguel Lavalle","email":"miguel@mlavalle.com","username":"minsel"},"change_message_id":"c0bb0453fec42332eb3188640f6a53a42da06415","unresolved":false,"context_lines":[{"line_number":340,"context_line":"                if sqlalchemy.inspect(new).persistent:"},{"line_number":341,"context_line":"                    sess.expire(new, [relationship_prop.back_populates])"},{"line_number":342,"context_line":"    else:"},{"line_number":343,"context_line":"        # no Session yet, do it later"},{"line_number":344,"context_line":"        if target not in _emit_on_pending:"},{"line_number":345,"context_line":"            _emit_on_pending[target] \u003d []"},{"line_number":346,"context_line":"        _emit_on_pending[target].append("}],"source_content_type":"text/x-python","patch_set":22,"id":"9f6a8fd7_c5238f55","line":343,"updated":"2018-04-20 20:34:31.000000000","message":"I also one to comment how we get to this path","commit_id":"3345a0691279512bdab1c5c986902b25bd483121"}],"neutron/db/db_base_plugin_common.py":[{"author":{"_account_id":11975,"name":"Slawek Kaplonski","email":"skaplons@redhat.com","username":"slaweq"},"change_message_id":"a6db5fcda0afb15f935625823bd0fd1da2093515","unresolved":false,"context_lines":[{"line_number":277,"context_line":"                     page_reverse\u003dFalse):"},{"line_number":278,"context_line":"        pager \u003d base_obj.Pager(sorts, limit, page_reverse, marker)"},{"line_number":279,"context_line":"        filters \u003d filters or {}"},{"line_number":280,"context_line":"        with db_api.context_manager.reader.using(context):"},{"line_number":281,"context_line":"            return subnet_obj.Subnet.get_objects(context, _pager\u003dpager,"},{"line_number":282,"context_line":"                                                 validate_filters\u003dFalse,"},{"line_number":283,"context_line":"                                                 **filters)"}],"source_content_type":"text/x-python","patch_set":13,"id":"bf659307_46ef811d","line":280,"updated":"2018-04-11 19:46:51.000000000","message":"IIUC commet message it is added because segments plugins still uses old code without engine facade. If so, shouldn\u0027t it be considered to remove when segments will be switched to use new facade?","commit_id":"62e5becb7d7dc56587f2119a8fb4385df4c538ac"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"adc3e531be5353bc7a0965ae465d0e77953a53ea","unresolved":false,"context_lines":[{"line_number":277,"context_line":"                     page_reverse\u003dFalse):"},{"line_number":278,"context_line":"        pager \u003d base_obj.Pager(sorts, limit, page_reverse, marker)"},{"line_number":279,"context_line":"        filters \u003d filters or {}"},{"line_number":280,"context_line":"        with db_api.context_manager.reader.using(context):"},{"line_number":281,"context_line":"            return subnet_obj.Subnet.get_objects(context, _pager\u003dpager,"},{"line_number":282,"context_line":"                                                 validate_filters\u003dFalse,"},{"line_number":283,"context_line":"                                                 **filters)"}],"source_content_type":"text/x-python","patch_set":13,"id":"bf659307_4668e11b","line":280,"in_reply_to":"bf659307_46ef811d","updated":"2018-04-11 20:00:54.000000000","message":"Done","commit_id":"62e5becb7d7dc56587f2119a8fb4385df4c538ac"}],"neutron/db/db_base_plugin_v2.py":[{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"1859bd3b1a7508056ce2f6b73e049a7027d9b89d","unresolved":false,"context_lines":[{"line_number":415,"context_line":"                    # test_update_network_with_subnet_set_shared"},{"line_number":416,"context_line":"                    context.session.flush()"},{"line_number":417,"context_line":"                    context.session.expire(network, [\u0027rbac_entries\u0027])"},{"line_number":418,"context_line":"                    getattr(network, \u0027rbac_entries\u0027)"},{"line_number":419,"context_line":"                elif not update_shared and entry:"},{"line_number":420,"context_line":"                    network.rbac_entries.remove(entry)"},{"line_number":421,"context_line":"            # The filter call removes attributes from the body received from"}],"source_content_type":"text/x-python","patch_set":11,"id":"bf659307_64dae1e9","line":418,"updated":"2018-04-10 20:49:21.000000000","message":"need to take a look at that one specifically","commit_id":"fda4c3250568ad962deade9a4f40a26d559ad8ce"},{"author":{"_account_id":9656,"name":"Ihar Hrachyshka","email":"ihrachys@redhat.com","username":"ihrachys","status":"Red Hat Networking Systems Engineer"},"change_message_id":"2b287e2e4b385f26f461bf46ae00b91769d537d3","unresolved":false,"context_lines":[{"line_number":415,"context_line":"                    # test_update_network_with_subnet_set_shared"},{"line_number":416,"context_line":"                    context.session.flush()"},{"line_number":417,"context_line":"                    context.session.expire(network, [\u0027rbac_entries\u0027])"},{"line_number":418,"context_line":"                    getattr(network, \u0027rbac_entries\u0027)"},{"line_number":419,"context_line":"                elif not update_shared and entry:"},{"line_number":420,"context_line":"                    network.rbac_entries.remove(entry)"},{"line_number":421,"context_line":"            # The filter call removes attributes from the body received from"}],"source_content_type":"text/x-python","patch_set":11,"id":"bf659307_9a2f3087","line":418,"in_reply_to":"bf659307_64dae1e9","updated":"2018-04-11 17:05:16.000000000","message":"Done","commit_id":"fda4c3250568ad962deade9a4f40a26d559ad8ce"}]}
