)]}'
{"/COMMIT_MSG":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"6fa418271671f06f1a35aca6b0e4e7ad430aed17","unresolved":false,"context_lines":[{"line_number":10,"context_line":"configure the object_expirer_task_container_per_day to increase the"},{"line_number":11,"context_line":"number of task_containers created per day beyond the default value of"},{"line_number":12,"context_line":"one hundred to any value that better matches their clusters topology and"},{"line_number":13,"context_line":"userage of the x-delete-at feature."},{"line_number":14,"context_line":""},{"line_number":15,"context_line":"UpgradeImpact: Two existing expirer options have been deprecated"},{"line_number":16,"context_line":""}],"source_content_type":"text/x-gerrit-commit-message","patch_set":5,"id":"d85f0b91_f3c271a8","line":13,"updated":"2024-06-14 01:27:04.000000000","message":"s/userage/usage/","commit_id":"c6e36d1e962e8eba623bdb086b5522e40368339e"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"296beca32dc11b900b395aa306e293bbda879e69","unresolved":false,"context_lines":[{"line_number":4,"context_line":"Commit:     Clay Gerrard \u003cclay.gerrard@gmail.com\u003e"},{"line_number":5,"context_line":"CommitDate: 2024-07-10 16:34:02 -0500"},{"line_number":6,"context_line":""},{"line_number":7,"context_line":"Configurable object_expirer_task_container_per_day"},{"line_number":8,"context_line":""},{"line_number":9,"context_line":"In order to better scale the object-expirer cluster operators may"},{"line_number":10,"context_line":"configure object_expirer_task_container_per_day to increase the number"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":10,"id":"5f5c3df5_a854b9ed","line":7,"range":{"start_line":7,"start_character":13,"end_line":7,"end_character":50},"updated":"2024-07-19 14:05:59.000000000","message":"It\u0027s ``expiring_objects_task_container_per_day`` 😊","commit_id":"6fe94c3c0074b7e4d74d7cf23a198b869e816ce7"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"12adff2a771a5e59e495ec6d7ea55e28557d5245","unresolved":true,"context_lines":[{"line_number":17,"context_line":"UpgradeImpact:"},{"line_number":18,"context_line":""},{"line_number":19,"context_line":"Operators are encouraged to remove their \"container_divisor\" setting and"},{"line_number":20,"context_line":"use the default value of 86400."},{"line_number":21,"context_line":""},{"line_number":22,"context_line":"If a cluster was deployed with a non-standard \"account_name\" operators"},{"line_number":23,"context_line":"should remove the option from all configs so they are using a supported"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":25,"id":"790e5039_997eb505","line":20,"updated":"2024-11-01 21:27:32.000000000","message":"Any knock-on effects here?","commit_id":"4639e066e36bc3436c0d8555a536e96795218141"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"d0f98cfd362e46a234f338320f8ee19044d5e31d","unresolved":false,"context_lines":[{"line_number":17,"context_line":"UpgradeImpact:"},{"line_number":18,"context_line":""},{"line_number":19,"context_line":"Operators are encouraged to remove their \"container_divisor\" setting and"},{"line_number":20,"context_line":"use the default value of 86400."},{"line_number":21,"context_line":""},{"line_number":22,"context_line":"If a cluster was deployed with a non-standard \"account_name\" operators"},{"line_number":23,"context_line":"should remove the option from all configs so they are using a supported"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":25,"id":"87e48ed9_494c3d6d","line":20,"in_reply_to":"790e5039_997eb505","updated":"2024-11-05 00:21:48.000000000","message":"Depending on what value they might have set it to they could get those new log messages about unexpected containers.  I\u0027d assume if anything they might have *lowered* the value \"trying\" to get more task containers per day - but it only works if users set expiration at different midnights.\n\nEverything will still get expirered as intended regardless.  But anytime you change any of these values there\u0027s some chance to get those orphaned task objects that 412.  I don\u0027t think that\u0027s a good enough reason not to fix this value if they\u0027ve configured it tho - we\u0027re deprecating it exactly because changing it causes these problems and it doesn\u0027t do what you want anyway.\n\nIf they upgrade to a new swift that lets them set \"container_divisor\" back to 86400 and task_container_per_day to match their *actual* desired hashing AND run expirer-rebalance they\u0027ll be all set!","commit_id":"4639e066e36bc3436c0d8555a536e96795218141"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"e661a73d674cf561ab30863a6abc5747d5478408","unresolved":true,"context_lines":[{"line_number":17,"context_line":"UpgradeImpact:"},{"line_number":18,"context_line":""},{"line_number":19,"context_line":"Operators are encouraged to remove their \"container_divisor\" setting and"},{"line_number":20,"context_line":"use the default value of 86400."},{"line_number":21,"context_line":""},{"line_number":22,"context_line":"If a cluster was deployed with a non-standard \"account_name\", operators"},{"line_number":23,"context_line":"should remove the option from all configs so they are using a supported"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":36,"id":"729ab939_90b6e988","line":20,"updated":"2025-02-07 21:25:30.000000000","message":"This will cause log lines like\n```\nprocessing N unexpected task containers (e.g. ...)\n```\nevery run until all old tasks get processed, is that right? Will running the migrator script in the next patch get things moved to the expected places?","commit_id":"b69a2bef45b100a2bc06b7fbb2eacd06380b117b"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"cc53537bdc2eabaf6787d0c01d044aaf13dc8d71","unresolved":true,"context_lines":[{"line_number":17,"context_line":"UpgradeImpact:"},{"line_number":18,"context_line":""},{"line_number":19,"context_line":"Operators are encouraged to remove their \"container_divisor\" setting and"},{"line_number":20,"context_line":"use the default value of 86400."},{"line_number":21,"context_line":""},{"line_number":22,"context_line":"If a cluster was deployed with a non-standard \"account_name\", operators"},{"line_number":23,"context_line":"should remove the option from all configs so they are using a supported"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":36,"id":"40e31c0e_e063147b","line":20,"in_reply_to":"729ab939_90b6e988","updated":"2025-02-08 01:07:26.000000000","message":"yes, every expirer iteration until all old tasks get processed. but it\u0027s only going to print out 5 container examples stored in ``unexpected_task_containers[\u0027examples\u0027]``.","commit_id":"b69a2bef45b100a2bc06b7fbb2eacd06380b117b"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"e661a73d674cf561ab30863a6abc5747d5478408","unresolved":true,"context_lines":[{"line_number":23,"context_line":"should remove the option from all configs so they are using a supported"},{"line_number":24,"context_line":"configuration going forward, but will need to deploy stand-alone expirer"},{"line_number":25,"context_line":"processes with legacy expirer config to clean-up old expiration tasks"},{"line_number":26,"context_line":"from the previously configured account name."},{"line_number":27,"context_line":""},{"line_number":28,"context_line":"Co-Authored-By: Alistair Coles \u003calistairncoles@gmail.com\u003e"},{"line_number":29,"context_line":"Co-Authored-By: Jianjian Huo \u003cjhuo@nvidia.com\u003e"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":36,"id":"fd1dfa4a_2affb836","line":26,"updated":"2025-02-07 21:25:30.000000000","message":"The migration script definitely *doesn\u0027t* help here -- continuing to run some separate expirers with the legacy config seems like the way to go. The fact that you basically need to do that *indefinitely*, though, makes me wonder whether anyone would actually bother to change, or if they\u0027d just continue using their configured account and keep to the single set of expirers.","commit_id":"b69a2bef45b100a2bc06b7fbb2eacd06380b117b"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"cc53537bdc2eabaf6787d0c01d044aaf13dc8d71","unresolved":false,"context_lines":[{"line_number":23,"context_line":"should remove the option from all configs so they are using a supported"},{"line_number":24,"context_line":"configuration going forward, but will need to deploy stand-alone expirer"},{"line_number":25,"context_line":"processes with legacy expirer config to clean-up old expiration tasks"},{"line_number":26,"context_line":"from the previously configured account name."},{"line_number":27,"context_line":""},{"line_number":28,"context_line":"Co-Authored-By: Alistair Coles \u003calistairncoles@gmail.com\u003e"},{"line_number":29,"context_line":"Co-Authored-By: Jianjian Huo \u003cjhuo@nvidia.com\u003e"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":36,"id":"8f7d3d5f_02adbd88","line":26,"in_reply_to":"fd1dfa4a_2affb836","updated":"2025-02-08 01:07:26.000000000","message":"\u003e you basically need to do that indefinitely\n\nif operator removes the option from all configs, restart all the processes, and also deploy other stand-alone expirers with legacy expirer config, they should be able to finish cleanup of old expiration tasks.\n\nyes, it\u0027s an option that user can continue to use their configured account.","commit_id":"b69a2bef45b100a2bc06b7fbb2eacd06380b117b"}],"/PATCHSET_LEVEL":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"d959d5a9bd1de78dcfa8765aa0e309875bbe8b94","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":4,"id":"010990a6_3c1cede2","updated":"2024-06-04 16:30:40.000000000","message":"commit message definately needed an UpgradeImpact","commit_id":"b61cf5170d46fb78d2f56e6f0ff8537bc162c466"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"8bc79c22db28289c7ef0aa424316b73e359c3cb2","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":5,"id":"c0937dc1_f827e371","updated":"2024-06-04 21:26:14.000000000","message":"the new commit message is great, thanks for adding it.","commit_id":"c6e36d1e962e8eba623bdb086b5522e40368339e"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"b8c63f308be42cefb0ecd26273eb849c03d956d7","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":6,"id":"3781e583_8dfdaed3","updated":"2024-06-19 16:31:59.000000000","message":"The deprecated options should be removed (or marked as deprecated) in man pages and docs:\n\nhttps://github.com/openstack/swift/blob/49b19613d29bda5717ca5eec8c9f6bc9049f99c0/doc/manpages/object-server.conf.5#L89-L93\nhttps://github.com/openstack/swift/blob/49b19613d29bda5717ca5eec8c9f6bc9049f99c0/doc/manpages/proxy-server.conf.5#L99-L103\nhttps://github.com/openstack/swift/blob/11eb17d3b268258a1fa60957e33d5cbe8566db98/doc/source/config/proxy_server_config.rst#L127-L128","commit_id":"c503d937bdf0898e739f4febf2b5f416d3af87e9"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"3c753577924d66ca4dbe4fe8e6634ada827d5d1b","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":6,"id":"ec95980f_3b25fc07","in_reply_to":"0d0c645e_99c4afc3","updated":"2024-07-31 15:51:16.000000000","message":"I think this is now done!?","commit_id":"c503d937bdf0898e739f4febf2b5f416d3af87e9"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"b24527820846696e9e7b7869638761cc8920deac","unresolved":true,"context_lines":[],"source_content_type":"","patch_set":6,"id":"0d0c645e_99c4afc3","in_reply_to":"3781e583_8dfdaed3","updated":"2024-07-10 16:31:27.000000000","message":"this still needs to get done!","commit_id":"c503d937bdf0898e739f4febf2b5f416d3af87e9"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"33adc3bde26369da862706bc0a1f289481d33c11","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":7,"id":"142e5861_2f6e8a50","updated":"2024-06-19 16:36:10.000000000","message":"I pushed some very trivial fixes.\n\nAlso, forgot to write a summary with previous review...\n\nI\u0027m in favour of the new option and the refactoring, but I stumbled over the helper method signatures.\n\nI think there\u0027s at least one drive-by (missing X-Container-Delete-At header handling) that I need to study a bit more, and look over tests. Out of time for today.","commit_id":"43cc17025cd094dd9a0c866887e7b35de08a3bc4"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"deb7b0fb11e435af1a79694882c472f73219e440","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":7,"id":"04c56633_22b2f9a7","updated":"2024-06-24 15:45:31.000000000","message":"Looks like a couple of easy things to clean up (man-pages, doc-strings) - but also maybe a couple of things to discuss (unexpected_containers, warning logs, argument style).\n\nI\u0027m leaning towards pushing this back out *behind* the patches we\u0027re carrying and trying against next release - but I\u0027ll try to get some high-bandwidth with Tim/Al/Jian today and make a decision by EOD.","commit_id":"43cc17025cd094dd9a0c866887e7b35de08a3bc4"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"7a319f3d37e591d2c517479b5c3988480a4a9ac3","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":9,"id":"adabafc6_e2ffadd1","updated":"2024-07-10 13:56:47.000000000","message":"i don\u0027t know this is still is conflict; but I need to rework the docs/manpages to deprecate the new options anyway...","commit_id":"9a682528608b1cc47286d9566db15aea4cd00909"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"9e1341653645bc630e2746759431a3fd177b5398","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":10,"id":"46cf1cf5_83dabb2d","updated":"2024-07-18 16:52:31.000000000","message":"I think this patch is great, I just have one concern about the relationship between  expiring_objects_task_container_per_day and expiring_objects_container_divisor: IIUC we should ``enforce expiring_objects_task_container_per_day \u003c expiring_objects_container_divisor`` in case of crazy configs.\n\n+1 for better encapsulation of the expirer parameters\n+1 for improved test coverage\n+1 for checks on containers in the expiry account","commit_id":"6fe94c3c0074b7e4d74d7cf23a198b869e816ce7"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"296beca32dc11b900b395aa306e293bbda879e69","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":11,"id":"93c38543_8794bfe4","updated":"2024-07-19 14:05:59.000000000","message":"@Clay please see follow-up to squash https://review.opendev.org/c/openstack/swift/+/924511 (unless I have misunderstood)\n\nwith that ^^ I\u0027d +2","commit_id":"17faac823373f58cde95365c4fae359ae6648267"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"3c753577924d66ca4dbe4fe8e6634ada827d5d1b","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":13,"id":"27f3b793_0ad92b89","updated":"2024-07-31 15:51:16.000000000","message":"resolving some comments; I hope I understood correctly - still some work to do here I think.","commit_id":"c9c0e033e02dcedefdaff1b40094a07d14ab379d"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"a2cc99d00d766f1a7533191b90cab97cfcf55947","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":15,"id":"9f89e7e3_473cdb50","updated":"2024-08-02 15:44:13.000000000","message":"recheck\n\nPOST_FAILURE","commit_id":"93c63225b3fa485a2e8f4133ce4db5ac640db1be"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"a6d1ab6198a8d93c528bf2d3c86c5c83dbabe5cf","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":18,"id":"c11a9833_8ad9ea20","updated":"2024-09-11 13:05:11.000000000","message":"recheck\n\ntime out creating a compute resource, unrelated\n```\nCaptured logging:\n~~~~~~~~~~~~~~~~~\n    2024-09-11 09:21:25,234 openstack.resource               Still waiting for resource Server:d0314ec0-ec70-49fa-a914-df870c8d4c8d to reach state ACTIVE, current state is BUILD\n2024-09-11 09:21:25,237 openstack.iterate_timeout        Waiting 2.0 seconds\n\n\nopenstack.tests.functional.examples.test_compute.TestCompute.test_compute\n-------------------------------------------------------------------------\n\nCaptured traceback:\n~~~~~~~~~~~~~~~~~~~\n    Traceback (most recent call last):\n\n      File \"/home/zuul/src/opendev.org/openstack/openstacksdk/openstack/tests/functional/examples/test_compute.py\", line 47, in test_compute\n    create.create_server(self.conn)\n\n      File \"/home/zuul/src/opendev.org/openstack/openstacksdk/examples/compute/create.py\", line 72, in create_server\n    server \u003d conn.compute.wait_for_server(server)\n\n      File \"/home/zuul/src/opendev.org/openstack/openstacksdk/openstack/compute/v2/_proxy.py\", line 2636, in wait_for_server\n    return resource.wait_for_status(\n\n      File \"/home/zuul/src/opendev.org/openstack/openstacksdk/openstack/resource.py\", line 2458, in wait_for_status\n    raise exceptions.ResourceFailure(\n\n    openstack.exceptions.ResourceFailure: Server:316be072-dbf2-40b3-850f-d10720c2cc8e transitioned to failure state ERROR\n\n```","commit_id":"2c920ec1b9b79300883aa1a3c1ffee3972163ab3"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"c02205ac2d10423d7033e84dfc99ef779c6c882d","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":22,"id":"05907bc1_0c106da6","updated":"2024-10-28 12:41:32.000000000","message":"-1 just for the premature reference to swift-expirer-rebalance which comes with the next patchset. I realise we plan to merge all of the chain but I can imagine some of these patches merging sooner so we should avoid the forward-reference.\n\nOtherwise all good. I prefer that the deprecation changes have been separated from the new option (next patchset) for the purpose of review, thanks!","commit_id":"22983c09eefe45089a76cd7d343e50bf9508af8b"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"804102f9ccc56893bda6a85c14f55ef7de54b59e","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":22,"id":"2a238e91_b35dbc5e","updated":"2024-10-28 22:11:05.000000000","message":"I changed up `__init__` on the ExpirerConfig - do know if everyone would strictly agree it\u0027s only better but had some advantages over the last patch set that made me think it might be useful.  Alternatively I might have considered just making the logger argument explicit and required.\n\nI found a few more places we documented these now deprecated options and proxy test that wasn\u0027t mocking the expirer_config properly.","commit_id":"22983c09eefe45089a76cd7d343e50bf9508af8b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"51d25ef595a99b441fb515378de96111e2edcd68","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":23,"id":"0048cf41_94251fae","updated":"2024-10-29 09:26:48.000000000","message":"Good catch on fixing the other doc sites.\n\nI much preferred the original interface to ExpirerConfig. But I do like making a logger from conf when no logger was passed. I think that\u0027s possible with either interface.\n\n-1 because there\u0027s an unnecessary ``if`` which ordinarily I\u0027d fix-and-merge, but I wonder how keen you are on the new interface?","commit_id":"81fb6359f63277a2b2ab985e80622ad796e4caef"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"0e05111f20bd14b2960faea0b331283101a9161b","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":23,"id":"49d9c121_410393c3","updated":"2024-10-31 11:18:06.000000000","message":"I reverted the ExpirerConfig constructor change but kept the fallback build logger from conf. However, I also noticed that this is only required for tests, so we could just make logger a required arg and fix all the tests ?? That said, there is probably precedence elsewhere (in daemons) for constructing a default logger just for tests.","commit_id":"81fb6359f63277a2b2ab985e80622ad796e4caef"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"832a0989df50c98bfdea0deae4dd97e98cb67334","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":23,"id":"d247f171_474e4f60","updated":"2024-10-30 14:06:36.000000000","message":"yay tests passed!","commit_id":"81fb6359f63277a2b2ab985e80622ad796e4caef"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"7e8b5245107293fbd1912dd0ea8014d83b851fe5","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":24,"id":"10f9f854_3f4fbddd","updated":"2024-10-31 13:32:55.000000000","message":"well that\u0027s embarassing. I guess the fact the 2 tests in proxy/test_server.py *always* fail on my machine (macos) blinded me to the genuine regression. \n\nShould be fixed in next patchset.","commit_id":"679ad81edd88a29d2d8a77ece500b87f350fb370"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"12adff2a771a5e59e495ec6d7ea55e28557d5245","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":27,"id":"827a4dae_da4963b0","updated":"2024-11-01 21:27:32.000000000","message":"recheck\n\nhttps://bugs.launchpad.net/openstacksdk/+bug/2085654","commit_id":"538c82e0fb554328d8ce72e513c583db2c20045a"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"ed2cb843f69c57e0cb32cf6ce4b2a7d8403bf05d","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":27,"id":"283868d1_662c8d7b","updated":"2024-11-01 21:39:57.000000000","message":"the diff could be a little tighter; but I think this all looks good.","commit_id":"538c82e0fb554328d8ce72e513c583db2c20045a"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"b8a5331d4c780ae61da2189c4136848dc90fada1","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":27,"id":"e5c216ae_2c42704b","updated":"2024-11-04 00:03:10.000000000","message":"warn() is deprecated since python 3.3","commit_id":"538c82e0fb554328d8ce72e513c583db2c20045a"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"d0f98cfd362e46a234f338320f8ee19044d5e31d","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":28,"id":"08f337d4_6167997b","updated":"2024-11-05 00:21:48.000000000","message":"this one seems fine; I tried to tighten up the diff","commit_id":"63af9fd3ffa51b14c25345e00f0cb543dd732d36"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"e707e3dcdb5f7a43ad3027ebcc729e8b7baf3f4d","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":29,"id":"2bcb7d98_bf6cfe0f","updated":"2024-11-05 10:10:19.000000000","message":"LGTM I just have one query about the most recent test addition (see inline)","commit_id":"a39f35f4b20d7e66639172aa46ccb0d94bf613d9"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"8770fff8b26a1de2cad0405e65c8e4c9e05ed324","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":32,"id":"5a20505d_83df072f","updated":"2024-11-18 19:06:00.000000000","message":"new patch coming up!","commit_id":"4d5b379862fb7ba9809bb61be67f05695cf49308"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"cc53537bdc2eabaf6787d0c01d044aaf13dc8d71","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":36,"id":"78055f9e_a2c42786","updated":"2025-02-08 01:07:26.000000000","message":"Tim also likes this patch, let\u0027s merge it!","commit_id":"b69a2bef45b100a2bc06b7fbb2eacd06380b117b"}],"doc/source/config/object_server_config.rst":[{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"9e1341653645bc630e2746759431a3fd177b5398","unresolved":true,"context_lines":[{"line_number":762,"context_line":"                                                                         The object expirer will reap objects in this"},{"line_number":763,"context_line":"                                                                         container from disk only after this delay"},{"line_number":764,"context_line":"                                                                         following their x-delete-at time."},{"line_number":765,"context_line":"\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d \u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d \u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d"}],"source_content_type":"text/x-rst","patch_set":10,"id":"43d7c975_e7d8d085","line":765,"updated":"2024-07-18 16:52:31.000000000","message":"don\u0027t you just love maintaining these tables 😂","commit_id":"6fe94c3c0074b7e4d74d7cf23a198b869e816ce7"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"3c753577924d66ca4dbe4fe8e6634ada827d5d1b","unresolved":false,"context_lines":[{"line_number":762,"context_line":"                                                                         The object expirer will reap objects in this"},{"line_number":763,"context_line":"                                                                         container from disk only after this delay"},{"line_number":764,"context_line":"                                                                         following their x-delete-at time."},{"line_number":765,"context_line":"\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d \u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d \u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d"}],"source_content_type":"text/x-rst","patch_set":10,"id":"fb79c6af_9bc17895","line":765,"in_reply_to":"43d7c975_e7d8d085","updated":"2024-07-31 15:51:16.000000000","message":"my fav.","commit_id":"6fe94c3c0074b7e4d74d7cf23a198b869e816ce7"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"ed2cb843f69c57e0cb32cf6ce4b2a7d8403bf05d","unresolved":true,"context_lines":[{"line_number":703,"context_line":"report_interval                          300                             Frequency of status logs in seconds."},{"line_number":704,"context_line":"concurrency                              1                               Level of concurrency to use to do the work,"},{"line_number":705,"context_line":"                                                                         this value must be set to at least 1"},{"line_number":706,"context_line":"dequeue_from_legacy                      False                           This service will look for jobs on the legacy expirer task queue."},{"line_number":707,"context_line":"round_robin_task_cache_size              100000                          Number of tasks objects to cache before processing."},{"line_number":708,"context_line":"processes                                0                               How many parts to divide the legacy work into,"},{"line_number":709,"context_line":"                                                                         one part per process that will be doing the work."}],"source_content_type":"text/x-rst","patch_set":27,"id":"259cd401_70af6609","line":706,"updated":"2024-11-01 21:39:57.000000000","message":"might as well fix the line wrap of the description while we\u0027re at it.","commit_id":"538c82e0fb554328d8ce72e513c583db2c20045a"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"d0f98cfd362e46a234f338320f8ee19044d5e31d","unresolved":false,"context_lines":[{"line_number":703,"context_line":"report_interval                          300                             Frequency of status logs in seconds."},{"line_number":704,"context_line":"concurrency                              1                               Level of concurrency to use to do the work,"},{"line_number":705,"context_line":"                                                                         this value must be set to at least 1"},{"line_number":706,"context_line":"dequeue_from_legacy                      False                           This service will look for jobs on the legacy expirer task queue."},{"line_number":707,"context_line":"round_robin_task_cache_size              100000                          Number of tasks objects to cache before processing."},{"line_number":708,"context_line":"processes                                0                               How many parts to divide the legacy work into,"},{"line_number":709,"context_line":"                                                                         one part per process that will be doing the work."}],"source_content_type":"text/x-rst","patch_set":27,"id":"3cc08b80_15ba33f3","line":706,"in_reply_to":"259cd401_70af6609","updated":"2024-11-05 00:21:48.000000000","message":"Done","commit_id":"538c82e0fb554328d8ce72e513c583db2c20045a"}],"doc/source/config/proxy_server_config.rst":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"ed2cb843f69c57e0cb32cf6ce4b2a7d8403bf05d","unresolved":true,"context_lines":[{"line_number":148,"context_line":"                                                                   the I/O priority of the process."},{"line_number":149,"context_line":"                                                                   Work only with ionice_class."},{"line_number":150,"context_line":"                                                                   Ignored if IOPRIO_CLASS_IDLE is set."},{"line_number":151,"context_line":"\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d  \u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d  \u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d"},{"line_number":152,"context_line":""},{"line_number":153,"context_line":"**************"},{"line_number":154,"context_line":"[proxy-server]"}],"source_content_type":"text/x-rst","patch_set":27,"id":"d3ad3b27_f51fcd13","line":151,"updated":"2024-11-01 21:39:57.000000000","message":"the formatting churn happens when we add `expiring_objects_task_containers_per_day` - which was originally the same patch, but in theory we could shrink this diff size by just removing the lines.","commit_id":"538c82e0fb554328d8ce72e513c583db2c20045a"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"d0f98cfd362e46a234f338320f8ee19044d5e31d","unresolved":false,"context_lines":[{"line_number":148,"context_line":"                                                                   the I/O priority of the process."},{"line_number":149,"context_line":"                                                                   Work only with ionice_class."},{"line_number":150,"context_line":"                                                                   Ignored if IOPRIO_CLASS_IDLE is set."},{"line_number":151,"context_line":"\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d  \u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d  \u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d"},{"line_number":152,"context_line":""},{"line_number":153,"context_line":"**************"},{"line_number":154,"context_line":"[proxy-server]"}],"source_content_type":"text/x-rst","patch_set":27,"id":"885c0d99_5fd6ebd9","line":151,"in_reply_to":"d3ad3b27_f51fcd13","updated":"2024-11-05 00:21:48.000000000","message":"Done","commit_id":"538c82e0fb554328d8ce72e513c583db2c20045a"}],"etc/object-expirer.conf-sample":[{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"2c8140e677772aa6c82d0a76410358dfb5e12ecd","unresolved":true,"context_lines":[{"line_number":40,"context_line":"# If you have a 100s of millions of expiring objects per day or 100s of"},{"line_number":41,"context_line":"# object-expirer nodes you may want to increase this (10x?) for better"},{"line_number":42,"context_line":"# scalability; otherwise the default is quite good"},{"line_number":43,"context_line":"# N.B. it MUST be kept consistent with [proxy|object]-server.conf"},{"line_number":44,"context_line":"# expiring_objects_task_container_per_day \u003d 100"},{"line_number":45,"context_line":""},{"line_number":46,"context_line":"[object-expirer]"}],"source_content_type":"application/octet-stream","patch_set":3,"id":"97fc3e5b_6781c57e","line":43,"updated":"2024-05-30 00:17:07.000000000","message":"actually three config files were modified with this patch, \nso need to include the latter  ``[proxy|object]-server.conf and object-expirer.conf``\n\nthis is error prone I feel, but I understand all three components need to access the new config.","commit_id":"8480d21430ed80f324c899397d991e9506853c29"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"8897b9d48b6dd910c839cd6ceefc4294a3b9aca1","unresolved":false,"context_lines":[{"line_number":40,"context_line":"# If you have a 100s of millions of expiring objects per day or 100s of"},{"line_number":41,"context_line":"# object-expirer nodes you may want to increase this (10x?) for better"},{"line_number":42,"context_line":"# scalability; otherwise the default is quite good"},{"line_number":43,"context_line":"# N.B. it MUST be kept consistent with [proxy|object]-server.conf"},{"line_number":44,"context_line":"# expiring_objects_task_container_per_day \u003d 100"},{"line_number":45,"context_line":""},{"line_number":46,"context_line":"[object-expirer]"}],"source_content_type":"application/octet-stream","patch_set":3,"id":"fbab2cd0_c8508e29","line":43,"in_reply_to":"97fc3e5b_6781c57e","updated":"2024-05-31 20:45:21.000000000","message":"this *is* object-expirer.conf - so this comment only calls out the other two.","commit_id":"8480d21430ed80f324c899397d991e9506853c29"}],"swift/common/middleware/slo.py":[{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"b8c63f308be42cefb0ecd26273eb849c03d956d7","unresolved":true,"context_lines":[{"line_number":1332,"context_line":"            delete_concurrency\u003ddelete_concurrency,"},{"line_number":1333,"context_line":"            logger\u003dself.logger)"},{"line_number":1334,"context_line":""},{"line_number":1335,"context_line":"        self.expirer_config \u003d expirer.get_expirer_config(conf)"},{"line_number":1336,"context_line":""},{"line_number":1337,"context_line":"    def handle_multipart_get_or_head(self, req, start_response):"},{"line_number":1338,"context_line":"        \"\"\""}],"source_content_type":"text/x-python","patch_set":6,"id":"0c99ea55_f9b85274","line":1335,"updated":"2024-06-19 16:31:59.000000000","message":"yes! better encapsulate this in the expirer module :)","commit_id":"c503d937bdf0898e739f4febf2b5f416d3af87e9"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"deb7b0fb11e435af1a79694882c472f73219e440","unresolved":false,"context_lines":[{"line_number":1332,"context_line":"            delete_concurrency\u003ddelete_concurrency,"},{"line_number":1333,"context_line":"            logger\u003dself.logger)"},{"line_number":1334,"context_line":""},{"line_number":1335,"context_line":"        self.expirer_config \u003d expirer.get_expirer_config(conf)"},{"line_number":1336,"context_line":""},{"line_number":1337,"context_line":"    def handle_multipart_get_or_head(self, req, start_response):"},{"line_number":1338,"context_line":"        \"\"\""}],"source_content_type":"text/x-python","patch_set":6,"id":"f396c5b5_64abb11d","line":1335,"in_reply_to":"0c99ea55_f9b85274","updated":"2024-06-24 15:45:31.000000000","message":"Acknowledged","commit_id":"c503d937bdf0898e739f4febf2b5f416d3af87e9"}],"swift/common/utils/__init__.py":[{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"b8c63f308be42cefb0ecd26273eb849c03d956d7","unresolved":true,"context_lines":[{"line_number":2820,"context_line":"    \"\"\""},{"line_number":2821,"context_line":"    shard_int \u003d int(hash_path(acc, cont, obj), 16) % 100"},{"line_number":2822,"context_line":"    return normalize_delete_at_timestamp("},{"line_number":2823,"context_line":"        int(x_delete_at) // expirer_divisor * expirer_divisor - shard_int)"},{"line_number":2824,"context_line":""},{"line_number":2825,"context_line":""},{"line_number":2826,"context_line":"class _MultipartMimeFileLikeObject(object):"}],"source_content_type":"text/x-python","patch_set":6,"id":"4b03650b_da0feef8","side":"PARENT","line":2823,"updated":"2024-06-19 16:31:59.000000000","message":"ok, moved to object_expirer.py","commit_id":"3637b1abd9240f7feeebc7f299d42fe8815d7dcd"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"deb7b0fb11e435af1a79694882c472f73219e440","unresolved":false,"context_lines":[{"line_number":2820,"context_line":"    \"\"\""},{"line_number":2821,"context_line":"    shard_int \u003d int(hash_path(acc, cont, obj), 16) % 100"},{"line_number":2822,"context_line":"    return normalize_delete_at_timestamp("},{"line_number":2823,"context_line":"        int(x_delete_at) // expirer_divisor * expirer_divisor - shard_int)"},{"line_number":2824,"context_line":""},{"line_number":2825,"context_line":""},{"line_number":2826,"context_line":"class _MultipartMimeFileLikeObject(object):"}],"source_content_type":"text/x-python","patch_set":6,"id":"08598788_f78760ee","side":"PARENT","line":2823,"in_reply_to":"4b03650b_da0feef8","updated":"2024-06-24 15:45:31.000000000","message":"Acknowledged","commit_id":"3637b1abd9240f7feeebc7f299d42fe8815d7dcd"}],"swift/obj/expirer.py":[{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"2c8140e677772aa6c82d0a76410358dfb5e12ecd","unresolved":true,"context_lines":[{"line_number":52,"context_line":""},{"line_number":53,"context_line":"def get_expirer_config(conf):"},{"line_number":54,"context_line":"    \"\"\""},{"line_number":55,"context_line":"    Read the configuable values for the obejct-expirer consistently and issue"},{"line_number":56,"context_line":"    warnings appropriately when we encounter deprecated config options.  This"},{"line_number":57,"context_line":"    function is used by both the object-expirer and the proxy-server."},{"line_number":58,"context_line":""}],"source_content_type":"text/x-python","patch_set":3,"id":"82ac08b4_d05e9de3","line":55,"updated":"2024-05-30 00:17:07.000000000","message":"s/obejct-expirer/object-expirer","commit_id":"8480d21430ed80f324c899397d991e9506853c29"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"8897b9d48b6dd910c839cd6ceefc4294a3b9aca1","unresolved":false,"context_lines":[{"line_number":52,"context_line":""},{"line_number":53,"context_line":"def get_expirer_config(conf):"},{"line_number":54,"context_line":"    \"\"\""},{"line_number":55,"context_line":"    Read the configuable values for the obejct-expirer consistently and issue"},{"line_number":56,"context_line":"    warnings appropriately when we encounter deprecated config options.  This"},{"line_number":57,"context_line":"    function is used by both the object-expirer and the proxy-server."},{"line_number":58,"context_line":""}],"source_content_type":"text/x-python","patch_set":3,"id":"772314f6_a648d382","line":55,"in_reply_to":"82ac08b4_d05e9de3","updated":"2024-05-31 20:45:21.000000000","message":"thanks!","commit_id":"8480d21430ed80f324c899397d991e9506853c29"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"2c8140e677772aa6c82d0a76410358dfb5e12ecd","unresolved":true,"context_lines":[{"line_number":65,"context_line":"            \u0027expiring_objects_container_divisor is deprecated; use \u0027"},{"line_number":66,"context_line":"            \u0027expiring_objects_task_container_per_day instead\u0027,"},{"line_number":67,"context_line":"            DeprecationWarning)"},{"line_number":68,"context_line":"        expirer_divisor \u003d config_positive_int_value("},{"line_number":69,"context_line":"            conf[\u0027expiring_objects_container_divisor\u0027])"},{"line_number":70,"context_line":"    else:"},{"line_number":71,"context_line":"        expirer_divisor \u003d EXPIRER_CONTAINER_DIVISOR"}],"source_content_type":"text/x-python","patch_set":3,"id":"06c13abd_5a3dac4a","line":68,"updated":"2024-05-30 00:17:07.000000000","message":"add the default value?\n\n``config_positive_int_value(conf[\u0027expiring_objects_container_divisor\u0027],EXPIRER_CONTAINER_DIVISOR)``\n\nor if we are going to convert everything to use one day default, we can just ignore this old config?","commit_id":"8480d21430ed80f324c899397d991e9506853c29"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"8897b9d48b6dd910c839cd6ceefc4294a3b9aca1","unresolved":false,"context_lines":[{"line_number":65,"context_line":"            \u0027expiring_objects_container_divisor is deprecated; use \u0027"},{"line_number":66,"context_line":"            \u0027expiring_objects_task_container_per_day instead\u0027,"},{"line_number":67,"context_line":"            DeprecationWarning)"},{"line_number":68,"context_line":"        expirer_divisor \u003d config_positive_int_value("},{"line_number":69,"context_line":"            conf[\u0027expiring_objects_container_divisor\u0027])"},{"line_number":70,"context_line":"    else:"},{"line_number":71,"context_line":"        expirer_divisor \u003d EXPIRER_CONTAINER_DIVISOR"}],"source_content_type":"text/x-python","patch_set":3,"id":"52812428_f1da85c3","line":68,"in_reply_to":"06c13abd_5a3dac4a","updated":"2024-05-31 20:45:21.000000000","message":"I think it would be weird to have a default since we\u0027re only in this block because the key exists in the config.","commit_id":"8480d21430ed80f324c899397d991e9506853c29"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"2c8140e677772aa6c82d0a76410358dfb5e12ecd","unresolved":true,"context_lines":[{"line_number":101,"context_line":""},{"line_number":102,"context_line":""},{"line_number":103,"context_line":"def get_expirer_account_and_container(x_delete_at, acc, cont, obj,"},{"line_number":104,"context_line":"                                      account_name\u003dEXPIRER_ACCOUNT_NAME,"},{"line_number":105,"context_line":"                                      **expirer_config):"},{"line_number":106,"context_line":"    \"\"\""},{"line_number":107,"context_line":"    Calculates the expected expirer account and container for the target given"}],"source_content_type":"text/x-python","patch_set":3,"id":"f32585c3_99caae1a","line":104,"updated":"2024-05-30 00:17:07.000000000","message":"``account_name`` is only used to return the tuple, and rest of function implementation is just calling another function ``get_expirer_container``. maybe this function is not necessary?","commit_id":"8480d21430ed80f324c899397d991e9506853c29"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"8897b9d48b6dd910c839cd6ceefc4294a3b9aca1","unresolved":false,"context_lines":[{"line_number":101,"context_line":""},{"line_number":102,"context_line":""},{"line_number":103,"context_line":"def get_expirer_account_and_container(x_delete_at, acc, cont, obj,"},{"line_number":104,"context_line":"                                      account_name\u003dEXPIRER_ACCOUNT_NAME,"},{"line_number":105,"context_line":"                                      **expirer_config):"},{"line_number":106,"context_line":"    \"\"\""},{"line_number":107,"context_line":"    Calculates the expected expirer account and container for the target given"}],"source_content_type":"text/x-python","patch_set":3,"id":"9d67e4a2_11a2dd86","line":104,"in_reply_to":"f32585c3_99caae1a","updated":"2024-05-31 20:45:21.000000000","message":"maybe not, but it\u0027s used in the object server where it needs to call get_expier_container and it also needs to get the account_name (possibly from the expier_config)\n\n... so I think the way it\u0027s getting used is pretty convienent for the caller.","commit_id":"8480d21430ed80f324c899397d991e9506853c29"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"2c8140e677772aa6c82d0a76410358dfb5e12ecd","unresolved":true,"context_lines":[{"line_number":131,"context_line":"    :returns: a boolean, True if name fits with the given config"},{"line_number":132,"context_line":"    \"\"\""},{"line_number":133,"context_line":"    r \u003d (task_container_int - 1) % expirer_divisor"},{"line_number":134,"context_line":"    return r \u003e\u003d (expirer_divisor - task_container_per_day)"},{"line_number":135,"context_line":""},{"line_number":136,"context_line":""},{"line_number":137,"context_line":"def get_delete_at_nodes(container_ring, x_delete_at, acc, cont, obj,"}],"source_content_type":"text/x-python","patch_set":3,"id":"2795e910_c3f82cc4","line":134,"updated":"2024-05-30 00:17:07.000000000","message":"can you add comments on why ``r \u003e\u003d (expirer_divisor - task_container_per_day)``?","commit_id":"8480d21430ed80f324c899397d991e9506853c29"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"8897b9d48b6dd910c839cd6ceefc4294a3b9aca1","unresolved":false,"context_lines":[{"line_number":131,"context_line":"    :returns: a boolean, True if name fits with the given config"},{"line_number":132,"context_line":"    \"\"\""},{"line_number":133,"context_line":"    r \u003d (task_container_int - 1) % expirer_divisor"},{"line_number":134,"context_line":"    return r \u003e\u003d (expirer_divisor - task_container_per_day)"},{"line_number":135,"context_line":""},{"line_number":136,"context_line":""},{"line_number":137,"context_line":"def get_delete_at_nodes(container_ring, x_delete_at, acc, cont, obj,"}],"source_content_type":"text/x-python","patch_set":3,"id":"c29825e0_1f53e6e4","line":134,"in_reply_to":"2795e910_c3f82cc4","updated":"2024-05-31 20:45:21.000000000","message":"heh, I\u0027ll try","commit_id":"8480d21430ed80f324c899397d991e9506853c29"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"dfb7b828a9732738e619104ce0ece2e198aa1760","unresolved":true,"context_lines":[{"line_number":97,"context_line":"    shard_int \u003d (int(utils.hash_path(acc, cont, obj), 16) %"},{"line_number":98,"context_line":"                 task_container_per_day)"},{"line_number":99,"context_line":"    return normalize_delete_at_timestamp("},{"line_number":100,"context_line":"        int(x_delete_at) // expirer_divisor * expirer_divisor - shard_int)"},{"line_number":101,"context_line":""},{"line_number":102,"context_line":""},{"line_number":103,"context_line":"def get_expirer_account_and_container(x_delete_at, acc, cont, obj,"}],"source_content_type":"text/x-python","patch_set":4,"id":"fb11b81f_87e93067","line":100,"updated":"2024-06-04 05:51:58.000000000","message":"the new function ``get_expirer_config`` will retrieve deprecated settings if it exists, such as  ``expirer_divisor``, and ``task_container_per_day`` is a new setting. so we are mixing them up here: the existing ``expirer_divisor`` could be 172800 (which means two days), but the ``shard_int`` is still calculated with ``task_container_per_day``. will that matter in some cases? if not, I feel it worths some comments at least.","commit_id":"b61cf5170d46fb78d2f56e6f0ff8537bc162c466"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"d959d5a9bd1de78dcfa8765aa0e309875bbe8b94","unresolved":false,"context_lines":[{"line_number":97,"context_line":"    shard_int \u003d (int(utils.hash_path(acc, cont, obj), 16) %"},{"line_number":98,"context_line":"                 task_container_per_day)"},{"line_number":99,"context_line":"    return normalize_delete_at_timestamp("},{"line_number":100,"context_line":"        int(x_delete_at) // expirer_divisor * expirer_divisor - shard_int)"},{"line_number":101,"context_line":""},{"line_number":102,"context_line":""},{"line_number":103,"context_line":"def get_expirer_account_and_container(x_delete_at, acc, cont, obj,"}],"source_content_type":"text/x-python","patch_set":4,"id":"e067a514_07ff5386","line":100,"in_reply_to":"fb11b81f_87e93067","updated":"2024-06-04 16:30:40.000000000","message":"AFAIK the math all works out, task_container_per_day could have been named task_container_per_divisor; but I\u0027m trying to move towards standardized thinking on \"days of task containers\" by deprecating the old option which is not helpful.\n\nSo for the *new* option I wanted to name it in the way it\u0027s expected to be used; but that was a design choice favoring future mainteance over backwards consistency - feedback is welcome.\n\nThanks for calling this out!  I\u0027ll expand on the idea in the commit message and consider how to phrase a comment here and some more targeted tests on the legacy config behavior.\n\n    swift/test/unit/obj/test_expirer.py::TestGetExpirerContainer::test_get_expirer_container_legacy_config","commit_id":"b61cf5170d46fb78d2f56e6f0ff8537bc162c466"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"dfb7b828a9732738e619104ce0ece2e198aa1760","unresolved":true,"context_lines":[{"line_number":456,"context_line":"        for c in self.swift.iter_containers(task_account,"},{"line_number":457,"context_line":"                                            prefix\u003dself.task_container_prefix):"},{"line_number":458,"context_line":"            try:"},{"line_number":459,"context_line":"                task_container_int \u003d non_negative_int(c[\u0027name\u0027])"},{"line_number":460,"context_line":"            except ValueError:"},{"line_number":461,"context_line":"                self.logger.error(\u0027skipping invalid task container: %s/%s\u0027,"},{"line_number":462,"context_line":"                                  task_account, c[\u0027name\u0027])"}],"source_content_type":"text/x-python","patch_set":4,"id":"7d513de7_84bcb6be","line":459,"updated":"2024-06-04 05:51:58.000000000","message":"the original ``Timestamp(task_container)`` is replaced with ``non_negative_int(c[\u0027name\u0027])``, and the latter will raise ValueError if it\u0027s a negative integer. but it seems to me that the original Timestamp constructor will offer more checks?\n\n```\n            if self.timestamp \u003c 0:\n                raise ValueError(\u0027timestamp cannot be negative\u0027)\n            if self.timestamp \u003e\u003d 10000000000:\n                raise ValueError(\u0027timestamp too large\u0027)\n```","commit_id":"b61cf5170d46fb78d2f56e6f0ff8537bc162c466"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"d959d5a9bd1de78dcfa8765aa0e309875bbe8b94","unresolved":false,"context_lines":[{"line_number":456,"context_line":"        for c in self.swift.iter_containers(task_account,"},{"line_number":457,"context_line":"                                            prefix\u003dself.task_container_prefix):"},{"line_number":458,"context_line":"            try:"},{"line_number":459,"context_line":"                task_container_int \u003d non_negative_int(c[\u0027name\u0027])"},{"line_number":460,"context_line":"            except ValueError:"},{"line_number":461,"context_line":"                self.logger.error(\u0027skipping invalid task container: %s/%s\u0027,"},{"line_number":462,"context_line":"                                  task_account, c[\u0027name\u0027])"}],"source_content_type":"text/x-python","patch_set":4,"id":"dce452eb_95610be6","line":459,"in_reply_to":"7d513de7_84bcb6be","updated":"2024-06-04 16:30:40.000000000","message":"I think this *could* be `int(Timestamp(c[\u0027name\u0027]))` - that might be more obvious/robust and I\u0027m not particularlly worried about the overhead in this loop.\n\nHowever, I think either would be a correct material improvement: task_container names are always integer timestamps [1], and the existing code had no exception handling.\n\nI think there\u0027s existing tests that demonstrate the lack of continuation in the face of unexpected container names on master:\n\n    swift/test/unit/obj/test_expirer.py::TestObjectExpirer::test_iter_task_account_containers_to_expire_invalid_container\n\n... but I\u0027ve added another one:\n\n    swift/test/unit/obj/test_expirer.py::TestObjectExpirer::test_run_once_with_invalid_container\n\n1) Although \"high_precision\" lead me down a rabbit hole:\n\nhttps://github.com/NVIDIA/swift/blob/master/swift/common/utils/timestamp.py#L380-L402\n\nI confirmed functionally that swift-container-deleter will also create task containers as integer timestamps:\n\nhttps://github.com/NVIDIA/swift/blob/master/swift/cli/container_deleter.py#L115\n\n... just like the proxy:\n\nhttps://github.com/openstack/swift/blob/2.33.0/swift/common/utils/__init__.py#L4192","commit_id":"b61cf5170d46fb78d2f56e6f0ff8537bc162c466"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"6fa418271671f06f1a35aca6b0e4e7ad430aed17","unresolved":true,"context_lines":[{"line_number":42,"context_line":"MAX_OBJECTS_TO_CACHE \u003d 100000"},{"line_number":43,"context_line":"ASYNC_DELETE_TYPE \u003d \u0027application/async-deleted\u0027"},{"line_number":44,"context_line":""},{"line_number":45,"context_line":"# This is apparently configuable, but AUTO_CREATE_ACCOUNT_PREFIX is not"},{"line_number":46,"context_line":"EXPIRER_ACCOUNT_NAME \u003d AUTO_CREATE_ACCOUNT_PREFIX + \u0027expiring_objects\u0027"},{"line_number":47,"context_line":"# Most clusters use the default \"expiring_objects_container_divisor\" of 86400."},{"line_number":48,"context_line":"EXPIRER_CONTAINER_DIVISOR \u003d 86400"}],"source_content_type":"text/x-python","patch_set":5,"id":"ae815dfa_cd37eb05","line":45,"updated":"2024-06-14 01:27:04.000000000","message":"wrong, i relearned auto-create-account-prefix is *sadly* configuable via constraints; hopefully no one has ever done that.\n\nhistorically we\u0027ve avoided putting stuff like `reclaim_age` (which has to be consistent accross object-server/replicator configs) in `swift.conf` because that would typically encourage restarting *all* swift services - even the access tier which should be uneffected in that case; but in *this* case the access tier also supports expirer configuration so that argument may not hold.\n\nBut another argument that may be valid is that proxy-server.conf and object-expirer.conf all support conf.d style configuration, and the constraints section in swift.conf may not (I haven\u0027t tested it, but i feel like /etc/swift/swift.conf is hard-coded; maybe it could be a directory tho if we just use read_conf anyway...)\n\nI know it\u0027s annoying to have a config value in 3 configs that all need to be exactly the same to ensure consistent operation; but realistically at least 2 of those 3 configs are on different physical nodes (access-iter vs. storage-tier) so it\u0027s not like ops has to write down any more config files... they just need to render the same var into all of them consistently.\n\nI might just be trying to talk myself into not having to do the work to write/test moving the new option to constraints, I feel like it would make the deprecation part of this change more complicated; but I guess that\u0027s wrong too since constraints configuration are just imported as constants.  So you\u0027d still pass the config into this method - but the only value we\u0027d read from that conf dict would all be deprecated!  I don\u0027t know... this work could be done different, but this works as is!","commit_id":"c6e36d1e962e8eba623bdb086b5522e40368339e"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"741dbae4879c5c177c949a7a4758c964f0674311","unresolved":false,"context_lines":[{"line_number":42,"context_line":"MAX_OBJECTS_TO_CACHE \u003d 100000"},{"line_number":43,"context_line":"ASYNC_DELETE_TYPE \u003d \u0027application/async-deleted\u0027"},{"line_number":44,"context_line":""},{"line_number":45,"context_line":"# This is apparently configuable, but AUTO_CREATE_ACCOUNT_PREFIX is not"},{"line_number":46,"context_line":"EXPIRER_ACCOUNT_NAME \u003d AUTO_CREATE_ACCOUNT_PREFIX + \u0027expiring_objects\u0027"},{"line_number":47,"context_line":"# Most clusters use the default \"expiring_objects_container_divisor\" of 86400."},{"line_number":48,"context_line":"EXPIRER_CONTAINER_DIVISOR \u003d 86400"}],"source_content_type":"text/x-python","patch_set":5,"id":"b1ec8124_58f7b376","line":45,"in_reply_to":"ae815dfa_cd37eb05","updated":"2024-07-10 00:02:17.000000000","message":"no one else has suggested moving the new option to constraints; I think using the app/daemon config and documenting they should be consistent across servers/services is a reasonably well established pattern.","commit_id":"c6e36d1e962e8eba623bdb086b5522e40368339e"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"6fa418271671f06f1a35aca6b0e4e7ad430aed17","unresolved":true,"context_lines":[{"line_number":460,"context_line":"            except ValueError:"},{"line_number":461,"context_line":"                self.logger.error(\u0027skipping invalid task container: %s/%s\u0027,"},{"line_number":462,"context_line":"                                  task_account, c[\u0027name\u0027])"},{"line_number":463,"context_line":"                continue"},{"line_number":464,"context_line":"            if not is_expected_task_container(task_container_int,"},{"line_number":465,"context_line":"                                              **self.expirer_config):"},{"line_number":466,"context_line":"                unexpected_task_containers[\u0027count\u0027] +\u003d 1"}],"source_content_type":"text/x-python","patch_set":5,"id":"9b0b1721_5778309a","line":463,"updated":"2024-06-14 01:27:04.000000000","message":"there\u0027s actually a bit of a \"bug fix\" here in that the main loop will now continue when it encouters an invalid task container name (instead of blow up the cycle)\n\nbut that is really only a bug in theory - i\u0027ve never heard of that happening, the container is entirly populated by our code.\n\nI added a test for that case anyway just to demonstrate the new code has the more desirable/robust beahvior of skipping the invalid container.","commit_id":"c6e36d1e962e8eba623bdb086b5522e40368339e"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"741dbae4879c5c177c949a7a4758c964f0674311","unresolved":false,"context_lines":[{"line_number":460,"context_line":"            except ValueError:"},{"line_number":461,"context_line":"                self.logger.error(\u0027skipping invalid task container: %s/%s\u0027,"},{"line_number":462,"context_line":"                                  task_account, c[\u0027name\u0027])"},{"line_number":463,"context_line":"                continue"},{"line_number":464,"context_line":"            if not is_expected_task_container(task_container_int,"},{"line_number":465,"context_line":"                                              **self.expirer_config):"},{"line_number":466,"context_line":"                unexpected_task_containers[\u0027count\u0027] +\u003d 1"}],"source_content_type":"text/x-python","patch_set":5,"id":"c3147a1d_5c139020","line":463,"in_reply_to":"9b0b1721_5778309a","updated":"2024-07-10 00:02:17.000000000","message":"Acknowledged","commit_id":"c6e36d1e962e8eba623bdb086b5522e40368339e"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"6fa418271671f06f1a35aca6b0e4e7ad430aed17","unresolved":true,"context_lines":[{"line_number":464,"context_line":"            if not is_expected_task_container(task_container_int,"},{"line_number":465,"context_line":"                                              **self.expirer_config):"},{"line_number":466,"context_line":"                unexpected_task_containers[\u0027count\u0027] +\u003d 1"},{"line_number":467,"context_line":"                if unexpected_task_containers[\u0027count\u0027] \u003c 5:"},{"line_number":468,"context_line":"                    unexpected_task_containers[\u0027examples\u0027].append(c[\u0027name\u0027])"},{"line_number":469,"context_line":"            if task_container_int \u003e Timestamp.now():"},{"line_number":470,"context_line":"                break"}],"source_content_type":"text/x-python","patch_set":5,"id":"44a655ff_3bd124fe","line":467,"updated":"2024-06-14 01:27:04.000000000","message":"trading one magic number for another... I don\u0027t want to bother ops to make this configurable really, nor forgo providing examples, nor collect a second large list...\n\nI think in a later patch i end up doing\n\n```\nif not is_expected():\n    unexpected_list.append()\nelse:\n    expected_list.append()\n```\n\nbut at the end I just return `expected_list + unexpected_list` anyway\n\nagain i think this could be different and also that this works.","commit_id":"c6e36d1e962e8eba623bdb086b5522e40368339e"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"deb7b0fb11e435af1a79694882c472f73219e440","unresolved":true,"context_lines":[{"line_number":464,"context_line":"            if not is_expected_task_container(task_container_int,"},{"line_number":465,"context_line":"                                              **self.expirer_config):"},{"line_number":466,"context_line":"                unexpected_task_containers[\u0027count\u0027] +\u003d 1"},{"line_number":467,"context_line":"                if unexpected_task_containers[\u0027count\u0027] \u003c 5:"},{"line_number":468,"context_line":"                    unexpected_task_containers[\u0027examples\u0027].append(c[\u0027name\u0027])"},{"line_number":469,"context_line":"            if task_container_int \u003e Timestamp.now():"},{"line_number":470,"context_line":"                break"}],"source_content_type":"text/x-python","patch_set":5,"id":"822b8378_90c2f607","line":467,"in_reply_to":"0ae91111_a35efb59","updated":"2024-06-24 15:45:31.000000000","message":"yeah I don\u0027t want to go back to yielding; it\u0027ll end up being a list eventually:\n\nhttps://review.opendev.org/c/openstack/swift/+/918366/5/swift/obj/expirer.py#154","commit_id":"c6e36d1e962e8eba623bdb086b5522e40368339e"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"b8c63f308be42cefb0ecd26273eb849c03d956d7","unresolved":true,"context_lines":[{"line_number":464,"context_line":"            if not is_expected_task_container(task_container_int,"},{"line_number":465,"context_line":"                                              **self.expirer_config):"},{"line_number":466,"context_line":"                unexpected_task_containers[\u0027count\u0027] +\u003d 1"},{"line_number":467,"context_line":"                if unexpected_task_containers[\u0027count\u0027] \u003c 5:"},{"line_number":468,"context_line":"                    unexpected_task_containers[\u0027examples\u0027].append(c[\u0027name\u0027])"},{"line_number":469,"context_line":"            if task_container_int \u003e Timestamp.now():"},{"line_number":470,"context_line":"                break"}],"source_content_type":"text/x-python","patch_set":5,"id":"0ae91111_a35efb59","line":467,"in_reply_to":"44a655ff_3bd124fe","updated":"2024-06-19 16:31:59.000000000","message":"I did find myself wondering \"why not just keep another list\" but agree this implementation avoids 2x lists, and also preserves the order (which may or may not be significant, but I appreciated not needing to decide if it was significant!)\n\nBut ... container_list could be avoided if the method continued to yield, and logged the unexpected containers as it exits:\nhttps://paste.openstack.org/show/bzpy8VVSgQeGuGi8BbIk/","commit_id":"c6e36d1e962e8eba623bdb086b5522e40368339e"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"741dbae4879c5c177c949a7a4758c964f0674311","unresolved":false,"context_lines":[{"line_number":464,"context_line":"            if not is_expected_task_container(task_container_int,"},{"line_number":465,"context_line":"                                              **self.expirer_config):"},{"line_number":466,"context_line":"                unexpected_task_containers[\u0027count\u0027] +\u003d 1"},{"line_number":467,"context_line":"                if unexpected_task_containers[\u0027count\u0027] \u003c 5:"},{"line_number":468,"context_line":"                    unexpected_task_containers[\u0027examples\u0027].append(c[\u0027name\u0027])"},{"line_number":469,"context_line":"            if task_container_int \u003e Timestamp.now():"},{"line_number":470,"context_line":"                break"}],"source_content_type":"text/x-python","patch_set":5,"id":"3f9c60ed_3017468f","line":467,"in_reply_to":"822b8378_90c2f607","updated":"2024-07-10 00:02:17.000000000","message":"this method didn\u0027t really get any better; I think we decided the logging is kind of janky and metrics might help:\n\nhttps://review.opendev.org/c/openstack/swift/+/920452/comment/d245cd8f_96acb38d/","commit_id":"c6e36d1e962e8eba623bdb086b5522e40368339e"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"6fa418271671f06f1a35aca6b0e4e7ad430aed17","unresolved":true,"context_lines":[{"line_number":476,"context_line":"                \u0027if you have recently changed your expirer config \u0027"},{"line_number":477,"context_line":"                \u0027this message should go away in a few days.\u0027,"},{"line_number":478,"context_line":"                unexpected_task_containers[\u0027count\u0027],"},{"line_number":479,"context_line":"                \u0027 \u0027.join(unexpected_task_containers[\u0027examples\u0027]))"},{"line_number":480,"context_line":"        if self.task_container_iteration_strategy \u003d\u003d \u0027randomized\u0027:"},{"line_number":481,"context_line":"            shuffle(container_list)"},{"line_number":482,"context_line":"        for task_container in container_list:"}],"source_content_type":"text/x-python","patch_set":5,"id":"d245cd8f_96acb38d","line":479,"updated":"2024-06-14 01:27:04.000000000","message":"I don\u0027t think it\u0027s fair to make this a warning; I\u0027m not 100% sure how useful it will be in practice.  It should happen once per-cycle until their clear (in our case 1 msg per day, but we are trying to reduce the cycle time with parallel task container iteration).\n\nMaybe we should carry this and try changing the config and seeing if we find these messages helpful/useful or if they could potentially be omitted/silenced/improved?","commit_id":"c6e36d1e962e8eba623bdb086b5522e40368339e"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"804102f9ccc56893bda6a85c14f55ef7de54b59e","unresolved":false,"context_lines":[{"line_number":476,"context_line":"                \u0027if you have recently changed your expirer config \u0027"},{"line_number":477,"context_line":"                \u0027this message should go away in a few days.\u0027,"},{"line_number":478,"context_line":"                unexpected_task_containers[\u0027count\u0027],"},{"line_number":479,"context_line":"                \u0027 \u0027.join(unexpected_task_containers[\u0027examples\u0027]))"},{"line_number":480,"context_line":"        if self.task_container_iteration_strategy \u003d\u003d \u0027randomized\u0027:"},{"line_number":481,"context_line":"            shuffle(container_list)"},{"line_number":482,"context_line":"        for task_container in container_list:"}],"source_content_type":"text/x-python","patch_set":5,"id":"351fc191_90a31a84","line":479,"in_reply_to":"d245cd8f_96acb38d","updated":"2024-10-28 22:11:05.000000000","message":"I think one new info log line per cycle is not so scary and might even be useful once the expirer-rebalance let\u0027s you actually DO something about it.  Maybe we could check if these messages went away after we finished rebalance!?","commit_id":"c6e36d1e962e8eba623bdb086b5522e40368339e"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"b8c63f308be42cefb0ecd26273eb849c03d956d7","unresolved":true,"context_lines":[{"line_number":311,"context_line":"        get delete_at timestamp from task_container name"},{"line_number":312,"context_line":"        \"\"\""},{"line_number":313,"context_line":"        # task_container name is timestamp"},{"line_number":314,"context_line":"        return Timestamp(task_container)"},{"line_number":315,"context_line":""},{"line_number":316,"context_line":"    def iter_task_containers_to_expire(self, task_account):"},{"line_number":317,"context_line":"        \"\"\""}],"source_content_type":"text/x-python","patch_set":6,"id":"c246ab58_ea140cdf","side":"PARENT","line":314,"updated":"2024-06-19 16:31:59.000000000","message":"ok, this didn\u0027t really warrant being broke out to a method","commit_id":"3637b1abd9240f7feeebc7f299d42fe8815d7dcd"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"deb7b0fb11e435af1a79694882c472f73219e440","unresolved":false,"context_lines":[{"line_number":311,"context_line":"        get delete_at timestamp from task_container name"},{"line_number":312,"context_line":"        \"\"\""},{"line_number":313,"context_line":"        # task_container name is timestamp"},{"line_number":314,"context_line":"        return Timestamp(task_container)"},{"line_number":315,"context_line":""},{"line_number":316,"context_line":"    def iter_task_containers_to_expire(self, task_account):"},{"line_number":317,"context_line":"        \"\"\""}],"source_content_type":"text/x-python","patch_set":6,"id":"c3984f96_513b94d5","side":"PARENT","line":314,"in_reply_to":"c246ab58_ea140cdf","updated":"2024-06-24 15:45:31.000000000","message":"Acknowledged","commit_id":"3637b1abd9240f7feeebc7f299d42fe8815d7dcd"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"b8c63f308be42cefb0ecd26273eb849c03d956d7","unresolved":true,"context_lines":[{"line_number":59,"context_line":"    \"\"\""},{"line_number":60,"context_line":"    Read the configuable values for the object-expirer consistently and issue"},{"line_number":61,"context_line":"    warnings appropriately when we encounter deprecated config options.  This"},{"line_number":62,"context_line":"    function is used by both the object-expirer and the proxy-server."},{"line_number":63,"context_line":""},{"line_number":64,"context_line":"    :param conf: a config dictionary"},{"line_number":65,"context_line":"    :returns: a dict, containing the required configuration (or default)"}],"source_content_type":"text/x-python","patch_set":6,"id":"88f61016_66db55d9","line":62,"updated":"2024-06-19 16:31:59.000000000","message":"and also SLO and object-server","commit_id":"c503d937bdf0898e739f4febf2b5f416d3af87e9"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"741dbae4879c5c177c949a7a4758c964f0674311","unresolved":false,"context_lines":[{"line_number":59,"context_line":"    \"\"\""},{"line_number":60,"context_line":"    Read the configuable values for the object-expirer consistently and issue"},{"line_number":61,"context_line":"    warnings appropriately when we encounter deprecated config options.  This"},{"line_number":62,"context_line":"    function is used by both the object-expirer and the proxy-server."},{"line_number":63,"context_line":""},{"line_number":64,"context_line":"    :param conf: a config dictionary"},{"line_number":65,"context_line":"    :returns: a dict, containing the required configuration (or default)"}],"source_content_type":"text/x-python","patch_set":6,"id":"7f6cf4b2_2831d3f4","line":62,"in_reply_to":"2afe1f57_30f49fd7","updated":"2024-07-10 00:02:17.000000000","message":"Done","commit_id":"c503d937bdf0898e739f4febf2b5f416d3af87e9"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"deb7b0fb11e435af1a79694882c472f73219e440","unresolved":true,"context_lines":[{"line_number":59,"context_line":"    \"\"\""},{"line_number":60,"context_line":"    Read the configuable values for the object-expirer consistently and issue"},{"line_number":61,"context_line":"    warnings appropriately when we encounter deprecated config options.  This"},{"line_number":62,"context_line":"    function is used by both the object-expirer and the proxy-server."},{"line_number":63,"context_line":""},{"line_number":64,"context_line":"    :param conf: a config dictionary"},{"line_number":65,"context_line":"    :returns: a dict, containing the required configuration (or default)"}],"source_content_type":"text/x-python","patch_set":6,"id":"2afe1f57_30f49fd7","line":62,"in_reply_to":"88f61016_66db55d9","updated":"2024-06-24 15:45:31.000000000","message":"I think SLO can get grouped with \"proxy-server\" (i.e. process not module) but probably good to call out `object-[expirer|server]` or just say \"multiple contexts\" 😊","commit_id":"c503d937bdf0898e739f4febf2b5f416d3af87e9"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"b8c63f308be42cefb0ecd26273eb849c03d956d7","unresolved":true,"context_lines":[{"line_number":94,"context_line":""},{"line_number":95,"context_line":"def get_expirer_container(x_delete_at, acc, cont, obj,"},{"line_number":96,"context_line":"                          task_container_per_day\u003dEXPIRER_CONTAINER_PER_DIVISOR,"},{"line_number":97,"context_line":"                          expirer_divisor\u003dEXPIRER_CONTAINER_DIVISOR, **kwargs):"},{"line_number":98,"context_line":"    \"\"\""},{"line_number":99,"context_line":"    Returns an expiring object task container name for given X-Delete-At and"},{"line_number":100,"context_line":"    (native string) a/c/o."}],"source_content_type":"text/x-python","patch_set":6,"id":"bad859aa_dc75c76a","line":97,"updated":"2024-06-19 16:31:59.000000000","message":"AFAICT all these helpers are passed (items of) an expirer_config (except in tests), so it seems odd, and brittle, to pass the config by expanding to named args that must always match the keys of expirer_config.\n\nThe pattern is that callers use ``get_expirer_config`` to get a config object, but then this method accepts ``task_container_per_day``, so the caller (author) has to know that the config object happens to be a dict that has that key, so passing ``**expirer_config`` is safe. It works, but is it a necessary pattern?\n\nAlso unfortunate to define the defaults again in the helper signatures. The defaults are already applied in ``get_expirer_config()``.\n\nIs there any reason (other than tests taking shortcuts) why we couldn\u0027t write just:\n\n```\ndef get_expirer_container(x_delete_at, acc, cont, obj, expirer_config)\n```\n\nI took a stab at how it would look https://review.opendev.org/c/openstack/swift/+/922332","commit_id":"c503d937bdf0898e739f4febf2b5f416d3af87e9"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"741dbae4879c5c177c949a7a4758c964f0674311","unresolved":false,"context_lines":[{"line_number":94,"context_line":""},{"line_number":95,"context_line":"def get_expirer_container(x_delete_at, acc, cont, obj,"},{"line_number":96,"context_line":"                          task_container_per_day\u003dEXPIRER_CONTAINER_PER_DIVISOR,"},{"line_number":97,"context_line":"                          expirer_divisor\u003dEXPIRER_CONTAINER_DIVISOR, **kwargs):"},{"line_number":98,"context_line":"    \"\"\""},{"line_number":99,"context_line":"    Returns an expiring object task container name for given X-Delete-At and"},{"line_number":100,"context_line":"    (native string) a/c/o."}],"source_content_type":"text/x-python","patch_set":6,"id":"5232013b_f0fbb5c0","line":97,"in_reply_to":"0a4d6d18_97aa10cd","updated":"2024-07-10 00:02:17.000000000","message":"went with an ExpirerConfig object","commit_id":"c503d937bdf0898e739f4febf2b5f416d3af87e9"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"deb7b0fb11e435af1a79694882c472f73219e440","unresolved":true,"context_lines":[{"line_number":94,"context_line":""},{"line_number":95,"context_line":"def get_expirer_container(x_delete_at, acc, cont, obj,"},{"line_number":96,"context_line":"                          task_container_per_day\u003dEXPIRER_CONTAINER_PER_DIVISOR,"},{"line_number":97,"context_line":"                          expirer_divisor\u003dEXPIRER_CONTAINER_DIVISOR, **kwargs):"},{"line_number":98,"context_line":"    \"\"\""},{"line_number":99,"context_line":"    Returns an expiring object task container name for given X-Delete-At and"},{"line_number":100,"context_line":"    (native string) a/c/o."}],"source_content_type":"text/x-python","patch_set":6,"id":"0a4d6d18_97aa10cd","line":97,"in_reply_to":"bad859aa_dc75c76a","updated":"2024-06-24 15:45:31.000000000","message":"\u003e seems odd, and brittle, to pass the config by expanding to named args that must always match the keys of expirer_config.\n\nI think the keys must match regarless, you can call them out in the function signature and get a TypeError or pass in a dict and get a KeyError.\n\n\u003e so the caller (author) has to know that the config object happens to be a dict that has that key\n\nRight, the pattern is to call the helpers with `**expirer_config` - I guess I hadn\u0027t given it much thought how someone might come to grok that outside of coping existing code.\n\n\u003e I took a stab at how it would look https://review.opendev.org/c/openstack/swift/+/922332\n\nI think that would work as well.  I wasn\u0027t trying to take shortcuts in tests as much as just make the required parameters called out in the function signature.","commit_id":"c503d937bdf0898e739f4febf2b5f416d3af87e9"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"b8c63f308be42cefb0ecd26273eb849c03d956d7","unresolved":true,"context_lines":[{"line_number":111,"context_line":""},{"line_number":112,"context_line":"def get_expirer_account_and_container(x_delete_at, acc, cont, obj,"},{"line_number":113,"context_line":"                                      account_name\u003dEXPIRER_ACCOUNT_NAME,"},{"line_number":114,"context_line":"                                      **expirer_config):"},{"line_number":115,"context_line":"    \"\"\""},{"line_number":116,"context_line":"    Calculates the expected expirer account and container for the target given"},{"line_number":117,"context_line":"    the current configuration."}],"source_content_type":"text/x-python","patch_set":6,"id":"03a1165b_c7c12702","line":114,"range":{"start_line":114,"start_character":40,"end_line":114,"end_character":54},"updated":"2024-06-19 16:31:59.000000000","message":"So this would I think be the caller\u0027s ``expirer_config`` minus the \u0027account_name\u0027 key.\n\nI\u0027m proposing above that we don\u0027t pass ``expirer_config`` instead of ``**expirer_config``, but if the current pattern stays it might be less confusing to name this ``**kwargs``, so there\u0027s no danger of someone passing it on thinking it has all the ``expirer_config`` items that the caller passed in.","commit_id":"c503d937bdf0898e739f4febf2b5f416d3af87e9"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"deb7b0fb11e435af1a79694882c472f73219e440","unresolved":true,"context_lines":[{"line_number":111,"context_line":""},{"line_number":112,"context_line":"def get_expirer_account_and_container(x_delete_at, acc, cont, obj,"},{"line_number":113,"context_line":"                                      account_name\u003dEXPIRER_ACCOUNT_NAME,"},{"line_number":114,"context_line":"                                      **expirer_config):"},{"line_number":115,"context_line":"    \"\"\""},{"line_number":116,"context_line":"    Calculates the expected expirer account and container for the target given"},{"line_number":117,"context_line":"    the current configuration."}],"source_content_type":"text/x-python","patch_set":6,"id":"8a4f4d04_9823aa04","line":114,"range":{"start_line":114,"start_character":40,"end_line":114,"end_character":54},"in_reply_to":"03a1165b_c7c12702","updated":"2024-06-24 15:45:31.000000000","message":"that\u0027s an interesting observation; but I think the idea is that it\u0027s the \"remaining_config\" or \"unused_config\" - if you wanted to call another method that explicitly required account_name in it\u0027s kwargs you\u0027d have to pass `account_name\u003daccount_name, **expirer_config`","commit_id":"c503d937bdf0898e739f4febf2b5f416d3af87e9"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"741dbae4879c5c177c949a7a4758c964f0674311","unresolved":false,"context_lines":[{"line_number":111,"context_line":""},{"line_number":112,"context_line":"def get_expirer_account_and_container(x_delete_at, acc, cont, obj,"},{"line_number":113,"context_line":"                                      account_name\u003dEXPIRER_ACCOUNT_NAME,"},{"line_number":114,"context_line":"                                      **expirer_config):"},{"line_number":115,"context_line":"    \"\"\""},{"line_number":116,"context_line":"    Calculates the expected expirer account and container for the target given"},{"line_number":117,"context_line":"    the current configuration."}],"source_content_type":"text/x-python","patch_set":6,"id":"c413dffc_d7483462","line":114,"range":{"start_line":114,"start_character":40,"end_line":114,"end_character":54},"in_reply_to":"8a4f4d04_9823aa04","updated":"2024-07-10 00:02:17.000000000","message":"Acknowledged","commit_id":"c503d937bdf0898e739f4febf2b5f416d3af87e9"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"b8c63f308be42cefb0ecd26273eb849c03d956d7","unresolved":true,"context_lines":[{"line_number":425,"context_line":""},{"line_number":426,"context_line":"    def iter_task_containers_to_expire(self, task_account):"},{"line_number":427,"context_line":"        \"\"\""},{"line_number":428,"context_line":"        Yields task_container names under the task_account if the delete at"},{"line_number":429,"context_line":"        timestamp of task_container is past."},{"line_number":430,"context_line":"        \"\"\""},{"line_number":431,"context_line":"        container_list \u003d []"}],"source_content_type":"text/x-python","patch_set":6,"id":"0e00890d_922f2cea","line":428,"range":{"start_line":428,"start_character":8,"end_line":428,"end_character":14},"updated":"2024-06-19 16:31:59.000000000","message":"no longer yields.\n\nMight also rename the method to get_task_containers_to_expire","commit_id":"c503d937bdf0898e739f4febf2b5f416d3af87e9"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"deb7b0fb11e435af1a79694882c472f73219e440","unresolved":true,"context_lines":[{"line_number":425,"context_line":""},{"line_number":426,"context_line":"    def iter_task_containers_to_expire(self, task_account):"},{"line_number":427,"context_line":"        \"\"\""},{"line_number":428,"context_line":"        Yields task_container names under the task_account if the delete at"},{"line_number":429,"context_line":"        timestamp of task_container is past."},{"line_number":430,"context_line":"        \"\"\""},{"line_number":431,"context_line":"        container_list \u003d []"}],"source_content_type":"text/x-python","patch_set":6,"id":"d4d6cdc0_8f31d588","line":428,"range":{"start_line":428,"start_character":8,"end_line":428,"end_character":14},"in_reply_to":"0e00890d_922f2cea","updated":"2024-06-24 15:45:31.000000000","message":"bah, this method - In my earliest attempts to refactor I noticed that on master we called it and immediately converted it to a list\n\nhttps://github.com/NVIDIA/swift/blob/master/swift/obj/expirer.py#L404-L406\n\nso i rephrased the whole thing as a generator - then as soon as I added randomization I wanted it to be a list again!\n\n\u003e Might also rename the method to get_task_containers_to_expire\n\nHah!  GREAT IDEA!  https://review.opendev.org/c/openstack/swift/+/919639/3/swift/obj/expirer.py#442","commit_id":"c503d937bdf0898e739f4febf2b5f416d3af87e9"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"741dbae4879c5c177c949a7a4758c964f0674311","unresolved":false,"context_lines":[{"line_number":425,"context_line":""},{"line_number":426,"context_line":"    def iter_task_containers_to_expire(self, task_account):"},{"line_number":427,"context_line":"        \"\"\""},{"line_number":428,"context_line":"        Yields task_container names under the task_account if the delete at"},{"line_number":429,"context_line":"        timestamp of task_container is past."},{"line_number":430,"context_line":"        \"\"\""},{"line_number":431,"context_line":"        container_list \u003d []"}],"source_content_type":"text/x-python","patch_set":6,"id":"870b3bf4_8517f6d0","line":428,"range":{"start_line":428,"start_character":8,"end_line":428,"end_character":14},"in_reply_to":"d4d6cdc0_8f31d588","updated":"2024-07-10 00:02:17.000000000","message":"Done","commit_id":"c503d937bdf0898e739f4febf2b5f416d3af87e9"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"9e1341653645bc630e2746759431a3fd177b5398","unresolved":true,"context_lines":[{"line_number":65,"context_line":"        Read the configurable object-expirer values consistently and issue"},{"line_number":66,"context_line":"        warnings appropriately when we encounter deprecated options."},{"line_number":67,"context_line":""},{"line_number":68,"context_line":"        This class is used in multiple context on proxy and object servers."},{"line_number":69,"context_line":""},{"line_number":70,"context_line":"        :param conf: a config dictionary"},{"line_number":71,"context_line":"        :param container_ring: optional, required in proxy context to lookup"}],"source_content_type":"text/x-python","patch_set":10,"id":"56f4a9b5_1ebd5c2f","line":68,"updated":"2024-07-18 16:52:31.000000000","message":"nit: s/context/contexts/","commit_id":"6fe94c3c0074b7e4d74d7cf23a198b869e816ce7"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"296beca32dc11b900b395aa306e293bbda879e69","unresolved":false,"context_lines":[{"line_number":65,"context_line":"        Read the configurable object-expirer values consistently and issue"},{"line_number":66,"context_line":"        warnings appropriately when we encounter deprecated options."},{"line_number":67,"context_line":""},{"line_number":68,"context_line":"        This class is used in multiple context on proxy and object servers."},{"line_number":69,"context_line":""},{"line_number":70,"context_line":"        :param conf: a config dictionary"},{"line_number":71,"context_line":"        :param container_ring: optional, required in proxy context to lookup"}],"source_content_type":"text/x-python","patch_set":10,"id":"d11ae90e_c1169f83","line":68,"in_reply_to":"56f4a9b5_1ebd5c2f","updated":"2024-07-19 14:05:59.000000000","message":"Done","commit_id":"6fe94c3c0074b7e4d74d7cf23a198b869e816ce7"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"9e1341653645bc630e2746759431a3fd177b5398","unresolved":true,"context_lines":[{"line_number":93,"context_line":"        self.expirer_divisor \u003d expirer_divisor"},{"line_number":94,"context_line":"        self.task_container_per_day \u003d config_positive_int_value("},{"line_number":95,"context_line":"            conf.get(\u0027expiring_objects_task_container_per_day\u0027,"},{"line_number":96,"context_line":"                     EXPIRER_CONTAINER_PER_DIVISOR))"},{"line_number":97,"context_line":"        self.container_ring \u003d container_ring"},{"line_number":98,"context_line":""},{"line_number":99,"context_line":"    def get_expirer_container(self, x_delete_at, acc, cont, obj):"}],"source_content_type":"text/x-python","patch_set":10,"id":"2dd65a4b_df6ee6b7","line":96,"updated":"2024-07-18 16:52:31.000000000","message":"I think ``expiring_objects_task_container_per_day`` must be less than ``expiring_objects_container_divisor``, otherwise the container names will bleed into adjacent divisors??\n\n```\ndiff --git a/test/unit/obj/test_expirer.py b/test/unit/obj/test_expirer.py\nindex 3d3ec2ec4..2fc32ce8c 100644\n--- a/test/unit/obj/test_expirer.py\n+++ b/test/unit/obj/test_expirer.py\n@@ -120,6 +120,21 @@ class TestGetExpirerContainer(TestCase):\n             1234, \u0027a\u0027, \u0027c\u0027, \u0027o\u0027)\n         self.assertEqual(container, \u00270000001199\u0027)\n\n+    def test_get_expirer_container(self):\n+        expirer_config \u003d ExpirerConfig(\n+            {\u0027expiring_objects_container_divisor\u0027: 20})\n+        with mock.patch(\u0027swift.obj.expirer.utils.hash_path\u0027,\n+                        return_value\u003dhex(101)[2:]):\n+            container \u003d expirer_config.get_expirer_container(\n+                1234, \u0027a\u0027, \u0027c\u0027, \u0027o\u0027)\n+            self.assertEqual(container, \u00270000001219\u0027)\n+        with mock.patch(\u0027swift.obj.expirer.utils.hash_path\u0027,\n+                        return_value\u003dhex(121)[2:]):\n+            container \u003d expirer_config.get_expirer_container(\n+                1254, \u0027a1\u0027, \u0027c1\u0027, \u0027o1\u0027)\n+            # oops?\n+            self.assertEqual(container, \u00270000001219\u0027)\n+\n     def test_get_expirer_container_legacy_config(self):\n         per_divisor \u003d 10\n         expirer_config \u003d ExpirerConfig({\n```","commit_id":"6fe94c3c0074b7e4d74d7cf23a198b869e816ce7"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"3c753577924d66ca4dbe4fe8e6634ada827d5d1b","unresolved":false,"context_lines":[{"line_number":93,"context_line":"        self.expirer_divisor \u003d expirer_divisor"},{"line_number":94,"context_line":"        self.task_container_per_day \u003d config_positive_int_value("},{"line_number":95,"context_line":"            conf.get(\u0027expiring_objects_task_container_per_day\u0027,"},{"line_number":96,"context_line":"                     EXPIRER_CONTAINER_PER_DIVISOR))"},{"line_number":97,"context_line":"        self.container_ring \u003d container_ring"},{"line_number":98,"context_line":""},{"line_number":99,"context_line":"    def get_expirer_container(self, x_delete_at, acc, cont, obj):"}],"source_content_type":"text/x-python","patch_set":10,"id":"64f0f20c_2e45c3ba","line":96,"in_reply_to":"065b0b95_dd5d05c6","updated":"2024-07-31 15:51:16.000000000","message":"Done","commit_id":"6fe94c3c0074b7e4d74d7cf23a198b869e816ce7"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"296beca32dc11b900b395aa306e293bbda879e69","unresolved":true,"context_lines":[{"line_number":93,"context_line":"        self.expirer_divisor \u003d expirer_divisor"},{"line_number":94,"context_line":"        self.task_container_per_day \u003d config_positive_int_value("},{"line_number":95,"context_line":"            conf.get(\u0027expiring_objects_task_container_per_day\u0027,"},{"line_number":96,"context_line":"                     EXPIRER_CONTAINER_PER_DIVISOR))"},{"line_number":97,"context_line":"        self.container_ring \u003d container_ring"},{"line_number":98,"context_line":""},{"line_number":99,"context_line":"    def get_expirer_container(self, x_delete_at, acc, cont, obj):"}],"source_content_type":"text/x-python","patch_set":10,"id":"065b0b95_dd5d05c6","line":96,"in_reply_to":"2dd65a4b_df6ee6b7","updated":"2024-07-19 14:05:59.000000000","message":"924511: sq? expirer: check task_container_per_day \u003c container_divisor | https://review.opendev.org/c/openstack/swift/+/924511","commit_id":"6fe94c3c0074b7e4d74d7cf23a198b869e816ce7"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"9e1341653645bc630e2746759431a3fd177b5398","unresolved":true,"context_lines":[{"line_number":106,"context_line":"                     self.task_container_per_day)"},{"line_number":107,"context_line":"        # even though the attr is named \"task_container_per_day\" it\u0027s actually"},{"line_number":108,"context_line":"        # \"task_container_per_divisor\" if for some reason the deprecated config"},{"line_number":109,"context_line":"        # \"expirer_divisor\" option doesn\u0027t have the default value of 86400"},{"line_number":110,"context_line":"        return normalize_delete_at_timestamp("},{"line_number":111,"context_line":"            int(x_delete_at) // self.expirer_divisor *"},{"line_number":112,"context_line":"            self.expirer_divisor - shard_int)"}],"source_content_type":"text/x-python","patch_set":10,"id":"47b4dde8_1429c46d","line":109,"updated":"2024-07-18 16:52:31.000000000","message":"thanks for the reminder 😊","commit_id":"6fe94c3c0074b7e4d74d7cf23a198b869e816ce7"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"3c753577924d66ca4dbe4fe8e6634ada827d5d1b","unresolved":false,"context_lines":[{"line_number":106,"context_line":"                     self.task_container_per_day)"},{"line_number":107,"context_line":"        # even though the attr is named \"task_container_per_day\" it\u0027s actually"},{"line_number":108,"context_line":"        # \"task_container_per_divisor\" if for some reason the deprecated config"},{"line_number":109,"context_line":"        # \"expirer_divisor\" option doesn\u0027t have the default value of 86400"},{"line_number":110,"context_line":"        return normalize_delete_at_timestamp("},{"line_number":111,"context_line":"            int(x_delete_at) // self.expirer_divisor *"},{"line_number":112,"context_line":"            self.expirer_divisor - shard_int)"}],"source_content_type":"text/x-python","patch_set":10,"id":"13b6baa0_ea5a7c75","line":109,"in_reply_to":"47b4dde8_1429c46d","updated":"2024-07-31 15:51:16.000000000","message":"Acknowledged","commit_id":"6fe94c3c0074b7e4d74d7cf23a198b869e816ce7"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"9e1341653645bc630e2746759431a3fd177b5398","unresolved":true,"context_lines":[{"line_number":109,"context_line":"        # \"expirer_divisor\" option doesn\u0027t have the default value of 86400"},{"line_number":110,"context_line":"        return normalize_delete_at_timestamp("},{"line_number":111,"context_line":"            int(x_delete_at) // self.expirer_divisor *"},{"line_number":112,"context_line":"            self.expirer_divisor - shard_int)"},{"line_number":113,"context_line":""},{"line_number":114,"context_line":"    def get_expirer_account_and_container(self, x_delete_at, acc, cont, obj):"},{"line_number":115,"context_line":"        \"\"\""}],"source_content_type":"text/x-python","patch_set":10,"id":"07069088_d831c926","line":112,"updated":"2024-07-18 16:52:31.000000000","message":"ok, this is same as what we had in utils but now with the configurable task_container_per_day","commit_id":"6fe94c3c0074b7e4d74d7cf23a198b869e816ce7"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"3c753577924d66ca4dbe4fe8e6634ada827d5d1b","unresolved":false,"context_lines":[{"line_number":109,"context_line":"        # \"expirer_divisor\" option doesn\u0027t have the default value of 86400"},{"line_number":110,"context_line":"        return normalize_delete_at_timestamp("},{"line_number":111,"context_line":"            int(x_delete_at) // self.expirer_divisor *"},{"line_number":112,"context_line":"            self.expirer_divisor - shard_int)"},{"line_number":113,"context_line":""},{"line_number":114,"context_line":"    def get_expirer_account_and_container(self, x_delete_at, acc, cont, obj):"},{"line_number":115,"context_line":"        \"\"\""}],"source_content_type":"text/x-python","patch_set":10,"id":"0e2d40ad_5cfa6d29","line":112,"in_reply_to":"07069088_d831c926","updated":"2024-07-31 15:51:16.000000000","message":"Acknowledged","commit_id":"6fe94c3c0074b7e4d74d7cf23a198b869e816ce7"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"9e1341653645bc630e2746759431a3fd177b5398","unresolved":true,"context_lines":[{"line_number":125,"context_line":"    def is_expected_task_container(self, task_container_int):"},{"line_number":126,"context_line":"        \"\"\""},{"line_number":127,"context_line":"        Validate the task_container timestamp as an expected value given the"},{"line_number":128,"context_line":"        current configuration, changing the expirer configuration will lead to"},{"line_number":129,"context_line":"        orphaned x-delete-at task objects on overwrite, which may stick around"},{"line_number":130,"context_line":"        a whole reclaim age."},{"line_number":131,"context_line":""}],"source_content_type":"text/x-python","patch_set":10,"id":"643083ce_2dbde9e4","line":128,"range":{"start_line":128,"start_character":31,"end_line":128,"end_character":40},"updated":"2024-07-18 16:52:31.000000000","message":"nit: start a new sentence at \u0027changing...\u0027","commit_id":"6fe94c3c0074b7e4d74d7cf23a198b869e816ce7"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"296beca32dc11b900b395aa306e293bbda879e69","unresolved":false,"context_lines":[{"line_number":125,"context_line":"    def is_expected_task_container(self, task_container_int):"},{"line_number":126,"context_line":"        \"\"\""},{"line_number":127,"context_line":"        Validate the task_container timestamp as an expected value given the"},{"line_number":128,"context_line":"        current configuration, changing the expirer configuration will lead to"},{"line_number":129,"context_line":"        orphaned x-delete-at task objects on overwrite, which may stick around"},{"line_number":130,"context_line":"        a whole reclaim age."},{"line_number":131,"context_line":""}],"source_content_type":"text/x-python","patch_set":10,"id":"ab5cf01c_60ba3848","line":128,"range":{"start_line":128,"start_character":31,"end_line":128,"end_character":40},"in_reply_to":"643083ce_2dbde9e4","updated":"2024-07-19 14:05:59.000000000","message":"Done","commit_id":"6fe94c3c0074b7e4d74d7cf23a198b869e816ce7"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"9e1341653645bc630e2746759431a3fd177b5398","unresolved":true,"context_lines":[{"line_number":130,"context_line":"        a whole reclaim age."},{"line_number":131,"context_line":""},{"line_number":132,"context_line":"        :params task_container_int: an int, all task_containers are expected"},{"line_number":133,"context_line":"                                    expected to be integer timestamps"},{"line_number":134,"context_line":""},{"line_number":135,"context_line":"        :returns: a boolean, True if name fits with the given config"},{"line_number":136,"context_line":"        \"\"\""}],"source_content_type":"text/x-python","patch_set":10,"id":"37a4f099_54c30f75","line":133,"range":{"start_line":133,"start_character":36,"end_line":133,"end_character":44},"updated":"2024-07-18 16:52:31.000000000","message":"typo \"expected expected\"","commit_id":"6fe94c3c0074b7e4d74d7cf23a198b869e816ce7"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"296beca32dc11b900b395aa306e293bbda879e69","unresolved":false,"context_lines":[{"line_number":130,"context_line":"        a whole reclaim age."},{"line_number":131,"context_line":""},{"line_number":132,"context_line":"        :params task_container_int: an int, all task_containers are expected"},{"line_number":133,"context_line":"                                    expected to be integer timestamps"},{"line_number":134,"context_line":""},{"line_number":135,"context_line":"        :returns: a boolean, True if name fits with the given config"},{"line_number":136,"context_line":"        \"\"\""}],"source_content_type":"text/x-python","patch_set":10,"id":"fc917a9e_041c3e09","line":133,"range":{"start_line":133,"start_character":36,"end_line":133,"end_character":44},"in_reply_to":"37a4f099_54c30f75","updated":"2024-07-19 14:05:59.000000000","message":"Done","commit_id":"6fe94c3c0074b7e4d74d7cf23a198b869e816ce7"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"9e1341653645bc630e2746759431a3fd177b5398","unresolved":true,"context_lines":[{"line_number":138,"context_line":"        r \u003d (task_container_int - 1) % self.expirer_divisor"},{"line_number":139,"context_line":"        # seconds offset should be no more than task_container_per_day i.e."},{"line_number":140,"context_line":"        # given % 86400, 86359 is ok (because 41 is less than 100), but 49768"},{"line_number":141,"context_line":"        # would be unexpected"},{"line_number":142,"context_line":"        return self.expirer_divisor - r \u003c\u003d self.task_container_per_day"},{"line_number":143,"context_line":""},{"line_number":144,"context_line":"    def get_delete_at_nodes(self, x_delete_at, acc, cont, obj):"}],"source_content_type":"text/x-python","patch_set":10,"id":"da27edd5_21ce4c8c","line":141,"updated":"2024-07-18 16:52:31.000000000","message":"ok, the edge case seems to be covered by tests","commit_id":"6fe94c3c0074b7e4d74d7cf23a198b869e816ce7"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"3c753577924d66ca4dbe4fe8e6634ada827d5d1b","unresolved":false,"context_lines":[{"line_number":138,"context_line":"        r \u003d (task_container_int - 1) % self.expirer_divisor"},{"line_number":139,"context_line":"        # seconds offset should be no more than task_container_per_day i.e."},{"line_number":140,"context_line":"        # given % 86400, 86359 is ok (because 41 is less than 100), but 49768"},{"line_number":141,"context_line":"        # would be unexpected"},{"line_number":142,"context_line":"        return self.expirer_divisor - r \u003c\u003d self.task_container_per_day"},{"line_number":143,"context_line":""},{"line_number":144,"context_line":"    def get_delete_at_nodes(self, x_delete_at, acc, cont, obj):"}],"source_content_type":"text/x-python","patch_set":10,"id":"438d446f_a2b982ba","line":141,"in_reply_to":"da27edd5_21ce4c8c","updated":"2024-07-31 15:51:16.000000000","message":"Acknowledged","commit_id":"6fe94c3c0074b7e4d74d7cf23a198b869e816ce7"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"9e1341653645bc630e2746759431a3fd177b5398","unresolved":true,"context_lines":[{"line_number":273,"context_line":""},{"line_number":274,"context_line":"    def __init__(self, conf, logger\u003dNone, swift\u003dNone):"},{"line_number":275,"context_line":"        self.conf \u003d conf"},{"line_number":276,"context_line":"        self.logger \u003d logger or get_logger(conf, log_route\u003dself.log_route)"},{"line_number":277,"context_line":"        self.interval \u003d float(conf.get(\u0027interval\u0027) or 300)"},{"line_number":278,"context_line":"        self.tasks_per_second \u003d float(conf.get(\u0027tasks_per_second\u0027, 50.0))"},{"line_number":279,"context_line":"        self.expirer_config \u003d ExpirerConfig(conf)"}],"source_content_type":"text/x-python","patch_set":10,"id":"fb3886dd_1f2e2cef","line":276,"updated":"2024-07-18 16:52:31.000000000","message":"off-topic: I was surprised this didn\u0027t call the ``Daemon.__init__`` , but it turns out that the Daemon constructor doesn\u0027t support the pattern of passing in a logger","commit_id":"6fe94c3c0074b7e4d74d7cf23a198b869e816ce7"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"3c753577924d66ca4dbe4fe8e6634ada827d5d1b","unresolved":false,"context_lines":[{"line_number":273,"context_line":""},{"line_number":274,"context_line":"    def __init__(self, conf, logger\u003dNone, swift\u003dNone):"},{"line_number":275,"context_line":"        self.conf \u003d conf"},{"line_number":276,"context_line":"        self.logger \u003d logger or get_logger(conf, log_route\u003dself.log_route)"},{"line_number":277,"context_line":"        self.interval \u003d float(conf.get(\u0027interval\u0027) or 300)"},{"line_number":278,"context_line":"        self.tasks_per_second \u003d float(conf.get(\u0027tasks_per_second\u0027, 50.0))"},{"line_number":279,"context_line":"        self.expirer_config \u003d ExpirerConfig(conf)"}],"source_content_type":"text/x-python","patch_set":10,"id":"5301cdd8_8401cdcd","line":276,"in_reply_to":"fb3886dd_1f2e2cef","updated":"2024-07-31 15:51:16.000000000","message":"super weird we don\u0027t call Daemon.__init__ !!!  It\u0027s not just here tho, all deamon\u0027s have an explicit __init__ and don\u0027t use the super class.\n\nI like the idea of adding some consistency here with the `log_route \u003d \u0027object-xxx\u0027` class attribute pattern tho - maybe we could try to move things in that direction, give `Deamon.__init__` a `logger\u003dNone` kwarg and start to re-use the couple line `Daemon.__init__` consistently!?\n\nmeh, not sure it\u0027s worth the trouble:\n\n925406: wip: use `Daemon.__init__` | https://review.opendev.org/c/openstack/swift/+/925406","commit_id":"6fe94c3c0074b7e4d74d7cf23a198b869e816ce7"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"d7e781cbb2ac6890076882b5b87a704427760843","unresolved":true,"context_lines":[{"line_number":76,"context_line":"            warnings.warn("},{"line_number":77,"context_line":"                \u0027expiring_objects_container_divisor is deprecated; use \u0027"},{"line_number":78,"context_line":"                \u0027expiring_objects_task_container_per_day instead\u0027,"},{"line_number":79,"context_line":"                DeprecationWarning)"},{"line_number":80,"context_line":"            expirer_divisor \u003d config_positive_int_value("},{"line_number":81,"context_line":"                conf[\u0027expiring_objects_container_divisor\u0027])"},{"line_number":82,"context_line":"        else:"}],"source_content_type":"text/x-python","patch_set":12,"id":"045887cd_444d9120","line":79,"updated":"2024-07-26 16:49:45.000000000","message":"This isn\u0027t going to show up for most operators -- from [the docs](https://docs.python.org/3/library/warnings.html#warning-categories), `DeprecationWarning`s are\n\n\u003e for warnings about deprecated features when those warnings are intended for other Python developers (**ignored by default**, unless triggered by code in `__main__`).\n\n(emphasis mine). If we want to go the `warnings` route, we want `FutureWarning` which is\n\n\u003e for warnings about deprecated features when those warnings are intended for end users of applications that are written in Python.\n\nBut can\u0027t we just pass a `logger` alongside `conf` and do `logger.warning`? I feel like that\u0027s the more \"normal\" approach. `warnings` should be reserved for developer messages (like the `set_prefix`/`set_statsd_prefix`/`ratelimit_sleep` warnings) where there\u0027s going to need to be a code change in some third-party repo to address it, or (in hopefully only very rare cases) when getting a sane, ops-configured logger is difficult (like the `getifaddrs`/`netifaces` warning in `utils/ipaddrs.py`, or the Jerasure deprecation in pyeclib -- both of which use `FutureWarning`).","commit_id":"d0e7bf1cfbf7370d244c5ea92c7856d60695d95d"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"dca26744e33cd58985e8b45a2ccca76de4ba4607","unresolved":true,"context_lines":[{"line_number":76,"context_line":"            warnings.warn("},{"line_number":77,"context_line":"                \u0027expiring_objects_container_divisor is deprecated; use \u0027"},{"line_number":78,"context_line":"                \u0027expiring_objects_task_container_per_day instead\u0027,"},{"line_number":79,"context_line":"                DeprecationWarning)"},{"line_number":80,"context_line":"            expirer_divisor \u003d config_positive_int_value("},{"line_number":81,"context_line":"                conf[\u0027expiring_objects_container_divisor\u0027])"},{"line_number":82,"context_line":"        else:"}],"source_content_type":"text/x-python","patch_set":12,"id":"d6ece363_2d8d049a","line":79,"in_reply_to":"045887cd_444d9120","updated":"2024-07-31 14:06:46.000000000","message":"sure enough, I only see a warning if I explicity set a custom warnings filter\n\n```\nvagrant@vagrant:~/swift$ PYTHONWARNINGS\u003ddefault::DeprecationWarning  swift-init object-expirer once\nWARNING: Unable to modify max process limit.  Running as non-root?\nWARNING: object-expirer.conf is deprecated. Move object-expirers\u0027 configuration into object-server.conf.\nRunning object-expirer once...(/etc/swift/object-expirer.conf.d)\n/vagrant/swift/swift/obj/expirer.py:76: DeprecationWarning: expiring_objects_container_divisor is deprecated; use expiring_objects_task_container_per_day instead\n  warnings.warn(\n```","commit_id":"d0e7bf1cfbf7370d244c5ea92c7856d60695d95d"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"3c753577924d66ca4dbe4fe8e6634ada827d5d1b","unresolved":false,"context_lines":[{"line_number":76,"context_line":"            warnings.warn("},{"line_number":77,"context_line":"                \u0027expiring_objects_container_divisor is deprecated; use \u0027"},{"line_number":78,"context_line":"                \u0027expiring_objects_task_container_per_day instead\u0027,"},{"line_number":79,"context_line":"                DeprecationWarning)"},{"line_number":80,"context_line":"            expirer_divisor \u003d config_positive_int_value("},{"line_number":81,"context_line":"                conf[\u0027expiring_objects_container_divisor\u0027])"},{"line_number":82,"context_line":"        else:"}],"source_content_type":"text/x-python","patch_set":12,"id":"67257065_6b10884e","line":79,"in_reply_to":"d6ece363_2d8d049a","updated":"2024-07-31 15:51:16.000000000","message":"Done","commit_id":"d0e7bf1cfbf7370d244c5ea92c7856d60695d95d"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"dca26744e33cd58985e8b45a2ccca76de4ba4607","unresolved":true,"context_lines":[{"line_number":352,"context_line":"        self.task_container_prefix \u003d \u0027\u0027"},{"line_number":353,"context_line":""},{"line_number":354,"context_line":"        request_tries \u003d int(self.conf.get(\u0027request_tries\u0027) or 3)"},{"line_number":355,"context_line":"        self.swift \u003d swift or InternalClient("},{"line_number":356,"context_line":"            self.ic_conf_path, \u0027Swift Object Expirer\u0027, request_tries,"},{"line_number":357,"context_line":"            use_replication_network\u003dTrue,"},{"line_number":358,"context_line":"            global_conf\u003d{\u0027log_name\u0027: \u0027%s-ic\u0027 % self.conf.get("}],"source_content_type":"text/x-python","patch_set":12,"id":"63d7f74f_b9e7dc0b","line":355,"updated":"2024-07-31 14:06:46.000000000","message":"hmmm, this internal client proxy app is going to always have the default expirer options unless they are explicitly configured in the object-expirer.conf or object-server.conf\n\nI think that\u0027s ok, this internal client isn\u0027t used for x-delete-at requests and has no SLO, but it feels like a bug waiting to happen?\n\nWe could pass the configured values in ``global_conf``","commit_id":"d0e7bf1cfbf7370d244c5ea92c7856d60695d95d"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"3c753577924d66ca4dbe4fe8e6634ada827d5d1b","unresolved":true,"context_lines":[{"line_number":352,"context_line":"        self.task_container_prefix \u003d \u0027\u0027"},{"line_number":353,"context_line":""},{"line_number":354,"context_line":"        request_tries \u003d int(self.conf.get(\u0027request_tries\u0027) or 3)"},{"line_number":355,"context_line":"        self.swift \u003d swift or InternalClient("},{"line_number":356,"context_line":"            self.ic_conf_path, \u0027Swift Object Expirer\u0027, request_tries,"},{"line_number":357,"context_line":"            use_replication_network\u003dTrue,"},{"line_number":358,"context_line":"            global_conf\u003d{\u0027log_name\u0027: \u0027%s-ic\u0027 % self.conf.get("}],"source_content_type":"text/x-python","patch_set":12,"id":"e86b34fe_4a787763","line":355,"in_reply_to":"63d7f74f_b9e7dc0b","updated":"2024-07-31 15:51:16.000000000","message":"yikes... but we can\u0027t say `global_conf\u003dself.conf` unless self.ic_conf_path has a bunch of `set x \u003d y` syntax to \"override\" global_conf 😞\n\nI don\u0027t want to have to explicitly select *a bunch* of named global_conf keys overrides from `self.conf` the existing `log_name \u003d mutulated-self.conf-get` is wonky enough already!\n\nmaybe if we *parse* self.ic_conf_path we could develop a generic set of rules for global_conf?  I think I understand why Tim has been saying \"let\u0027s just dump paste\" 😞","commit_id":"d0e7bf1cfbf7370d244c5ea92c7856d60695d95d"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"804102f9ccc56893bda6a85c14f55ef7de54b59e","unresolved":false,"context_lines":[{"line_number":352,"context_line":"        self.task_container_prefix \u003d \u0027\u0027"},{"line_number":353,"context_line":""},{"line_number":354,"context_line":"        request_tries \u003d int(self.conf.get(\u0027request_tries\u0027) or 3)"},{"line_number":355,"context_line":"        self.swift \u003d swift or InternalClient("},{"line_number":356,"context_line":"            self.ic_conf_path, \u0027Swift Object Expirer\u0027, request_tries,"},{"line_number":357,"context_line":"            use_replication_network\u003dTrue,"},{"line_number":358,"context_line":"            global_conf\u003d{\u0027log_name\u0027: \u0027%s-ic\u0027 % self.conf.get("}],"source_content_type":"text/x-python","patch_set":12,"id":"ac1f917e_ad8dba64","line":355,"in_reply_to":"e86b34fe_4a787763","updated":"2024-10-28 22:11:05.000000000","message":"so I guess for the time being we\u0027re going to lean into the \"it doesn\u0027t actually matter\" side of this comment and save \"consistency for consistency sake\" for a future exercise.\n\nMaybe that\u0027s especially relevant since THIS change \"just\" removes options, and task_container_per_day doesn\u0027t show up until the next change; at which point internal_client COULD be come inconsistent and it still wouldn\u0027t matter.\n\nMorever the `_make_internal_client` got refactored to support an `internal_client_conf_path` option which would at least ALLOW you to setup consistent DEFAULT section options for `[app:proxy-server]` across client access app and internal-client app.","commit_id":"d0e7bf1cfbf7370d244c5ea92c7856d60695d95d"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"3c753577924d66ca4dbe4fe8e6634ada827d5d1b","unresolved":true,"context_lines":[{"line_number":72,"context_line":"                               task container (part, nodes)"},{"line_number":73,"context_line":"        \"\"\""},{"line_number":74,"context_line":"        if \u0027expiring_objects_container_divisor\u0027 in conf:"},{"line_number":75,"context_line":"            if logger:"},{"line_number":76,"context_line":"                logger.warn("},{"line_number":77,"context_line":"                    \u0027expiring_objects_container_divisor is deprecated; use \u0027"},{"line_number":78,"context_line":"                    \u0027expiring_objects_task_container_per_day instead\u0027)"}],"source_content_type":"text/x-python","patch_set":13,"id":"b62df367_494a9e88","line":75,"updated":"2024-07-31 15:51:16.000000000","message":"😞\n\nmaybe we want an `app\u003dNone` kwarg?\n\n````\nself.container_ring \u003d getattr(app, \u0027container_ring\u0027, None)\nself.logger \u003d getattr(app, \u0027logger\u0027, None) or get_logger(conf)\n```\n\n????","commit_id":"c9c0e033e02dcedefdaff1b40094a07d14ab379d"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"804102f9ccc56893bda6a85c14f55ef7de54b59e","unresolved":false,"context_lines":[{"line_number":72,"context_line":"                               task container (part, nodes)"},{"line_number":73,"context_line":"        \"\"\""},{"line_number":74,"context_line":"        if \u0027expiring_objects_container_divisor\u0027 in conf:"},{"line_number":75,"context_line":"            if logger:"},{"line_number":76,"context_line":"                logger.warn("},{"line_number":77,"context_line":"                    \u0027expiring_objects_container_divisor is deprecated; use \u0027"},{"line_number":78,"context_line":"                    \u0027expiring_objects_task_container_per_day instead\u0027)"}],"source_content_type":"text/x-python","patch_set":13,"id":"02e7b4e9_7a3eb28c","line":75,"in_reply_to":"b62df367_494a9e88","updated":"2024-10-28 22:11:05.000000000","message":"so it turns out we\u0027re not very consistent about setting `self.conf \u003d conf` - but in general the idea of just passing a app/self that we can pull the logger off seems reasonable.\n\nI\u0027m not sure it\u0027s entirely virtuous to make the instantiation of this new object be so flexible but I went ahead and coded it up with tests anyway.  I do rather like how the final `or get_logger(conf)` means we don\u0027t have to `if logger`","commit_id":"c9c0e033e02dcedefdaff1b40094a07d14ab379d"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"3c753577924d66ca4dbe4fe8e6634ada827d5d1b","unresolved":true,"context_lines":[{"line_number":286,"context_line":"        self.logger \u003d logger or get_logger(conf, log_route\u003dself.log_route)"},{"line_number":287,"context_line":"        self.interval \u003d float(conf.get(\u0027interval\u0027) or 300)"},{"line_number":288,"context_line":"        self.tasks_per_second \u003d float(conf.get(\u0027tasks_per_second\u0027, 50.0))"},{"line_number":289,"context_line":"        self.expirer_config \u003d ExpirerConfig(conf, logger\u003dself.logger)"},{"line_number":290,"context_line":""},{"line_number":291,"context_line":"        self.conf_path \u003d \\"},{"line_number":292,"context_line":"            self.conf.get(\u0027__file__\u0027) or \u0027/etc/swift/object-expirer.conf\u0027"}],"source_content_type":"text/x-python","patch_set":13,"id":"f8c42c69_214a4206","line":289,"updated":"2024-07-31 15:51:16.000000000","message":"heh, if ExpirerConfig *just* took an app\n\n    self.expirer_config \u003d ExpirerConfig(self)\n\nit could even pull off a `conf \u003d app.conf` in this case 😄","commit_id":"c9c0e033e02dcedefdaff1b40094a07d14ab379d"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"804102f9ccc56893bda6a85c14f55ef7de54b59e","unresolved":false,"context_lines":[{"line_number":286,"context_line":"        self.logger \u003d logger or get_logger(conf, log_route\u003dself.log_route)"},{"line_number":287,"context_line":"        self.interval \u003d float(conf.get(\u0027interval\u0027) or 300)"},{"line_number":288,"context_line":"        self.tasks_per_second \u003d float(conf.get(\u0027tasks_per_second\u0027, 50.0))"},{"line_number":289,"context_line":"        self.expirer_config \u003d ExpirerConfig(conf, logger\u003dself.logger)"},{"line_number":290,"context_line":""},{"line_number":291,"context_line":"        self.conf_path \u003d \\"},{"line_number":292,"context_line":"            self.conf.get(\u0027__file__\u0027) or \u0027/etc/swift/object-expirer.conf\u0027"}],"source_content_type":"text/x-python","patch_set":13,"id":"742996f3_0358da1e","line":289,"in_reply_to":"f8c42c69_214a4206","updated":"2024-10-28 22:11:05.000000000","message":"and now it does!  Which... might not actually be boardly agreed as an improvement in style.","commit_id":"c9c0e033e02dcedefdaff1b40094a07d14ab379d"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"c02205ac2d10423d7033e84dfc99ef779c6c882d","unresolved":true,"context_lines":[{"line_number":457,"context_line":"            self.logger.info("},{"line_number":458,"context_line":"                \u0027processing %s unexpected task containers (e.g. %s) \u0027"},{"line_number":459,"context_line":"                \u0027if you have recently changed your expirer config \u0027"},{"line_number":460,"context_line":"                \u0027you can run swift-expirer-rebalance.\u0027,"},{"line_number":461,"context_line":"                unexpected_task_containers[\u0027count\u0027],"},{"line_number":462,"context_line":"                \u0027 \u0027.join(unexpected_task_containers[\u0027examples\u0027]))"},{"line_number":463,"context_line":"        return container_list"}],"source_content_type":"text/x-python","patch_set":22,"id":"b68b1623_4a395dc9","line":460,"updated":"2024-10-28 12:41:32.000000000","message":"this change has snuck in a little prematurely - we don\u0027t have ``swift-expirer-rebalance`` yet nor configurable ``task_container_per_day``","commit_id":"22983c09eefe45089a76cd7d343e50bf9508af8b"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"804102f9ccc56893bda6a85c14f55ef7de54b59e","unresolved":false,"context_lines":[{"line_number":457,"context_line":"            self.logger.info("},{"line_number":458,"context_line":"                \u0027processing %s unexpected task containers (e.g. %s) \u0027"},{"line_number":459,"context_line":"                \u0027if you have recently changed your expirer config \u0027"},{"line_number":460,"context_line":"                \u0027you can run swift-expirer-rebalance.\u0027,"},{"line_number":461,"context_line":"                unexpected_task_containers[\u0027count\u0027],"},{"line_number":462,"context_line":"                \u0027 \u0027.join(unexpected_task_containers[\u0027examples\u0027]))"},{"line_number":463,"context_line":"        return container_list"}],"source_content_type":"text/x-python","patch_set":22,"id":"3c5f0cdf_9a271d26","line":460,"in_reply_to":"b68b1623_4a395dc9","updated":"2024-10-28 22:11:05.000000000","message":"oh that\u0027s so frustrating; I specifically remember trying to get some of the ExpirerConfig error message to look sane in this patch.  I guess I missed this one.","commit_id":"22983c09eefe45089a76cd7d343e50bf9508af8b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"51d25ef595a99b441fb515378de96111e2edcd68","unresolved":true,"context_lines":[{"line_number":62,"context_line":""},{"line_number":63,"context_line":"        This class is used in multiple contexts on proxy and object servers."},{"line_number":64,"context_line":""},{"line_number":65,"context_line":"        :param app_or_conf: a config dictionary (or app with a conf attr)"},{"line_number":66,"context_line":"        :param logger: optional, will re-use the logger attribute of the app if"},{"line_number":67,"context_line":"                       provided or create one from the conf as needed."},{"line_number":68,"context_line":"        :param container_ring: optional, will re-use the container_ring"}],"source_content_type":"text/x-python","patch_set":23,"id":"a74662f9_3088feef","line":65,"updated":"2024-10-29 09:26:48.000000000","message":"I\u0027m not sure I see the advantage of inspecting the caller rather than having the caller pass args. This version seems more complex, and has required more tests being added, but I don\u0027t see the benefit in terms of significantly simple code elsewhere? Perhaps if it was a long list of args that was being reduced to ``app_or_conf``, but we\u0027ve actually got more args now. Maybe I\u0027m missing something.","commit_id":"81fb6359f63277a2b2ab985e80622ad796e4caef"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"ed2cb843f69c57e0cb32cf6ce4b2a7d8403bf05d","unresolved":false,"context_lines":[{"line_number":62,"context_line":""},{"line_number":63,"context_line":"        This class is used in multiple contexts on proxy and object servers."},{"line_number":64,"context_line":""},{"line_number":65,"context_line":"        :param app_or_conf: a config dictionary (or app with a conf attr)"},{"line_number":66,"context_line":"        :param logger: optional, will re-use the logger attribute of the app if"},{"line_number":67,"context_line":"                       provided or create one from the conf as needed."},{"line_number":68,"context_line":"        :param container_ring: optional, will re-use the container_ring"}],"source_content_type":"text/x-python","patch_set":23,"id":"460404ce_e2e9137b","line":65,"in_reply_to":"47f45489_fb29ac60","updated":"2024-11-01 21:39:57.000000000","message":"motivation had to do with some tests forgetting to pass in logger, but I think I fixed that and the explicit interface is quite nice for real code where as the implicit interface didn\u0027t actually prevent the test bugs.  This is better.","commit_id":"81fb6359f63277a2b2ab985e80622ad796e4caef"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"832a0989df50c98bfdea0deae4dd97e98cb67334","unresolved":true,"context_lines":[{"line_number":62,"context_line":""},{"line_number":63,"context_line":"        This class is used in multiple contexts on proxy and object servers."},{"line_number":64,"context_line":""},{"line_number":65,"context_line":"        :param app_or_conf: a config dictionary (or app with a conf attr)"},{"line_number":66,"context_line":"        :param logger: optional, will re-use the logger attribute of the app if"},{"line_number":67,"context_line":"                       provided or create one from the conf as needed."},{"line_number":68,"context_line":"        :param container_ring: optional, will re-use the container_ring"}],"source_content_type":"text/x-python","patch_set":23,"id":"47f45489_fb29ac60","line":65,"in_reply_to":"a74662f9_3088feef","updated":"2024-10-30 14:06:36.000000000","message":"I forget why I felt motivated to do it - I think I was expecting more of the consumers to have a `self.conf` AND a `self.logger` - but I ended up having to be more flexible.\n\nMaybe the main goal of \"get rid of `if logger`\" could still happen even w/o the implicit app/self attr lookups.  I can back it out if it\u0027s a blocker.","commit_id":"81fb6359f63277a2b2ab985e80622ad796e4caef"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"51d25ef595a99b441fb515378de96111e2edcd68","unresolved":true,"context_lines":[{"line_number":64,"context_line":""},{"line_number":65,"context_line":"        :param app_or_conf: a config dictionary (or app with a conf attr)"},{"line_number":66,"context_line":"        :param logger: optional, will re-use the logger attribute of the app if"},{"line_number":67,"context_line":"                       provided or create one from the conf as needed."},{"line_number":68,"context_line":"        :param container_ring: optional, will re-use the container_ring"},{"line_number":69,"context_line":"                               attribute of the app in proxy context to lookup"},{"line_number":70,"context_line":"                               task container (part, nodes)"}],"source_content_type":"text/x-python","patch_set":23,"id":"8aff0045_39ca7344","line":67,"range":{"start_line":67,"start_character":35,"end_line":67,"end_character":69},"updated":"2024-10-29 09:26:48.000000000","message":"+1 that makes sense, why live without a logger when we can construct it from the conf.","commit_id":"81fb6359f63277a2b2ab985e80622ad796e4caef"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"0e05111f20bd14b2960faea0b331283101a9161b","unresolved":true,"context_lines":[{"line_number":64,"context_line":""},{"line_number":65,"context_line":"        :param app_or_conf: a config dictionary (or app with a conf attr)"},{"line_number":66,"context_line":"        :param logger: optional, will re-use the logger attribute of the app if"},{"line_number":67,"context_line":"                       provided or create one from the conf as needed."},{"line_number":68,"context_line":"        :param container_ring: optional, will re-use the container_ring"},{"line_number":69,"context_line":"                               attribute of the app in proxy context to lookup"},{"line_number":70,"context_line":"                               task container (part, nodes)"}],"source_content_type":"text/x-python","patch_set":23,"id":"d4d013c8_e3406988","line":67,"range":{"start_line":67,"start_character":35,"end_line":67,"end_character":69},"in_reply_to":"8aff0045_39ca7344","updated":"2024-10-31 11:18:06.000000000","message":"AFAICT the only time a logger is *not* given is in tests","commit_id":"81fb6359f63277a2b2ab985e80622ad796e4caef"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"ed2cb843f69c57e0cb32cf6ce4b2a7d8403bf05d","unresolved":false,"context_lines":[{"line_number":64,"context_line":""},{"line_number":65,"context_line":"        :param app_or_conf: a config dictionary (or app with a conf attr)"},{"line_number":66,"context_line":"        :param logger: optional, will re-use the logger attribute of the app if"},{"line_number":67,"context_line":"                       provided or create one from the conf as needed."},{"line_number":68,"context_line":"        :param container_ring: optional, will re-use the container_ring"},{"line_number":69,"context_line":"                               attribute of the app in proxy context to lookup"},{"line_number":70,"context_line":"                               task container (part, nodes)"}],"source_content_type":"text/x-python","patch_set":23,"id":"25788721_4f57ea18","line":67,"range":{"start_line":67,"start_character":35,"end_line":67,"end_character":69},"in_reply_to":"d4d013c8_e3406988","updated":"2024-11-01 21:39:57.000000000","message":"i think that was actually why I tried to change this signature - i found some tests that were doing `assertFalse(self.logger.get_all_logs())` but hadn\u0027t passed in the logger (as it turned out there WAS no logs generated, but still felt easy to get wrong compared to passing in `self`)\n\nI think I fixed all the tests at this point tho.","commit_id":"81fb6359f63277a2b2ab985e80622ad796e4caef"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"51d25ef595a99b441fb515378de96111e2edcd68","unresolved":true,"context_lines":[{"line_number":71,"context_line":"        :param conf: only needed if app object doesn\u0027t have a conf attribute."},{"line_number":72,"context_line":"        \"\"\""},{"line_number":73,"context_line":"        conf \u003d getattr(app_or_conf, \u0027conf\u0027, conf)"},{"line_number":74,"context_line":"        if conf is None:"},{"line_number":75,"context_line":"            conf \u003d conf or app_or_conf"},{"line_number":76,"context_line":"        logger \u003d getattr(app_or_conf, \u0027logger\u0027, None) or \\"},{"line_number":77,"context_line":"            logger or get_logger(conf)"},{"line_number":78,"context_line":"        if \u0027expiring_objects_container_divisor\u0027 in conf:"}],"source_content_type":"text/x-python","patch_set":23,"id":"dcf59b47_852e737d","line":75,"range":{"start_line":74,"start_character":8,"end_line":75,"end_character":38},"updated":"2024-10-29 09:26:48.000000000","message":"The ``if`` (line 74) is unnecessary.\n\nLines 73-75 could reduce to just ``conf \u003d getattr(app_or_conf, \u0027conf\u0027, conf or app_or_conf)``.","commit_id":"81fb6359f63277a2b2ab985e80622ad796e4caef"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"ed2cb843f69c57e0cb32cf6ce4b2a7d8403bf05d","unresolved":false,"context_lines":[{"line_number":71,"context_line":"        :param conf: only needed if app object doesn\u0027t have a conf attribute."},{"line_number":72,"context_line":"        \"\"\""},{"line_number":73,"context_line":"        conf \u003d getattr(app_or_conf, \u0027conf\u0027, conf)"},{"line_number":74,"context_line":"        if conf is None:"},{"line_number":75,"context_line":"            conf \u003d conf or app_or_conf"},{"line_number":76,"context_line":"        logger \u003d getattr(app_or_conf, \u0027logger\u0027, None) or \\"},{"line_number":77,"context_line":"            logger or get_logger(conf)"},{"line_number":78,"context_line":"        if \u0027expiring_objects_container_divisor\u0027 in conf:"}],"source_content_type":"text/x-python","patch_set":23,"id":"5f807768_3075b140","line":75,"range":{"start_line":74,"start_character":8,"end_line":75,"end_character":38},"in_reply_to":"691a4cc7_4fd9669e","updated":"2024-11-01 21:39:57.000000000","message":"it\u0027s required now; doesn\u0027t matter.","commit_id":"81fb6359f63277a2b2ab985e80622ad796e4caef"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"832a0989df50c98bfdea0deae4dd97e98cb67334","unresolved":true,"context_lines":[{"line_number":71,"context_line":"        :param conf: only needed if app object doesn\u0027t have a conf attribute."},{"line_number":72,"context_line":"        \"\"\""},{"line_number":73,"context_line":"        conf \u003d getattr(app_or_conf, \u0027conf\u0027, conf)"},{"line_number":74,"context_line":"        if conf is None:"},{"line_number":75,"context_line":"            conf \u003d conf or app_or_conf"},{"line_number":76,"context_line":"        logger \u003d getattr(app_or_conf, \u0027logger\u0027, None) or \\"},{"line_number":77,"context_line":"            logger or get_logger(conf)"},{"line_number":78,"context_line":"        if \u0027expiring_objects_container_divisor\u0027 in conf:"}],"source_content_type":"text/x-python","patch_set":23,"id":"691a4cc7_4fd9669e","line":75,"range":{"start_line":74,"start_character":8,"end_line":75,"end_character":38},"in_reply_to":"dcf59b47_852e737d","updated":"2024-10-30 14:06:36.000000000","message":"I got tripped up with `conf\u003d{}` - maybe there\u0027s a better way to spell it.","commit_id":"81fb6359f63277a2b2ab985e80622ad796e4caef"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"12adff2a771a5e59e495ec6d7ea55e28557d5245","unresolved":true,"context_lines":[{"line_number":451,"context_line":"            self.logger.info("},{"line_number":452,"context_line":"                \u0027processing %s unexpected task containers (e.g. %s)\u0027,"},{"line_number":453,"context_line":"                unexpected_task_containers[\u0027count\u0027],"},{"line_number":454,"context_line":"                \u0027 \u0027.join(unexpected_task_containers[\u0027examples\u0027]))"},{"line_number":455,"context_line":"        return container_list"},{"line_number":456,"context_line":""},{"line_number":457,"context_line":"    def get_delay_reaping(self, target_account, target_container):"}],"source_content_type":"text/x-python","patch_set":25,"id":"99c36bbe_4f899693","line":454,"updated":"2024-11-01 21:27:32.000000000","message":"What do we expect operators to *do* with this information? I guess, run `swift-expirer-rebalancer` when that comes in?","commit_id":"4639e066e36bc3436c0d8555a536e96795218141"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"d0f98cfd362e46a234f338320f8ee19044d5e31d","unresolved":false,"context_lines":[{"line_number":451,"context_line":"            self.logger.info("},{"line_number":452,"context_line":"                \u0027processing %s unexpected task containers (e.g. %s)\u0027,"},{"line_number":453,"context_line":"                unexpected_task_containers[\u0027count\u0027],"},{"line_number":454,"context_line":"                \u0027 \u0027.join(unexpected_task_containers[\u0027examples\u0027]))"},{"line_number":455,"context_line":"        return container_list"},{"line_number":456,"context_line":""},{"line_number":457,"context_line":"    def get_delay_reaping(self, target_account, target_container):"}],"source_content_type":"text/x-python","patch_set":25,"id":"fa2700eb_1069a5d3","line":454,"in_reply_to":"79e7fcea_eac4860d","updated":"2024-11-05 00:21:48.000000000","message":"it\u0027s one log message per cycle and probably not bad information for operators to have if they don\u0027t expect it.","commit_id":"4639e066e36bc3436c0d8555a536e96795218141"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"b8a5331d4c780ae61da2189c4136848dc90fada1","unresolved":true,"context_lines":[{"line_number":451,"context_line":"            self.logger.info("},{"line_number":452,"context_line":"                \u0027processing %s unexpected task containers (e.g. %s)\u0027,"},{"line_number":453,"context_line":"                unexpected_task_containers[\u0027count\u0027],"},{"line_number":454,"context_line":"                \u0027 \u0027.join(unexpected_task_containers[\u0027examples\u0027]))"},{"line_number":455,"context_line":"        return container_list"},{"line_number":456,"context_line":""},{"line_number":457,"context_line":"    def get_delay_reaping(self, target_account, target_container):"}],"source_content_type":"text/x-python","patch_set":25,"id":"79e7fcea_eac4860d","line":454,"in_reply_to":"99c36bbe_4f899693","updated":"2024-11-04 00:03:10.000000000","message":"it\u0027s only an informational notice to operators, indicating that there was config changes (probably container divisor was not using default value 86400). it\u0027s not necessary for them to run swift-expirer-rebalancer with it.","commit_id":"4639e066e36bc3436c0d8555a536e96795218141"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"b8a5331d4c780ae61da2189c4136848dc90fada1","unresolved":true,"context_lines":[{"line_number":68,"context_line":"        \"\"\""},{"line_number":69,"context_line":"        logger \u003d logger or get_logger(conf)"},{"line_number":70,"context_line":"        if \u0027expiring_objects_container_divisor\u0027 in conf:"},{"line_number":71,"context_line":"            logger.warn("},{"line_number":72,"context_line":"                \u0027expiring_objects_container_divisor is deprecated\u0027)"},{"line_number":73,"context_line":"            expirer_divisor \u003d config_positive_int_value("},{"line_number":74,"context_line":"                conf[\u0027expiring_objects_container_divisor\u0027])"}],"source_content_type":"text/x-python","patch_set":27,"id":"9e7bd641_a5551551","line":71,"updated":"2024-11-04 00:03:10.000000000","message":"warn() is deprecated since python 3.3, use warning().","commit_id":"538c82e0fb554328d8ce72e513c583db2c20045a"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"036e2d36fc260aa18dbdf9734bc06a8168c92dc0","unresolved":false,"context_lines":[{"line_number":68,"context_line":"        \"\"\""},{"line_number":69,"context_line":"        logger \u003d logger or get_logger(conf)"},{"line_number":70,"context_line":"        if \u0027expiring_objects_container_divisor\u0027 in conf:"},{"line_number":71,"context_line":"            logger.warn("},{"line_number":72,"context_line":"                \u0027expiring_objects_container_divisor is deprecated\u0027)"},{"line_number":73,"context_line":"            expirer_divisor \u003d config_positive_int_value("},{"line_number":74,"context_line":"                conf[\u0027expiring_objects_container_divisor\u0027])"}],"source_content_type":"text/x-python","patch_set":27,"id":"5bedab0d_2188a126","line":71,"in_reply_to":"9e7bd641_a5551551","updated":"2024-11-04 00:06:52.000000000","message":"Done","commit_id":"538c82e0fb554328d8ce72e513c583db2c20045a"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"b8a5331d4c780ae61da2189c4136848dc90fada1","unresolved":true,"context_lines":[{"line_number":76,"context_line":"            expirer_divisor \u003d EXPIRER_CONTAINER_DIVISOR"},{"line_number":77,"context_line":""},{"line_number":78,"context_line":"        if \u0027expiring_objects_account_name\u0027 in conf:"},{"line_number":79,"context_line":"            logger.warn("},{"line_number":80,"context_line":"                \u0027expiring_objects_account_name is deprecated; you need \u0027"},{"line_number":81,"context_line":"                \u0027to migrate to the standard .expiring_objects account\u0027)"},{"line_number":82,"context_line":"            account_name \u003d (AUTO_CREATE_ACCOUNT_PREFIX +"}],"source_content_type":"text/x-python","patch_set":27,"id":"8a4310f9_c76c911f","line":79,"updated":"2024-11-04 00:03:10.000000000","message":"ditto","commit_id":"538c82e0fb554328d8ce72e513c583db2c20045a"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"036e2d36fc260aa18dbdf9734bc06a8168c92dc0","unresolved":false,"context_lines":[{"line_number":76,"context_line":"            expirer_divisor \u003d EXPIRER_CONTAINER_DIVISOR"},{"line_number":77,"context_line":""},{"line_number":78,"context_line":"        if \u0027expiring_objects_account_name\u0027 in conf:"},{"line_number":79,"context_line":"            logger.warn("},{"line_number":80,"context_line":"                \u0027expiring_objects_account_name is deprecated; you need \u0027"},{"line_number":81,"context_line":"                \u0027to migrate to the standard .expiring_objects account\u0027)"},{"line_number":82,"context_line":"            account_name \u003d (AUTO_CREATE_ACCOUNT_PREFIX +"}],"source_content_type":"text/x-python","patch_set":27,"id":"41614fd8_8117abfd","line":79,"in_reply_to":"8a4310f9_c76c911f","updated":"2024-11-04 00:06:52.000000000","message":"Done","commit_id":"538c82e0fb554328d8ce72e513c583db2c20045a"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"ed2cb843f69c57e0cb32cf6ce4b2a7d8403bf05d","unresolved":true,"context_lines":[{"line_number":452,"context_line":"                \u0027processing %s unexpected task containers (e.g. %s)\u0027,"},{"line_number":453,"context_line":"                unexpected_task_containers[\u0027count\u0027],"},{"line_number":454,"context_line":"                \u0027 \u0027.join(unexpected_task_containers[\u0027examples\u0027]))"},{"line_number":455,"context_line":"        return container_list"},{"line_number":456,"context_line":""},{"line_number":457,"context_line":"    def get_delay_reaping(self, target_account, target_container):"},{"line_number":458,"context_line":"        return get_delay_reaping(self.delay_reaping_times, target_account,"}],"source_content_type":"text/x-python","patch_set":27,"id":"e38a9810_e006db3c","line":455,"updated":"2024-11-01 21:39:57.000000000","message":"so this would all conflict textually with the \"remove iter_task_accounts_to_expire\" refactor; but it still seems like logically they could be flopped... but it may not be necessary if everone is excited to try and get rid of these dumb options ASAP.","commit_id":"538c82e0fb554328d8ce72e513c583db2c20045a"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"d0f98cfd362e46a234f338320f8ee19044d5e31d","unresolved":false,"context_lines":[{"line_number":452,"context_line":"                \u0027processing %s unexpected task containers (e.g. %s)\u0027,"},{"line_number":453,"context_line":"                unexpected_task_containers[\u0027count\u0027],"},{"line_number":454,"context_line":"                \u0027 \u0027.join(unexpected_task_containers[\u0027examples\u0027]))"},{"line_number":455,"context_line":"        return container_list"},{"line_number":456,"context_line":""},{"line_number":457,"context_line":"    def get_delay_reaping(self, target_account, target_container):"},{"line_number":458,"context_line":"        return get_delay_reaping(self.delay_reaping_times, target_account,"}],"source_content_type":"text/x-python","patch_set":27,"id":"84d673ad_29f2c1e2","line":455,"in_reply_to":"e38a9810_e006db3c","updated":"2024-11-05 00:21:48.000000000","message":"I remember one reason I didn\u0027t flop them was because the `remove iter_task_accounts_to_expire` makes the most sense immediately preceding the introduction of the parallel strategy because it also moves the my_index/divisor into a return value of `select_task_containers_to_expire` - so that the parallel strategy can make use of changing them... \n\nSince I don\u0027t have any idea that makes it obviously BETTER I\u0027m going to assume it\u0027s six-one-way/half-a-dozen-the-other and leave them in the order they\u0027re in for now.","commit_id":"538c82e0fb554328d8ce72e513c583db2c20045a"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"e1ecf17f20a86415a2e69cb1ba17ae654ea7dbe8","unresolved":true,"context_lines":[{"line_number":138,"context_line":"        # seconds offset should be no more than task_container_per_day i.e."},{"line_number":139,"context_line":"        # given % 86400, r\u003d\u003d86359 is ok (because 41 is less than 100), but"},{"line_number":140,"context_line":"        # 49768 would be unexpected"},{"line_number":141,"context_line":"        return self.expirer_divisor - r \u003c\u003d self.task_container_per_day"},{"line_number":142,"context_line":""},{"line_number":143,"context_line":"    def get_delete_at_nodes(self, x_delete_at, acc, cont, obj):"},{"line_number":144,"context_line":"        \"\"\""}],"source_content_type":"text/x-python","patch_set":34,"id":"a8fa7945_3ae1c8a4","line":141,"updated":"2025-01-03 22:15:04.000000000","message":"This all looks fishy -- I don\u0027t trust the `- 1` nor the `\u003c\u003d` without some more tests.","commit_id":"c7988c0a6830ea7fa2d9b14a5eb92a03f6f8e709"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"5b95077b5d52024580ecaada3582383bf9970fbc","unresolved":false,"context_lines":[{"line_number":138,"context_line":"        # seconds offset should be no more than task_container_per_day i.e."},{"line_number":139,"context_line":"        # given % 86400, r\u003d\u003d86359 is ok (because 41 is less than 100), but"},{"line_number":140,"context_line":"        # 49768 would be unexpected"},{"line_number":141,"context_line":"        return self.expirer_divisor - r \u003c\u003d self.task_container_per_day"},{"line_number":142,"context_line":""},{"line_number":143,"context_line":"    def get_delete_at_nodes(self, x_delete_at, acc, cont, obj):"},{"line_number":144,"context_line":"        \"\"\""}],"source_content_type":"text/x-python","patch_set":34,"id":"21f798a4_c98a05cc","line":141,"in_reply_to":"a8fa7945_3ae1c8a4","updated":"2025-02-07 16:37:06.000000000","message":"Acknowledged","commit_id":"c7988c0a6830ea7fa2d9b14a5eb92a03f6f8e709"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"e661a73d674cf561ab30863a6abc5747d5478408","unresolved":true,"context_lines":[{"line_number":452,"context_line":"                \u0027processing %s unexpected task containers (e.g. %s)\u0027,"},{"line_number":453,"context_line":"                unexpected_task_containers[\u0027count\u0027],"},{"line_number":454,"context_line":"                \u0027 \u0027.join(unexpected_task_containers[\u0027examples\u0027]))"},{"line_number":455,"context_line":"        return container_list"},{"line_number":456,"context_line":""},{"line_number":457,"context_line":"    def get_delay_reaping(self, target_account, target_container):"},{"line_number":458,"context_line":"        return get_delay_reaping(self.delay_reaping_times, target_account,"}],"source_content_type":"text/x-python","patch_set":34,"id":"d061a499_0b124f52","line":455,"updated":"2025-02-07 21:25:30.000000000","message":"Ditching the generator to return the whole list -- how big do we expect this to be? *Hopefully* just around `EXPIRER_CONTAINER_PER_DIVISOR` or even twice that, I suppose...","commit_id":"c7988c0a6830ea7fa2d9b14a5eb92a03f6f8e709"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"cc53537bdc2eabaf6787d0c01d044aaf13dc8d71","unresolved":false,"context_lines":[{"line_number":452,"context_line":"                \u0027processing %s unexpected task containers (e.g. %s)\u0027,"},{"line_number":453,"context_line":"                unexpected_task_containers[\u0027count\u0027],"},{"line_number":454,"context_line":"                \u0027 \u0027.join(unexpected_task_containers[\u0027examples\u0027]))"},{"line_number":455,"context_line":"        return container_list"},{"line_number":456,"context_line":""},{"line_number":457,"context_line":"    def get_delay_reaping(self, target_account, target_container):"},{"line_number":458,"context_line":"        return get_delay_reaping(self.delay_reaping_times, target_account,"}],"source_content_type":"text/x-python","patch_set":34,"id":"87b83b09_fd811b11","line":455,"in_reply_to":"d061a499_0b124f52","updated":"2025-02-08 01:07:26.000000000","message":"yes, what I have seen from prod is usually ``EXPIRER_CONTAINER_PER_DIVISOR`` or twice.","commit_id":"c7988c0a6830ea7fa2d9b14a5eb92a03f6f8e709"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"e661a73d674cf561ab30863a6abc5747d5478408","unresolved":true,"context_lines":[{"line_number":599,"context_line":""},{"line_number":600,"context_line":"                task_account_container_list \u003d \\"},{"line_number":601,"context_line":"                    [(task_account, task_container) for task_container in"},{"line_number":602,"context_line":"                     self.get_task_containers_to_expire(task_account)]"},{"line_number":603,"context_line":""},{"line_number":604,"context_line":"                # delete_task_iter is a generator to yield a dict of"},{"line_number":605,"context_line":"                # task_account, task_container, task_object, delete_timestamp,"}],"source_content_type":"text/x-python","patch_set":34,"id":"6398cf57_b5ddfe53","line":602,"updated":"2025-02-07 21:25:30.000000000","message":"And then we were going to turn it all into a list anyway, so w/e\n\nThough I guess I wonder a little at why we don\u0027t just hoist this part up into `get_task_containers_to_expire`...","commit_id":"c7988c0a6830ea7fa2d9b14a5eb92a03f6f8e709"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"cc53537bdc2eabaf6787d0c01d044aaf13dc8d71","unresolved":true,"context_lines":[{"line_number":599,"context_line":""},{"line_number":600,"context_line":"                task_account_container_list \u003d \\"},{"line_number":601,"context_line":"                    [(task_account, task_container) for task_container in"},{"line_number":602,"context_line":"                     self.get_task_containers_to_expire(task_account)]"},{"line_number":603,"context_line":""},{"line_number":604,"context_line":"                # delete_task_iter is a generator to yield a dict of"},{"line_number":605,"context_line":"                # task_account, task_container, task_object, delete_timestamp,"}],"source_content_type":"text/x-python","patch_set":34,"id":"3decd1fc_06169d01","line":602,"in_reply_to":"6398cf57_b5ddfe53","updated":"2025-02-08 01:07:26.000000000","message":"seems so. It\u0027s a small refactoring, if @clay.gerrard@gmail.com also like it, I am going to do it in the follow-up patches.","commit_id":"c7988c0a6830ea7fa2d9b14a5eb92a03f6f8e709"}],"swift/obj/server.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"8897b9d48b6dd910c839cd6ceefc4294a3b9aca1","unresolved":true,"context_lines":[{"line_number":469,"context_line":""},{"line_number":470,"context_line":"        expiring_objects_account_name, delete_at_container \u003d \\"},{"line_number":471,"context_line":"            expirer.get_expirer_account_and_container("},{"line_number":472,"context_line":"                delete_at, account, container, obj, **self.expirer_config)"},{"line_number":473,"context_line":"        if op !\u003d \u0027DELETE\u0027:"},{"line_number":474,"context_line":"            hosts \u003d headers_in.get(\u0027X-Delete-At-Host\u0027, None)"},{"line_number":475,"context_line":"            if hosts is None:"}],"source_content_type":"text/x-python","patch_set":3,"id":"0a581cc4_8aafadd7","line":472,"updated":"2024-05-31 20:45:21.000000000","message":"I sort of like how using this helper means we never have to dig into expirer_config ourselves.","commit_id":"8480d21430ed80f324c899397d991e9506853c29"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"d959d5a9bd1de78dcfa8765aa0e309875bbe8b94","unresolved":true,"context_lines":[{"line_number":469,"context_line":""},{"line_number":470,"context_line":"        expiring_objects_account_name, delete_at_container \u003d \\"},{"line_number":471,"context_line":"            expirer.get_expirer_account_and_container("},{"line_number":472,"context_line":"                delete_at, account, container, obj, **self.expirer_config)"},{"line_number":473,"context_line":"        if op !\u003d \u0027DELETE\u0027:"},{"line_number":474,"context_line":"            hosts \u003d headers_in.get(\u0027X-Delete-At-Host\u0027, None)"},{"line_number":475,"context_line":"            if hosts is None:"}],"source_content_type":"text/x-python","patch_set":3,"id":"34f67760_7443cd99","line":472,"in_reply_to":"0a581cc4_8aafadd7","updated":"2024-06-04 16:30:40.000000000","message":"LOL, except we *do* anyway\n\nhttps://review.opendev.org/c/openstack/swift/+/920452/4/swift/obj/expirer.py#335","commit_id":"8480d21430ed80f324c899397d991e9506853c29"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"741dbae4879c5c177c949a7a4758c964f0674311","unresolved":false,"context_lines":[{"line_number":469,"context_line":""},{"line_number":470,"context_line":"        expiring_objects_account_name, delete_at_container \u003d \\"},{"line_number":471,"context_line":"            expirer.get_expirer_account_and_container("},{"line_number":472,"context_line":"                delete_at, account, container, obj, **self.expirer_config)"},{"line_number":473,"context_line":"        if op !\u003d \u0027DELETE\u0027:"},{"line_number":474,"context_line":"            hosts \u003d headers_in.get(\u0027X-Delete-At-Host\u0027, None)"},{"line_number":475,"context_line":"            if hosts is None:"}],"source_content_type":"text/x-python","patch_set":3,"id":"f0a01b78_dd21e7d3","line":472,"in_reply_to":"34f67760_7443cd99","updated":"2024-07-10 00:02:17.000000000","message":"new version uses self.expirer_config.account_name as needed","commit_id":"8480d21430ed80f324c899397d991e9506853c29"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"6fa418271671f06f1a35aca6b0e4e7ad430aed17","unresolved":true,"context_lines":[{"line_number":458,"context_line":"        updates \u003d [(None, None)]"},{"line_number":459,"context_line":""},{"line_number":460,"context_line":"        partition \u003d None"},{"line_number":461,"context_line":"        hosts \u003d contdevices \u003d [None]"},{"line_number":462,"context_line":"        headers_in \u003d request.headers"},{"line_number":463,"context_line":"        headers_out \u003d HeaderKeyDict({"},{"line_number":464,"context_line":"            # system accounts are always Policy-0"}],"source_content_type":"text/x-python","patch_set":5,"id":"4938deac_4474c3e0","side":"PARENT","line":461,"updated":"2024-06-14 01:27:04.000000000","message":"normally I\u0027m a fan of initializing values at the top of function but these are weird.\n\nupdates is a list of (target_host, target_device)\npartition must not be None when x-delete-at-device (a csv) is provided for the inline requests to make sense.\n\nthis mehod will return early if x-delete-at-host is not provided (common case when more object replicas than container replicas)\n\nhosts and contdevices were only ever used in the `if op !\u003d \u0027DELETE\u0027` block and always overwritten!\n\nin the `op \u003d\u003d DELETE`/else block, we implicitly relied on these defaults to trigger the \"DELETE always goes to async\" behavior - which is required; because the proxy didn\u0027t know about the existing x-delete-at and we don\u0027t have rings to look up the target.\n\nI\u0027m not sure deleting these helps make any of that more maintainable; but I certainly had trouble understanding what these defaults were trying to acomplish while groking this code.","commit_id":"689ae8e8a1e7223ff20b44afa5c1790187751bfd"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"741dbae4879c5c177c949a7a4758c964f0674311","unresolved":false,"context_lines":[{"line_number":458,"context_line":"        updates \u003d [(None, None)]"},{"line_number":459,"context_line":""},{"line_number":460,"context_line":"        partition \u003d None"},{"line_number":461,"context_line":"        hosts \u003d contdevices \u003d [None]"},{"line_number":462,"context_line":"        headers_in \u003d request.headers"},{"line_number":463,"context_line":"        headers_out \u003d HeaderKeyDict({"},{"line_number":464,"context_line":"            # system accounts are always Policy-0"}],"source_content_type":"text/x-python","patch_set":5,"id":"3f0f20a4_669996d6","side":"PARENT","line":461,"in_reply_to":"4938deac_4474c3e0","updated":"2024-07-10 00:02:17.000000000","message":"Acknowledged","commit_id":"689ae8e8a1e7223ff20b44afa5c1790187751bfd"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"6fa418271671f06f1a35aca6b0e4e7ad430aed17","unresolved":false,"context_lines":[{"line_number":182,"context_line":"            (conf.get(\u0027expiring_objects_account_name\u0027) or \u0027expiring_objects\u0027)"},{"line_number":183,"context_line":""},{"line_number":184,"context_line":"        self.expiring_objects_container_divisor \u003d \\"},{"line_number":185,"context_line":"            int(conf.get(\u0027expiring_objects_container_divisor\u0027) or 86400)"},{"line_number":186,"context_line":"        # Initialization was successful, so now apply the network chunk size"},{"line_number":187,"context_line":"        # parameter as the default read / write buffer size for the network"},{"line_number":188,"context_line":"        # sockets."}],"source_content_type":"text/x-python","patch_set":5,"id":"f25e8808_d34f5ec2","line":185,"updated":"2024-06-14 01:27:04.000000000","message":"umm... these old attributes should go?","commit_id":"c6e36d1e962e8eba623bdb086b5522e40368339e"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"6fa418271671f06f1a35aca6b0e4e7ad430aed17","unresolved":true,"context_lines":[{"line_number":485,"context_line":"                self.logger.debug("},{"line_number":486,"context_line":"                    \u0027Proxy X-Delete-At-Container %r does not match expected \u0027"},{"line_number":487,"context_line":"                    \u0027%r for current expirer_config.\u0027,"},{"line_number":488,"context_line":"                    proxy_delete_at_container, delete_at_container)"},{"line_number":489,"context_line":"                # it\u0027s not possible to say which is \"more correct\", this will"},{"line_number":490,"context_line":"                # at least match the host/part/device"},{"line_number":491,"context_line":"                delete_at_container \u003d normalize_delete_at_timestamp("}],"source_content_type":"text/x-python","patch_set":5,"id":"45f4d886_2ff6f9e2","line":488,"updated":"2024-06-14 01:27:04.000000000","message":"`self.stats.increment(\u0027unexpected_proxy_delete_at_container\u0027)` or YAGNI?","commit_id":"c6e36d1e962e8eba623bdb086b5522e40368339e"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"deb7b0fb11e435af1a79694882c472f73219e440","unresolved":true,"context_lines":[{"line_number":485,"context_line":"                self.logger.debug("},{"line_number":486,"context_line":"                    \u0027Proxy X-Delete-At-Container %r does not match expected \u0027"},{"line_number":487,"context_line":"                    \u0027%r for current expirer_config.\u0027,"},{"line_number":488,"context_line":"                    proxy_delete_at_container, delete_at_container)"},{"line_number":489,"context_line":"                # it\u0027s not possible to say which is \"more correct\", this will"},{"line_number":490,"context_line":"                # at least match the host/part/device"},{"line_number":491,"context_line":"                delete_at_container \u003d normalize_delete_at_timestamp("}],"source_content_type":"text/x-python","patch_set":5,"id":"41832abb_7b8e739a","line":488,"in_reply_to":"2f1a7a49_858f949c","updated":"2024-06-24 15:45:31.000000000","message":"heh, i\u0027m not sure if you\u0027re advocating we add it now or wait - any change to the config before or after this change will always orphan old/overwritten x-delete-at updates 😞 (old task written to old config, cleanup delete goes to new config)","commit_id":"c6e36d1e962e8eba623bdb086b5522e40368339e"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"741dbae4879c5c177c949a7a4758c964f0674311","unresolved":false,"context_lines":[{"line_number":485,"context_line":"                self.logger.debug("},{"line_number":486,"context_line":"                    \u0027Proxy X-Delete-At-Container %r does not match expected \u0027"},{"line_number":487,"context_line":"                    \u0027%r for current expirer_config.\u0027,"},{"line_number":488,"context_line":"                    proxy_delete_at_container, delete_at_container)"},{"line_number":489,"context_line":"                # it\u0027s not possible to say which is \"more correct\", this will"},{"line_number":490,"context_line":"                # at least match the host/part/device"},{"line_number":491,"context_line":"                delete_at_container \u003d normalize_delete_at_timestamp("}],"source_content_type":"text/x-python","patch_set":5,"id":"f9cc58ac_cf9669b9","line":488,"in_reply_to":"41832abb_7b8e739a","updated":"2024-07-10 00:02:17.000000000","message":"I think the real danger on master is configuring the expiring_objects_account_name since that\u0027s not sent in request headers\n\nI\u0027m not sure I can justify a new metric adding much value to any real-world debug loop - if we\u0027re running inconsistent configs for any period we\u0027re not going to notice that from some one off alert we setup for some new  \u0027object_server.expirer.unexpected_delete_at_container\u0027 metric.\n\nI think ultimately this condition should be considred \"operating normally\" and \"trust the proxy\" is the only sensible answer; Probably barely deserves a debug message for any real world scenario outside of the development and testing of *this* change; so if there\u0027s a debate to be had it might be \"should we remove this check/debug message\" rather than \"should we add metrics for this\"\n\nIf you\u0027re down in the weeds enough to be looking at this condition the example \"I expected x and got y\" debug message might actually be more useful (even if off-by-default) than a generic \"something doesn\u0027t match; good luck figuring out what/why\". \n So if I had to pick just adding ONE new \"probably unneccessary telemetry\" it still feels like a reasonable compromise to provide a safety net where one *could* set `log_level \u003d DEBUG` on a single node if they wanted to functionally validate they understand what\u0027s going on when changing this new option... But, I would easily be presuaded to remove it if it\u0027s a distraction.","commit_id":"c6e36d1e962e8eba623bdb086b5522e40368339e"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"b8c63f308be42cefb0ecd26273eb849c03d956d7","unresolved":true,"context_lines":[{"line_number":485,"context_line":"                self.logger.debug("},{"line_number":486,"context_line":"                    \u0027Proxy X-Delete-At-Container %r does not match expected \u0027"},{"line_number":487,"context_line":"                    \u0027%r for current expirer_config.\u0027,"},{"line_number":488,"context_line":"                    proxy_delete_at_container, delete_at_container)"},{"line_number":489,"context_line":"                # it\u0027s not possible to say which is \"more correct\", this will"},{"line_number":490,"context_line":"                # at least match the host/part/device"},{"line_number":491,"context_line":"                delete_at_container \u003d normalize_delete_at_timestamp("}],"source_content_type":"text/x-python","patch_set":5,"id":"2f1a7a49_858f949c","line":488,"in_reply_to":"45f4d886_2ff6f9e2","updated":"2024-06-19 16:31:59.000000000","message":"IIUC this could happen on master if the divisor config was inconsistent?\n\nIf so, a stat might be useful if you\u0027re wondering why you have stuck objects in the queue, but feels like a different topic. YAGNI until it\u0027s too late to add it 😊","commit_id":"c6e36d1e962e8eba623bdb086b5522e40368339e"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"b8c63f308be42cefb0ecd26273eb849c03d956d7","unresolved":true,"context_lines":[{"line_number":472,"context_line":"                # If header is missing, no update needed as sufficient other"},{"line_number":473,"context_line":"                # object servers should perform the required update."},{"line_number":474,"context_line":"                return"},{"line_number":475,"context_line":"            if delete_at_container !\u003d headers_in.get("},{"line_number":476,"context_line":"                    \u0027X-Delete-At-Container\u0027, delete_at_container):"},{"line_number":477,"context_line":"                proxy_delete_at_container \u003d headers_in[\u0027X-Delete-At-Container\u0027]"},{"line_number":478,"context_line":"                # Inconsistent configuratoin may lead to orphaned expirer task"}],"source_content_type":"text/x-python","patch_set":6,"id":"83512435_6873ef89","line":475,"updated":"2024-06-19 16:31:59.000000000","message":"IIUC on master we\u0027ll log a warning if the proxy appears to be old and not sending the headers, but with this patch we\u0027ll log only log at debug level if the proxy does send the header but it disagrees with the local config.\n\nThat change doesn\u0027t seem like a consequence of the new option, and feels like it\u0027s at least worth a mention in the commit message?","commit_id":"c503d937bdf0898e739f4febf2b5f416d3af87e9"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"deb7b0fb11e435af1a79694882c472f73219e440","unresolved":true,"context_lines":[{"line_number":472,"context_line":"                # If header is missing, no update needed as sufficient other"},{"line_number":473,"context_line":"                # object servers should perform the required update."},{"line_number":474,"context_line":"                return"},{"line_number":475,"context_line":"            if delete_at_container !\u003d headers_in.get("},{"line_number":476,"context_line":"                    \u0027X-Delete-At-Container\u0027, delete_at_container):"},{"line_number":477,"context_line":"                proxy_delete_at_container \u003d headers_in[\u0027X-Delete-At-Container\u0027]"},{"line_number":478,"context_line":"                # Inconsistent configuratoin may lead to orphaned expirer task"}],"source_content_type":"text/x-python","patch_set":6,"id":"bf4c9424_52ccf521","line":475,"in_reply_to":"83512435_6873ef89","updated":"2024-06-24 15:45:31.000000000","message":"I don\u0027t mind mentioning something to the effect in the commit message; but I\u0027m not really sure what to say about it:\n\nhttps://review.opendev.org/c/openstack/swift/+/920452/comment/d245cd8f_96acb38d/\n\nthe existing warning seemed aimed at some kind of upgrade path I don\u0027t really think I understand very well; or maybe had unspecified consequences that weren\u0027t well understood at the time?  It\u0027d be fun to run with inconsistent expirer_account and watch the proxy and object nodes pick different parts for the same container names!?","commit_id":"c503d937bdf0898e739f4febf2b5f416d3af87e9"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"741dbae4879c5c177c949a7a4758c964f0674311","unresolved":false,"context_lines":[{"line_number":472,"context_line":"                # If header is missing, no update needed as sufficient other"},{"line_number":473,"context_line":"                # object servers should perform the required update."},{"line_number":474,"context_line":"                return"},{"line_number":475,"context_line":"            if delete_at_container !\u003d headers_in.get("},{"line_number":476,"context_line":"                    \u0027X-Delete-At-Container\u0027, delete_at_container):"},{"line_number":477,"context_line":"                proxy_delete_at_container \u003d headers_in[\u0027X-Delete-At-Container\u0027]"},{"line_number":478,"context_line":"                # Inconsistent configuratoin may lead to orphaned expirer task"}],"source_content_type":"text/x-python","patch_set":6,"id":"d6a7848a_c1cff131","line":475,"in_reply_to":"bf4c9424_52ccf521","updated":"2024-07-10 00:02:17.000000000","message":"adding back the warning behavior on missing header (with a snarky comment) so that I don\u0027t have to bikeshed over how to justify removing it in the commit message.","commit_id":"c503d937bdf0898e739f4febf2b5f416d3af87e9"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"b8c63f308be42cefb0ecd26273eb849c03d956d7","unresolved":true,"context_lines":[{"line_number":475,"context_line":"            if delete_at_container !\u003d headers_in.get("},{"line_number":476,"context_line":"                    \u0027X-Delete-At-Container\u0027, delete_at_container):"},{"line_number":477,"context_line":"                proxy_delete_at_container \u003d headers_in[\u0027X-Delete-At-Container\u0027]"},{"line_number":478,"context_line":"                # Inconsistent configuratoin may lead to orphaned expirer task"},{"line_number":479,"context_line":"                # queue objects when X-Delete-At is updated, which can stick"},{"line_number":480,"context_line":"                # around for a whole reclaim age."},{"line_number":481,"context_line":"                self.logger.debug("}],"source_content_type":"text/x-python","patch_set":6,"id":"c7bd35ef_6f130ee8","line":478,"range":{"start_line":478,"start_character":31,"end_line":478,"end_character":44},"updated":"2024-06-19 16:31:59.000000000","message":"spelling: configuration","commit_id":"c503d937bdf0898e739f4febf2b5f416d3af87e9"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"33adc3bde26369da862706bc0a1f289481d33c11","unresolved":false,"context_lines":[{"line_number":475,"context_line":"            if delete_at_container !\u003d headers_in.get("},{"line_number":476,"context_line":"                    \u0027X-Delete-At-Container\u0027, delete_at_container):"},{"line_number":477,"context_line":"                proxy_delete_at_container \u003d headers_in[\u0027X-Delete-At-Container\u0027]"},{"line_number":478,"context_line":"                # Inconsistent configuratoin may lead to orphaned expirer task"},{"line_number":479,"context_line":"                # queue objects when X-Delete-At is updated, which can stick"},{"line_number":480,"context_line":"                # around for a whole reclaim age."},{"line_number":481,"context_line":"                self.logger.debug("}],"source_content_type":"text/x-python","patch_set":6,"id":"28f38b04_977c971e","line":478,"range":{"start_line":478,"start_character":31,"end_line":478,"end_character":44},"in_reply_to":"c7bd35ef_6f130ee8","updated":"2024-06-19 16:36:10.000000000","message":"Done","commit_id":"c503d937bdf0898e739f4febf2b5f416d3af87e9"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"b8c63f308be42cefb0ecd26273eb849c03d956d7","unresolved":true,"context_lines":[{"line_number":508,"context_line":"                return"},{"line_number":509,"context_line":"            # DELETE op always go directly to async_pending"},{"line_number":510,"context_line":"            partition \u003d None"},{"line_number":511,"context_line":"            updates \u003d [(None, None)]"},{"line_number":512,"context_line":""},{"line_number":513,"context_line":"        for host, contdevice in updates:"},{"line_number":514,"context_line":"            self.async_update("}],"source_content_type":"text/x-python","patch_set":6,"id":"1fe0b3e0_e348fb44","line":511,"updated":"2024-06-19 16:31:59.000000000","message":"FWIW I prefer these being declared here","commit_id":"c503d937bdf0898e739f4febf2b5f416d3af87e9"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"deb7b0fb11e435af1a79694882c472f73219e440","unresolved":false,"context_lines":[{"line_number":508,"context_line":"                return"},{"line_number":509,"context_line":"            # DELETE op always go directly to async_pending"},{"line_number":510,"context_line":"            partition \u003d None"},{"line_number":511,"context_line":"            updates \u003d [(None, None)]"},{"line_number":512,"context_line":""},{"line_number":513,"context_line":"        for host, contdevice in updates:"},{"line_number":514,"context_line":"            self.async_update("}],"source_content_type":"text/x-python","patch_set":6,"id":"40f26dfd_f2c8c964","line":511,"in_reply_to":"1fe0b3e0_e348fb44","updated":"2024-06-24 15:45:31.000000000","message":"Acknowledged","commit_id":"c503d937bdf0898e739f4febf2b5f416d3af87e9"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"9e1341653645bc630e2746759431a3fd177b5398","unresolved":true,"context_lines":[{"line_number":489,"context_line":"                else:"},{"line_number":490,"context_line":"                    # Inconsistent configuration may lead to orphaned expirer"},{"line_number":491,"context_line":"                    # task queue objects when X-Delete-At is updated, which can"},{"line_number":492,"context_line":"                    # stick around for a whole reclaim age."},{"line_number":493,"context_line":"                    self.logger.debug("},{"line_number":494,"context_line":"                        \u0027Proxy X-Delete-At-Container %r does not match \u0027"},{"line_number":495,"context_line":"                        \u0027expected %r for current expirer_config.\u0027,"}],"source_content_type":"text/x-python","patch_set":10,"id":"334bc589_8fb6373c","line":492,"updated":"2024-07-18 16:52:31.000000000","message":"let me see if I get this: an update would go to a different container than the original, so the original would be tried but fail, until reclaimed?","commit_id":"6fe94c3c0074b7e4d74d7cf23a198b869e816ce7"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"3c753577924d66ca4dbe4fe8e6634ada827d5d1b","unresolved":false,"context_lines":[{"line_number":489,"context_line":"                else:"},{"line_number":490,"context_line":"                    # Inconsistent configuration may lead to orphaned expirer"},{"line_number":491,"context_line":"                    # task queue objects when X-Delete-At is updated, which can"},{"line_number":492,"context_line":"                    # stick around for a whole reclaim age."},{"line_number":493,"context_line":"                    self.logger.debug("},{"line_number":494,"context_line":"                        \u0027Proxy X-Delete-At-Container %r does not match \u0027"},{"line_number":495,"context_line":"                        \u0027expected %r for current expirer_config.\u0027,"}],"source_content_type":"text/x-python","patch_set":10,"id":"b10fcd1c_3b1782a9","line":492,"in_reply_to":"334bc589_8fb6373c","updated":"2024-07-31 15:51:16.000000000","message":"that sounds like it matches my understanding.","commit_id":"6fe94c3c0074b7e4d74d7cf23a198b869e816ce7"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"9e1341653645bc630e2746759431a3fd177b5398","unresolved":true,"context_lines":[{"line_number":497,"context_line":"                # it\u0027s not possible to say which is \"more correct\", this will"},{"line_number":498,"context_line":"                # at least match the host/part/device"},{"line_number":499,"context_line":"                delete_at_container \u003d normalize_delete_at_timestamp("},{"line_number":500,"context_line":"                    proxy_delete_at_container)"},{"line_number":501,"context_line":""},{"line_number":502,"context_line":"            # new updates need to enqueue new x-delete-at"},{"line_number":503,"context_line":"            partition \u003d headers_in.get(\u0027X-Delete-At-Partition\u0027, None)"}],"source_content_type":"text/x-python","patch_set":10,"id":"fcb2d234_3744b7c9","line":500,"updated":"2024-07-18 16:52:31.000000000","message":"hmmm, should we normalize ``proxy_delete_at_container`` before comparing with the already normalized ``delete_at_container``?\n\nI guess we expect the poxy to send us a normalized timestamp, and its only a debug log if it doesn\u0027t match but would match if it was normlaized, so probably OK as it is here. And we should normalize somewhere just in case!","commit_id":"6fe94c3c0074b7e4d74d7cf23a198b869e816ce7"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"3c753577924d66ca4dbe4fe8e6634ada827d5d1b","unresolved":false,"context_lines":[{"line_number":497,"context_line":"                # it\u0027s not possible to say which is \"more correct\", this will"},{"line_number":498,"context_line":"                # at least match the host/part/device"},{"line_number":499,"context_line":"                delete_at_container \u003d normalize_delete_at_timestamp("},{"line_number":500,"context_line":"                    proxy_delete_at_container)"},{"line_number":501,"context_line":""},{"line_number":502,"context_line":"            # new updates need to enqueue new x-delete-at"},{"line_number":503,"context_line":"            partition \u003d headers_in.get(\u0027X-Delete-At-Partition\u0027, None)"}],"source_content_type":"text/x-python","patch_set":10,"id":"7a76bd80_24526ae7","line":500,"in_reply_to":"fcb2d234_3744b7c9","updated":"2024-07-31 15:51:16.000000000","message":"right, the debug message would be indicating `123457 !\u003d 123457.0` and I\u0027d say that\u0027s technically a proxy bug and worth logging for developers.  In the happy path when the match because they\u0027re supposed to we get normalized values we get to skip a little string matching. SoL!\n\nGoes a little in the face of \"liberal in what you accept\" but the storage servers have historically been pretty particular about the formats proxy\u0027s send because we don\u0027t want to paper over bugs (with the obvious special-case exception of liberally excepting old proxy versions)","commit_id":"6fe94c3c0074b7e4d74d7cf23a198b869e816ce7"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"5b95077b5d52024580ecaada3582383bf9970fbc","unresolved":true,"context_lines":[{"line_number":494,"context_line":"                else:"},{"line_number":495,"context_line":"                    # Inconsistent configuration may lead to orphaned expirer"},{"line_number":496,"context_line":"                    # task queue objects when X-Delete-At is updated, which can"},{"line_number":497,"context_line":"                    # stick around for a whole reclaim age."},{"line_number":498,"context_line":"                    self.logger.debug("},{"line_number":499,"context_line":"                        \u0027Proxy X-Delete-At-Container %r does not match \u0027"},{"line_number":500,"context_line":"                        \u0027expected %r for current expirer_config.\u0027,"}],"source_content_type":"text/x-python","patch_set":35,"id":"1a25cd8b_934eb43e","line":497,"updated":"2025-02-07 16:37:06.000000000","message":"I am going to modify this comment with the follow-up patch which would have expirer delete those stale delete tasks with object server returned 409 responses.","commit_id":"287fa42ab8ff101a8ab59aebd44f25028d096c1b"}],"swift/proxy/controllers/obj.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"6fa418271671f06f1a35aca6b0e4e7ad430aed17","unresolved":true,"context_lines":[{"line_number":636,"context_line":"                \u0027x-delete-at:%s\u0027 % x_delete_at)"},{"line_number":637,"context_line":""},{"line_number":638,"context_line":"            delete_at_part, delete_at_nodes, delete_at_container \u003d \\"},{"line_number":639,"context_line":"                expirer.get_delete_at_nodes(self.app.container_ring,"},{"line_number":640,"context_line":"                                            x_delete_at,"},{"line_number":641,"context_line":"                                            self.account_name,"},{"line_number":642,"context_line":"                                            self.container_name,"}],"source_content_type":"text/x-python","patch_set":5,"id":"474db8f0_3e62f038","line":639,"updated":"2024-06-14 01:27:04.000000000","message":"better as `get_delete_at_part_nodes_and_container`???\n\nI guess I was thinking the ring\u0027s `get_nodes` method returns a tuple of `(part, nodes)` and the expirer `get_nodes` method returns a tuple of `(part, nodes, expirer_container)` - it\u0027s got a docstring!","commit_id":"c6e36d1e962e8eba623bdb086b5522e40368339e"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"b8c63f308be42cefb0ecd26273eb849c03d956d7","unresolved":true,"context_lines":[{"line_number":636,"context_line":"                \u0027x-delete-at:%s\u0027 % x_delete_at)"},{"line_number":637,"context_line":""},{"line_number":638,"context_line":"            delete_at_part, delete_at_nodes, delete_at_container \u003d \\"},{"line_number":639,"context_line":"                expirer.get_delete_at_nodes(self.app.container_ring,"},{"line_number":640,"context_line":"                                            x_delete_at,"},{"line_number":641,"context_line":"                                            self.account_name,"},{"line_number":642,"context_line":"                                            self.container_name,"}],"source_content_type":"text/x-python","patch_set":5,"id":"6d42a4bb_b65c1eae","line":639,"in_reply_to":"474db8f0_3e62f038","updated":"2024-06-19 16:31:59.000000000","message":"get_delete_at_target?? \n\n``BaseObjectController._get_update_target`` returns (part, nodes, container)\n\nI\u0027m not so convinced that get_delete_at_nodes is necessarily adding much value vs: \n\n```\n    account_name, task_container \u003d get_expirer_account_and_container(\n        x_delete_at, acc, cont, obj, expirer_config)\n    delete_at_part, delete_at_nodes \u003d container_ring.get_nodes(account_name, task_container)\n```","commit_id":"c6e36d1e962e8eba623bdb086b5522e40368339e"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"741dbae4879c5c177c949a7a4758c964f0674311","unresolved":false,"context_lines":[{"line_number":636,"context_line":"                \u0027x-delete-at:%s\u0027 % x_delete_at)"},{"line_number":637,"context_line":""},{"line_number":638,"context_line":"            delete_at_part, delete_at_nodes, delete_at_container \u003d \\"},{"line_number":639,"context_line":"                expirer.get_delete_at_nodes(self.app.container_ring,"},{"line_number":640,"context_line":"                                            x_delete_at,"},{"line_number":641,"context_line":"                                            self.account_name,"},{"line_number":642,"context_line":"                                            self.container_name,"}],"source_content_type":"text/x-python","patch_set":5,"id":"dd7ba4a2_0a168eb6","line":639,"in_reply_to":"6adba66f_631bc1fa","updated":"2024-07-10 00:02:17.000000000","message":"this is now a method and the container_ring is passed in from the proxy when creating the ExpirerConfig object, the method is still `get_delete_at_nodes` and returns `(part, nodes, task_container_name)` as documented.","commit_id":"c6e36d1e962e8eba623bdb086b5522e40368339e"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"deb7b0fb11e435af1a79694882c472f73219e440","unresolved":true,"context_lines":[{"line_number":636,"context_line":"                \u0027x-delete-at:%s\u0027 % x_delete_at)"},{"line_number":637,"context_line":""},{"line_number":638,"context_line":"            delete_at_part, delete_at_nodes, delete_at_container \u003d \\"},{"line_number":639,"context_line":"                expirer.get_delete_at_nodes(self.app.container_ring,"},{"line_number":640,"context_line":"                                            x_delete_at,"},{"line_number":641,"context_line":"                                            self.account_name,"},{"line_number":642,"context_line":"                                            self.container_name,"}],"source_content_type":"text/x-python","patch_set":5,"id":"6adba66f_631bc1fa","line":639,"in_reply_to":"6d42a4bb_b65c1eae","updated":"2024-06-24 15:45:31.000000000","message":"I think I avoided \"target\" because sometimes when dealing with expiring objects we call the *target* object (the one being reaped) the \"delete_at_target\"\n\nI do like having the helper; I\u0027m trying to hide the hadling of the expiring_object_account_name from the caller as much as possible.","commit_id":"c6e36d1e962e8eba623bdb086b5522e40368339e"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"b8c63f308be42cefb0ecd26273eb849c03d956d7","unresolved":true,"context_lines":[{"line_number":625,"context_line":"        delete_at_part \u003d None"},{"line_number":626,"context_line":"        delete_at_nodes \u003d None"},{"line_number":627,"context_line":""},{"line_number":628,"context_line":"        req \u003d constraints.check_delete_headers(req)"},{"line_number":629,"context_line":""},{"line_number":630,"context_line":"        if \u0027x-delete-at\u0027 in req.headers:"},{"line_number":631,"context_line":"            req.headers[\u0027x-delete-at\u0027] \u003d normalize_delete_at_timestamp("}],"source_content_type":"text/x-python","patch_set":6,"id":"78325a6d_6edffe66","line":628,"updated":"2024-06-19 16:31:59.000000000","message":"off-topic: odd that this method returns ``req`` when in fact it is the same ``req`` that was passed in","commit_id":"c503d937bdf0898e739f4febf2b5f416d3af87e9"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"deb7b0fb11e435af1a79694882c472f73219e440","unresolved":false,"context_lines":[{"line_number":625,"context_line":"        delete_at_part \u003d None"},{"line_number":626,"context_line":"        delete_at_nodes \u003d None"},{"line_number":627,"context_line":""},{"line_number":628,"context_line":"        req \u003d constraints.check_delete_headers(req)"},{"line_number":629,"context_line":""},{"line_number":630,"context_line":"        if \u0027x-delete-at\u0027 in req.headers:"},{"line_number":631,"context_line":"            req.headers[\u0027x-delete-at\u0027] \u003d normalize_delete_at_timestamp("}],"source_content_type":"text/x-python","patch_set":6,"id":"166185c6_8048c4ec","line":628,"in_reply_to":"78325a6d_6edffe66","updated":"2024-06-24 15:45:31.000000000","message":"Acknowledged","commit_id":"c503d937bdf0898e739f4febf2b5f416d3af87e9"}],"test/unit/common/middleware/test_slo.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"03ea67ba85dbb56847f83b66a0ac20f8bfe931d8","unresolved":true,"context_lines":[{"line_number":1816,"context_line":"        }"},{"line_number":1817,"context_line":"        self.slo \u003d slo.filter_factory(slo_conf)(self.app)"},{"line_number":1818,"context_line":"        self.app.register("},{"line_number":1819,"context_line":"            \u0027UPDATE\u0027, \u0027/v1/.exp/1716902792\u0027,"},{"line_number":1820,"context_line":"            swob.HTTPNoContent, {}, None)"},{"line_number":1821,"context_line":"        req \u003d Request.blank("},{"line_number":1822,"context_line":"            \u0027/v1/AUTH_test/deltest/man-all-there\u0027,"}],"source_content_type":"text/x-python","patch_set":2,"id":"317a744d_9f046c92","line":1819,"updated":"2024-05-29 13:42:34.000000000","message":"LOL?  why did I think i could hard code this one?","commit_id":"45c067912d6b37cbeb41caaaf33cf5e664b5b939"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"d959d5a9bd1de78dcfa8765aa0e309875bbe8b94","unresolved":false,"context_lines":[{"line_number":1816,"context_line":"        }"},{"line_number":1817,"context_line":"        self.slo \u003d slo.filter_factory(slo_conf)(self.app)"},{"line_number":1818,"context_line":"        self.app.register("},{"line_number":1819,"context_line":"            \u0027UPDATE\u0027, \u0027/v1/.exp/1716902792\u0027,"},{"line_number":1820,"context_line":"            swob.HTTPNoContent, {}, None)"},{"line_number":1821,"context_line":"        req \u003d Request.blank("},{"line_number":1822,"context_line":"            \u0027/v1/AUTH_test/deltest/man-all-there\u0027,"}],"source_content_type":"text/x-python","patch_set":2,"id":"b7b294a0_af48e844","line":1819,"in_reply_to":"317a744d_9f046c92","updated":"2024-06-04 16:30:40.000000000","message":"Done","commit_id":"45c067912d6b37cbeb41caaaf33cf5e664b5b939"}],"test/unit/obj/test_expirer.py":[{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"8bc79c22db28289c7ef0aa424316b73e359c3cb2","unresolved":false,"context_lines":[{"line_number":113,"context_line":"                                                  expirer_divisor\u003d200)"},{"line_number":114,"context_line":"        self.assertEqual(container, \u00270000001199\u0027)"},{"line_number":115,"context_line":""},{"line_number":116,"context_line":"    def test_get_expirer_container_legacy_config(self):"},{"line_number":117,"context_line":"        per_divisor \u003d 10"},{"line_number":118,"context_line":"        config \u003d {"},{"line_number":119,"context_line":"            \u0027expirer_divisor\u0027: 86400 * 2,"}],"source_content_type":"text/x-python","patch_set":5,"id":"19123274_8badca3b","line":116,"updated":"2024-06-04 21:26:14.000000000","message":"nice! here is test to cover the legacy config.","commit_id":"c6e36d1e962e8eba623bdb086b5522e40368339e"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"6fa418271671f06f1a35aca6b0e4e7ad430aed17","unresolved":true,"context_lines":[{"line_number":1323,"context_line":"        self.assertEqual(lines, ["},{"line_number":1324,"context_line":"            \u0027processing 2 unexpected task containers (e.g. 86300 86401) \u0027"},{"line_number":1325,"context_line":"            \u0027if you have recently changed your expirer config \u0027"},{"line_number":1326,"context_line":"            \u0027this message should go away in a few days.\u0027"},{"line_number":1327,"context_line":"        ])"},{"line_number":1328,"context_line":""},{"line_number":1329,"context_line":"    def test_run_once_with_invalid_container(self):"}],"source_content_type":"text/x-python","patch_set":5,"id":"9d24788a_6916f432","line":1326,"updated":"2024-06-14 01:27:04.000000000","message":"or it might continue for years if you\u0027ve *decreased* the per_day value...","commit_id":"c6e36d1e962e8eba623bdb086b5522e40368339e"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"c02205ac2d10423d7033e84dfc99ef779c6c882d","unresolved":false,"context_lines":[{"line_number":1323,"context_line":"        self.assertEqual(lines, ["},{"line_number":1324,"context_line":"            \u0027processing 2 unexpected task containers (e.g. 86300 86401) \u0027"},{"line_number":1325,"context_line":"            \u0027if you have recently changed your expirer config \u0027"},{"line_number":1326,"context_line":"            \u0027this message should go away in a few days.\u0027"},{"line_number":1327,"context_line":"        ])"},{"line_number":1328,"context_line":""},{"line_number":1329,"context_line":"    def test_run_once_with_invalid_container(self):"}],"source_content_type":"text/x-python","patch_set":5,"id":"31c71793_8da8717f","line":1326,"in_reply_to":"045e298e_44395a1c","updated":"2024-10-28 12:41:32.000000000","message":"Done","commit_id":"c6e36d1e962e8eba623bdb086b5522e40368339e"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"3c753577924d66ca4dbe4fe8e6634ada827d5d1b","unresolved":true,"context_lines":[{"line_number":1323,"context_line":"        self.assertEqual(lines, ["},{"line_number":1324,"context_line":"            \u0027processing 2 unexpected task containers (e.g. 86300 86401) \u0027"},{"line_number":1325,"context_line":"            \u0027if you have recently changed your expirer config \u0027"},{"line_number":1326,"context_line":"            \u0027this message should go away in a few days.\u0027"},{"line_number":1327,"context_line":"        ])"},{"line_number":1328,"context_line":""},{"line_number":1329,"context_line":"    def test_run_once_with_invalid_container(self):"}],"source_content_type":"text/x-python","patch_set":5,"id":"045e298e_44395a1c","line":1326,"in_reply_to":"18dc94ce_191bcc5f","updated":"2024-07-31 15:51:16.000000000","message":"I think because every new day there\u0027s a chance we find a *old* container; created with the *old* config for some *future* date and info again: hey I still don\u0027t consider these legacy records \"expected\" 😞\n\nWe should figure out the right verbosity here before we merge.","commit_id":"c6e36d1e962e8eba623bdb086b5522e40368339e"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"9e1341653645bc630e2746759431a3fd177b5398","unresolved":true,"context_lines":[{"line_number":1323,"context_line":"        self.assertEqual(lines, ["},{"line_number":1324,"context_line":"            \u0027processing 2 unexpected task containers (e.g. 86300 86401) \u0027"},{"line_number":1325,"context_line":"            \u0027if you have recently changed your expirer config \u0027"},{"line_number":1326,"context_line":"            \u0027this message should go away in a few days.\u0027"},{"line_number":1327,"context_line":"        ])"},{"line_number":1328,"context_line":""},{"line_number":1329,"context_line":"    def test_run_once_with_invalid_container(self):"}],"source_content_type":"text/x-python","patch_set":5,"id":"18dc94ce_191bcc5f","line":1326,"in_reply_to":"9d24788a_6916f432","updated":"2024-07-18 16:52:31.000000000","message":"help me understand...we still process unexpected containers, so why would they not eventually go away within a cycle or so?","commit_id":"c6e36d1e962e8eba623bdb086b5522e40368339e"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"8bc79c22db28289c7ef0aa424316b73e359c3cb2","unresolved":false,"context_lines":[{"line_number":1365,"context_line":"            ])"},{"line_number":1366,"context_line":"        self._expirer_run_once_with_mocks(now\u003dnow)"},{"line_number":1367,"context_line":"        # we processed all tasks in all valid containers"},{"line_number":1368,"context_line":"        self.assertEqual(task_per_container * 2, self.expirer.report_objects)"},{"line_number":1369,"context_line":""},{"line_number":1370,"context_line":"    def test_iter_task_to_expire(self):"},{"line_number":1371,"context_line":"        # In this test, all tasks are assigned to the tested expirer"}],"source_content_type":"text/x-python","patch_set":5,"id":"f8312f29_79024c1d","line":1368,"updated":"2024-06-04 21:26:14.000000000","message":"okay, the delete tasks in invalid container are skipped.","commit_id":"c6e36d1e962e8eba623bdb086b5522e40368339e"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"9e1341653645bc630e2746759431a3fd177b5398","unresolved":true,"context_lines":[{"line_number":105,"context_line":"        return swob.HTTPNoContent()"},{"line_number":106,"context_line":""},{"line_number":107,"context_line":""},{"line_number":108,"context_line":"class TestGetExpirerContainer(TestCase):"},{"line_number":109,"context_line":""},{"line_number":110,"context_line":"    @mock.patch(\u0027swift.obj.expirer.utils.hash_path\u0027, return_value\u003dhex(101)[2:])"},{"line_number":111,"context_line":"    def test_get_expirer_container(self, mock_hash_path):"}],"source_content_type":"text/x-python","patch_set":10,"id":"17dcfb96_a8636cb0","line":108,"updated":"2024-07-18 16:52:31.000000000","message":"probably better named TestExpirerConfig","commit_id":"6fe94c3c0074b7e4d74d7cf23a198b869e816ce7"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"296beca32dc11b900b395aa306e293bbda879e69","unresolved":false,"context_lines":[{"line_number":105,"context_line":"        return swob.HTTPNoContent()"},{"line_number":106,"context_line":""},{"line_number":107,"context_line":""},{"line_number":108,"context_line":"class TestGetExpirerContainer(TestCase):"},{"line_number":109,"context_line":""},{"line_number":110,"context_line":"    @mock.patch(\u0027swift.obj.expirer.utils.hash_path\u0027, return_value\u003dhex(101)[2:])"},{"line_number":111,"context_line":"    def test_get_expirer_container(self, mock_hash_path):"}],"source_content_type":"text/x-python","patch_set":10,"id":"41cf3015_32d01f61","line":108,"in_reply_to":"17dcfb96_a8636cb0","updated":"2024-07-19 14:05:59.000000000","message":"Done","commit_id":"6fe94c3c0074b7e4d74d7cf23a198b869e816ce7"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"9e1341653645bc630e2746759431a3fd177b5398","unresolved":true,"context_lines":[{"line_number":120,"context_line":"            1234, \u0027a\u0027, \u0027c\u0027, \u0027o\u0027)"},{"line_number":121,"context_line":"        self.assertEqual(container, \u00270000001199\u0027)"},{"line_number":122,"context_line":""},{"line_number":123,"context_line":"    def test_get_expirer_container_legacy_config(self):"},{"line_number":124,"context_line":"        per_divisor \u003d 10"},{"line_number":125,"context_line":"        expirer_config \u003d ExpirerConfig({"},{"line_number":126,"context_line":"            \u0027expiring_objects_container_divisor\u0027: 86400 * 2,"}],"source_content_type":"text/x-python","patch_set":10,"id":"e8ddac2c_288169d8","line":123,"updated":"2024-07-18 16:52:31.000000000","message":"this test is similar to test_task_container_per_day_config except it sets ``\u0027expiring_objects_container_divisor\u0027`` to a non-default value but doesn\u0027t assert it\n\nSetting \u0027expiring_objects_container_divisor\u0027 is covered in test_get_expirer_config_legacy\n\nSetting ``expiring_objects_task_container_per_day`` is covered in test_get_expirer_config and test_task_container_per_day_config\n\nJust wondering if this test adds anything? I guess some weird interaction between the two??","commit_id":"6fe94c3c0074b7e4d74d7cf23a198b869e816ce7"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"3c753577924d66ca4dbe4fe8e6634ada827d5d1b","unresolved":false,"context_lines":[{"line_number":120,"context_line":"            1234, \u0027a\u0027, \u0027c\u0027, \u0027o\u0027)"},{"line_number":121,"context_line":"        self.assertEqual(container, \u00270000001199\u0027)"},{"line_number":122,"context_line":""},{"line_number":123,"context_line":"    def test_get_expirer_container_legacy_config(self):"},{"line_number":124,"context_line":"        per_divisor \u003d 10"},{"line_number":125,"context_line":"        expirer_config \u003d ExpirerConfig({"},{"line_number":126,"context_line":"            \u0027expiring_objects_container_divisor\u0027: 86400 * 2,"}],"source_content_type":"text/x-python","patch_set":10,"id":"72b37108_989cea76","line":123,"in_reply_to":"e8ddac2c_288169d8","updated":"2024-07-31 15:51:16.000000000","message":"yeah, i think it\u0027s trying to show that even with non-default divsor you get \"per_day\" \u003d\u003d \"found per_divisor\" not ... \"per day\"\n\ndefinately a wonky interaction for \"test_legacy_config\" - I agree it\u0027s providing marginal value in terms of *coverage* beyond confirming this \"per_day\" config is sort of mis-named for it\u0027s *behavior* but given we\u0027re deprecating \"divisor\" as configurable we named it how it\u0027s *used* not what it *does*.\n\nIf it\u0027s not obvious what it\u0027s trying to demonstrate even to reviewers of this patch I suppose it\u0027s unlikely to be helpful to some future observer trying to understand \"WTF did we do here\"!?\n\nMy judgement would be to leave it cause it\u0027s already written and probably won\u0027t *hurt* anything even it\u0027s close to zero value.  But I may only be able to understand it cause I think I wrote it?  If it\u0027s actively confusing others we should definately remove it.","commit_id":"6fe94c3c0074b7e4d74d7cf23a198b869e816ce7"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"ed2cb843f69c57e0cb32cf6ce4b2a7d8403bf05d","unresolved":true,"context_lines":[{"line_number":356,"context_line":"        # the actual target a/c/o used only matters for consistent"},{"line_number":357,"context_line":"        # distribution, tests typically only create one task container per-day,"},{"line_number":358,"context_line":"        # but we want the task container names to be realistic"},{"line_number":359,"context_line":"        return self.expirer_config.get_expirer_container("},{"line_number":360,"context_line":"            delete_at, target_account, target_container, target_object)"},{"line_number":361,"context_line":""},{"line_number":362,"context_line":"    def setUp(self):"}],"source_content_type":"text/x-python","patch_set":27,"id":"b9c2f878_32b0e6a7","line":359,"updated":"2024-11-01 21:39:57.000000000","message":"I suppose this could use `getattr(self, \u0027expirer_config\u0027)` if it we wanted to get rid of the dummy `self.expirer_config` in `setUp` until we get our real one off the expirer in `_setup_fake_swift`","commit_id":"538c82e0fb554328d8ce72e513c583db2c20045a"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"d0f98cfd362e46a234f338320f8ee19044d5e31d","unresolved":false,"context_lines":[{"line_number":356,"context_line":"        # the actual target a/c/o used only matters for consistent"},{"line_number":357,"context_line":"        # distribution, tests typically only create one task container per-day,"},{"line_number":358,"context_line":"        # but we want the task container names to be realistic"},{"line_number":359,"context_line":"        return self.expirer_config.get_expirer_container("},{"line_number":360,"context_line":"            delete_at, target_account, target_container, target_object)"},{"line_number":361,"context_line":""},{"line_number":362,"context_line":"    def setUp(self):"}],"source_content_type":"text/x-python","patch_set":27,"id":"9f38c4b4_3bd95e7d","line":359,"in_reply_to":"b9c2f878_32b0e6a7","updated":"2024-11-05 00:21:48.000000000","message":"Done","commit_id":"538c82e0fb554328d8ce72e513c583db2c20045a"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"ed2cb843f69c57e0cb32cf6ce4b2a7d8403bf05d","unresolved":true,"context_lines":[{"line_number":375,"context_line":"        self.now \u003d now \u003d int(time())"},{"line_number":376,"context_line":""},{"line_number":377,"context_line":"        self.empty_time \u003d str(now - 864000)"},{"line_number":378,"context_line":"        self.expirer_config \u003d ExpirerConfig(self.conf)"},{"line_number":379,"context_line":"        self.empty_time_container \u003d self.get_expirer_container("},{"line_number":380,"context_line":"            self.empty_time)"},{"line_number":381,"context_line":"        self.past_time \u003d str(now - 86400)"}],"source_content_type":"text/x-python","patch_set":27,"id":"7618dd80_7e6e7eca","line":378,"updated":"2024-11-01 21:39:57.000000000","message":"well this still probably deserves a logger even if we do replace it in `_setup_fake_swift`","commit_id":"538c82e0fb554328d8ce72e513c583db2c20045a"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"d0f98cfd362e46a234f338320f8ee19044d5e31d","unresolved":false,"context_lines":[{"line_number":375,"context_line":"        self.now \u003d now \u003d int(time())"},{"line_number":376,"context_line":""},{"line_number":377,"context_line":"        self.empty_time \u003d str(now - 864000)"},{"line_number":378,"context_line":"        self.expirer_config \u003d ExpirerConfig(self.conf)"},{"line_number":379,"context_line":"        self.empty_time_container \u003d self.get_expirer_container("},{"line_number":380,"context_line":"            self.empty_time)"},{"line_number":381,"context_line":"        self.past_time \u003d str(now - 86400)"}],"source_content_type":"text/x-python","patch_set":27,"id":"5d452a7c_457a03d8","line":378,"in_reply_to":"7618dd80_7e6e7eca","updated":"2024-11-05 00:21:48.000000000","message":"Done","commit_id":"538c82e0fb554328d8ce72e513c583db2c20045a"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"ed2cb843f69c57e0cb32cf6ce4b2a7d8403bf05d","unresolved":true,"context_lines":[{"line_number":2026,"context_line":"                mock.patch(\u0027swift.common.utils.timestamp.time.time\u0027,"},{"line_number":2027,"context_line":"                           memory_efficient_time), \\"},{"line_number":2028,"context_line":"                mock.patch(\u0027swift.obj.expirer.time\u0027, memory_efficient_time):"},{"line_number":2029,"context_line":"            self.expirer.run_once()"},{"line_number":2030,"context_line":""},{"line_number":2031,"context_line":"    def test_run_once_unicode_problem(self):"},{"line_number":2032,"context_line":"        requests \u003d []"}],"source_content_type":"text/x-python","patch_set":27,"id":"670fad64_91001890","line":2029,"updated":"2024-11-01 21:39:57.000000000","message":"in this patch this is only used in a new test `test_run_once_with_invalid_container` - we could probably move the definition up above that.","commit_id":"538c82e0fb554328d8ce72e513c583db2c20045a"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"d0f98cfd362e46a234f338320f8ee19044d5e31d","unresolved":false,"context_lines":[{"line_number":2026,"context_line":"                mock.patch(\u0027swift.common.utils.timestamp.time.time\u0027,"},{"line_number":2027,"context_line":"                           memory_efficient_time), \\"},{"line_number":2028,"context_line":"                mock.patch(\u0027swift.obj.expirer.time\u0027, memory_efficient_time):"},{"line_number":2029,"context_line":"            self.expirer.run_once()"},{"line_number":2030,"context_line":""},{"line_number":2031,"context_line":"    def test_run_once_unicode_problem(self):"},{"line_number":2032,"context_line":"        requests \u003d []"}],"source_content_type":"text/x-python","patch_set":27,"id":"9698af81_14f7188d","line":2029,"in_reply_to":"670fad64_91001890","updated":"2024-11-05 00:21:48.000000000","message":"Done","commit_id":"538c82e0fb554328d8ce72e513c583db2c20045a"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"e707e3dcdb5f7a43ad3027ebcc729e8b7baf3f4d","unresolved":true,"context_lines":[{"line_number":357,"context_line":"        # distribution, tests typically only create one task container per-day,"},{"line_number":358,"context_line":"        # but we want the task container names to be realistic"},{"line_number":359,"context_line":"        expirer_config \u003d getattr(self, \u0027expirer_config\u0027,"},{"line_number":360,"context_line":"                                 ExpirerConfig(self.conf, self.logger))"},{"line_number":361,"context_line":"        return expirer_config.get_expirer_container("},{"line_number":362,"context_line":"            delete_at, target_account, target_container, target_object)"},{"line_number":363,"context_line":""}],"source_content_type":"text/x-python","patch_set":29,"id":"6a041cc2_3e1d2a3b","line":360,"updated":"2024-11-05 10:10:19.000000000","message":"hmm, the dependency ordering is unfortunate (we need an ExpirerConfig to calculate the contaniers that are used to construct the fake swift that is passed to the expirer which will then construct an ExpirerConfig), but this at least avoids the potentially confusing \n\n```\nself.expirer_config \u003d ExpirerConfig(self.conf)\n```\n in ``setUp`` which is in fact only transient.\n \nnit:\nI don\u0027t think there\u0027s anywhere else that accesses ``self.expirer_config``, so we could just write:\n\n```\nexpirer \u003d getattr(self, \u0027expirer\u0027, None)\nexpirer_config \u003d expirer.expirer_config if expirer or ExpirerConfig(self.conf, self.logger))\n```\n\nwhich avoids the need for a ``self.expirer_config`` and the suggestion that it might ever be something other than ``self.expirer.expirer_config``","commit_id":"a39f35f4b20d7e66639172aa46ccb0d94bf613d9"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"8770fff8b26a1de2cad0405e65c8e4c9e05ed324","unresolved":false,"context_lines":[{"line_number":357,"context_line":"        # distribution, tests typically only create one task container per-day,"},{"line_number":358,"context_line":"        # but we want the task container names to be realistic"},{"line_number":359,"context_line":"        expirer_config \u003d getattr(self, \u0027expirer_config\u0027,"},{"line_number":360,"context_line":"                                 ExpirerConfig(self.conf, self.logger))"},{"line_number":361,"context_line":"        return expirer_config.get_expirer_container("},{"line_number":362,"context_line":"            delete_at, target_account, target_container, target_object)"},{"line_number":363,"context_line":""}],"source_content_type":"text/x-python","patch_set":29,"id":"fbc9d8c0_30245a4d","line":360,"in_reply_to":"6a041cc2_3e1d2a3b","updated":"2024-11-18 19:06:00.000000000","message":"Done","commit_id":"a39f35f4b20d7e66639172aa46ccb0d94bf613d9"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"e707e3dcdb5f7a43ad3027ebcc729e8b7baf3f4d","unresolved":true,"context_lines":[{"line_number":1289,"context_line":"        ])"},{"line_number":1290,"context_line":""},{"line_number":1291,"context_line":"    def _expirer_run_once_with_mocks("},{"line_number":1292,"context_line":"            self, now\u003dNone, stub_pop_queue\u003dNone):"},{"line_number":1293,"context_line":"        \"\"\""},{"line_number":1294,"context_line":"        call self.expirer.run_once() with some things (optionally) stubbed out"},{"line_number":1295,"context_line":"        \"\"\""}],"source_content_type":"text/x-python","patch_set":29,"id":"a552bc56_a6433853","line":1292,"updated":"2024-11-05 10:10:19.000000000","message":"nit: no need for the line wrap","commit_id":"a39f35f4b20d7e66639172aa46ccb0d94bf613d9"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"8770fff8b26a1de2cad0405e65c8e4c9e05ed324","unresolved":false,"context_lines":[{"line_number":1289,"context_line":"        ])"},{"line_number":1290,"context_line":""},{"line_number":1291,"context_line":"    def _expirer_run_once_with_mocks("},{"line_number":1292,"context_line":"            self, now\u003dNone, stub_pop_queue\u003dNone):"},{"line_number":1293,"context_line":"        \"\"\""},{"line_number":1294,"context_line":"        call self.expirer.run_once() with some things (optionally) stubbed out"},{"line_number":1295,"context_line":"        \"\"\""}],"source_content_type":"text/x-python","patch_set":29,"id":"c5d8d273_c2d80200","line":1292,"in_reply_to":"a552bc56_a6433853","updated":"2024-11-18 19:06:00.000000000","message":"Done","commit_id":"a39f35f4b20d7e66639172aa46ccb0d94bf613d9"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"e1ecf17f20a86415a2e69cb1ba17ae654ea7dbe8","unresolved":true,"context_lines":[{"line_number":211,"context_line":"            delete_at, \u0027a\u0027, \u0027c\u0027, \u0027o\u0027)"},{"line_number":212,"context_line":"        self.assertEqual(\u0027.exp\u0027, account)"},{"line_number":213,"context_line":"        self.assertTrue(expirer_config.is_expected_task_container("},{"line_number":214,"context_line":"            int(container)))"},{"line_number":215,"context_line":""},{"line_number":216,"context_line":"    def test_get_delete_at_nodes(self):"},{"line_number":217,"context_line":"        container_ring \u003d FakeRing()"}],"source_content_type":"text/x-python","patch_set":34,"id":"2cdf6918_828422a4","line":214,"updated":"2025-01-03 22:15:04.000000000","message":"This would be so much better with\n```\ndiff --git a/test/unit/obj/test_expirer.py b/test/unit/obj/test_expirer.py\nindex e9a6140fd4..186ed880f0 100644\n--- a/test/unit/obj/test_expirer.py\n+++ b/test/unit/obj/test_expirer.py\n@@ -212,6 +212,10 @@ class TestExpirerConfig(TestCase):\n         self.assertEqual(\u0027.exp\u0027, account)\n         self.assertTrue(expirer_config.is_expected_task_container(\n             int(container)))\n+        self.assertTrue(expirer_config.is_expected_task_container(2000))\n+        self.assertTrue(expirer_config.is_expected_task_container(1999))\n+        self.assertTrue(expirer_config.is_expected_task_container(1901))\n+        self.assertFalse(expirer_config.is_expected_task_container(1900))\n+        self.assertFalse(expirer_config.is_expected_task_container(1001))\n+        self.assertTrue(expirer_config.is_expected_task_container(1000))\n \n     def test_get_delete_at_nodes(self):\n         container_ring \u003d FakeRing()\n```\n(and even more so if that *passed*.)","commit_id":"c7988c0a6830ea7fa2d9b14a5eb92a03f6f8e709"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"5b95077b5d52024580ecaada3582383bf9970fbc","unresolved":false,"context_lines":[{"line_number":211,"context_line":"            delete_at, \u0027a\u0027, \u0027c\u0027, \u0027o\u0027)"},{"line_number":212,"context_line":"        self.assertEqual(\u0027.exp\u0027, account)"},{"line_number":213,"context_line":"        self.assertTrue(expirer_config.is_expected_task_container("},{"line_number":214,"context_line":"            int(container)))"},{"line_number":215,"context_line":""},{"line_number":216,"context_line":"    def test_get_delete_at_nodes(self):"},{"line_number":217,"context_line":"        container_ring \u003d FakeRing()"}],"source_content_type":"text/x-python","patch_set":34,"id":"e1874eb1_cdb017b3","line":214,"in_reply_to":"2cdf6918_828422a4","updated":"2025-02-07 16:37:06.000000000","message":"Done","commit_id":"c7988c0a6830ea7fa2d9b14a5eb92a03f6f8e709"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"e661a73d674cf561ab30863a6abc5747d5478408","unresolved":false,"context_lines":[{"line_number":211,"context_line":"            delete_at, \u0027a\u0027, \u0027c\u0027, \u0027o\u0027)"},{"line_number":212,"context_line":"        self.assertEqual(\u0027.exp\u0027, account)"},{"line_number":213,"context_line":"        self.assertTrue(expirer_config.is_expected_task_container("},{"line_number":214,"context_line":"            int(container)))"},{"line_number":215,"context_line":""},{"line_number":216,"context_line":"    def test_get_delete_at_nodes(self):"},{"line_number":217,"context_line":"        container_ring \u003d FakeRing()"}],"source_content_type":"text/x-python","patch_set":34,"id":"fe2aebcc_842e1d73","line":214,"in_reply_to":"e1874eb1_cdb017b3","updated":"2025-02-07 21:25:30.000000000","message":"OIC -- this test was just using the wrong config option before.","commit_id":"c7988c0a6830ea7fa2d9b14a5eb92a03f6f8e709"}],"test/unit/obj/test_server.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"6fa418271671f06f1a35aca6b0e4e7ad430aed17","unresolved":true,"context_lines":[{"line_number":6783,"context_line":"        self.assertEqual({\u0027debug\u0027: ["},{"line_number":6784,"context_line":"            \"Proxy X-Delete-At-Container \u0027%s\u0027 does not match expected \""},{"line_number":6785,"context_line":"            \"\u0027%s\u0027 for current expirer_config.\" % (unexpected_container,"},{"line_number":6786,"context_line":"                                                  expected_container)"},{"line_number":6787,"context_line":"        ]}, self.logger.all_log_lines())"},{"line_number":6788,"context_line":"        self.assertEqual("},{"line_number":6789,"context_line":"            given_args, ["}],"source_content_type":"text/x-python","patch_set":5,"id":"e53391a7_d06645ee","line":6786,"updated":"2024-06-14 01:27:04.000000000","message":"probably reasonable at debug; maybe problematic if it continues to be inconsistent for long periods of time - oppertunity for a metric?","commit_id":"c6e36d1e962e8eba623bdb086b5522e40368339e"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"741dbae4879c5c177c949a7a4758c964f0674311","unresolved":false,"context_lines":[{"line_number":6783,"context_line":"        self.assertEqual({\u0027debug\u0027: ["},{"line_number":6784,"context_line":"            \"Proxy X-Delete-At-Container \u0027%s\u0027 does not match expected \""},{"line_number":6785,"context_line":"            \"\u0027%s\u0027 for current expirer_config.\" % (unexpected_container,"},{"line_number":6786,"context_line":"                                                  expected_container)"},{"line_number":6787,"context_line":"        ]}, self.logger.all_log_lines())"},{"line_number":6788,"context_line":"        self.assertEqual("},{"line_number":6789,"context_line":"            given_args, ["}],"source_content_type":"text/x-python","patch_set":5,"id":"426477bc_cad40f60","line":6786,"in_reply_to":"e53391a7_d06645ee","updated":"2024-07-10 00:02:17.000000000","message":"it\u0027s not really problematic for the *object-server* - the expirer will emit a new info message about the volume of unexpected containers that may evolve and i believe it has the best hope of helping catch any issues here.","commit_id":"c6e36d1e962e8eba623bdb086b5522e40368339e"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"6fa418271671f06f1a35aca6b0e4e7ad430aed17","unresolved":true,"context_lines":[{"line_number":6787,"context_line":"        ]}, self.logger.all_log_lines())"},{"line_number":6788,"context_line":"        self.assertEqual("},{"line_number":6789,"context_line":"            given_args, ["},{"line_number":6790,"context_line":"                \u0027PUT\u0027, \u0027.expiring_objects\u0027, unexpected_container,"},{"line_number":6791,"context_line":"                \u0027%s-a/c/o\u0027 % delete_at,"},{"line_number":6792,"context_line":"                req_headers[\u0027X-Delete-At-Host\u0027],"},{"line_number":6793,"context_line":"                req_headers[\u0027X-Delete-At-Partition\u0027],"}],"source_content_type":"text/x-python","patch_set":5,"id":"45bff95a_64534bc4","line":6790,"updated":"2024-06-14 01:27:04.000000000","message":"important point is we do what the proxy says; even if it\u0027s \"wrong\" we can hope it\u0027s internally self consistent.","commit_id":"c6e36d1e962e8eba623bdb086b5522e40368339e"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"741dbae4879c5c177c949a7a4758c964f0674311","unresolved":false,"context_lines":[{"line_number":6787,"context_line":"        ]}, self.logger.all_log_lines())"},{"line_number":6788,"context_line":"        self.assertEqual("},{"line_number":6789,"context_line":"            given_args, ["},{"line_number":6790,"context_line":"                \u0027PUT\u0027, \u0027.expiring_objects\u0027, unexpected_container,"},{"line_number":6791,"context_line":"                \u0027%s-a/c/o\u0027 % delete_at,"},{"line_number":6792,"context_line":"                req_headers[\u0027X-Delete-At-Host\u0027],"},{"line_number":6793,"context_line":"                req_headers[\u0027X-Delete-At-Partition\u0027],"}],"source_content_type":"text/x-python","patch_set":5,"id":"3bb758f6_f990b67b","line":6790,"in_reply_to":"45bff95a_64534bc4","updated":"2024-07-10 00:02:17.000000000","message":"Acknowledged","commit_id":"c6e36d1e962e8eba623bdb086b5522e40368339e"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"6fa418271671f06f1a35aca6b0e4e7ad430aed17","unresolved":false,"context_lines":[{"line_number":6844,"context_line":""},{"line_number":6845,"context_line":"        self.object_controller.async_update \u003d fake_async_update"},{"line_number":6846,"context_line":"        self.object_controller.logger \u003d self.logger"},{"line_number":6847,"context_line":"        delete_at_container \u003d expirer.get_expirer_container(\u00271\u0027, \u0027a\u0027, \u0027c\u0027, \u0027o\u0027)"},{"line_number":6848,"context_line":"        req \u003d Request.blank("},{"line_number":6849,"context_line":"            \u0027/v1/a/c/o\u0027,"},{"line_number":6850,"context_line":"            environ\u003d{\u0027REQUEST_METHOD\u0027: \u0027PUT\u0027},"}],"source_content_type":"text/x-python","patch_set":5,"id":"ac186eeb_072b4630","line":6847,"updated":"2024-06-14 01:27:04.000000000","message":"for uber correctness we should probably pass **self.object_controller.expirer_config, but in this test the stub object_ocntroller is using the defaults.","commit_id":"c6e36d1e962e8eba623bdb086b5522e40368339e"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"9e1341653645bc630e2746759431a3fd177b5398","unresolved":true,"context_lines":[{"line_number":6805,"context_line":"        expected_container \u003d \\"},{"line_number":6806,"context_line":"            self.object_controller.expirer_config.get_expirer_container("},{"line_number":6807,"context_line":"                delete_at, \u0027a\u0027, \u0027c\u0027, \u0027o\u0027)"},{"line_number":6808,"context_line":"        unexpected_container \u003d str(int(delete_at) + 100)"},{"line_number":6809,"context_line":"        req_headers[\u0027X-Delete-At-Container\u0027] \u003d unexpected_container"},{"line_number":6810,"context_line":"        req \u003d Request.blank("},{"line_number":6811,"context_line":"            \u0027/v1/a/c/o\u0027,"}],"source_content_type":"text/x-python","patch_set":10,"id":"d163cd56_3b4a7cc3","line":6808,"updated":"2024-07-18 16:52:31.000000000","message":"this hasn\u0027t been \u0027normalized\u0027 but I think it\u0027s ok because it is the correct format by default (10 digit int)","commit_id":"6fe94c3c0074b7e4d74d7cf23a198b869e816ce7"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"3c753577924d66ca4dbe4fe8e6634ada827d5d1b","unresolved":false,"context_lines":[{"line_number":6805,"context_line":"        expected_container \u003d \\"},{"line_number":6806,"context_line":"            self.object_controller.expirer_config.get_expirer_container("},{"line_number":6807,"context_line":"                delete_at, \u0027a\u0027, \u0027c\u0027, \u0027o\u0027)"},{"line_number":6808,"context_line":"        unexpected_container \u003d str(int(delete_at) + 100)"},{"line_number":6809,"context_line":"        req_headers[\u0027X-Delete-At-Container\u0027] \u003d unexpected_container"},{"line_number":6810,"context_line":"        req \u003d Request.blank("},{"line_number":6811,"context_line":"            \u0027/v1/a/c/o\u0027,"}],"source_content_type":"text/x-python","patch_set":10,"id":"2b791b8f_9e13ed4a","line":6808,"in_reply_to":"d163cd56_3b4a7cc3","updated":"2024-07-31 15:51:16.000000000","message":"wouldn\u0027t hurt to normalize; but tests be testing...\n\nnot critical to \"fix to make MORE correct\" IMHO","commit_id":"6fe94c3c0074b7e4d74d7cf23a198b869e816ce7"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"ed2cb843f69c57e0cb32cf6ce4b2a7d8403bf05d","unresolved":true,"context_lines":[{"line_number":1391,"context_line":"                                  node_count\u003d1):"},{"line_number":1392,"context_line":"        delete_at \u003d headers[\u0027X-Delete-At\u0027]"},{"line_number":1393,"context_line":"        expirer_config \u003d ExpirerConfig("},{"line_number":1394,"context_line":"            self.conf, container_ring\u003dself.container_ring)"},{"line_number":1395,"context_line":"        part, nodes, delete_at_container \u003d expirer_config.get_delete_at_nodes("},{"line_number":1396,"context_line":"            delete_at, a, c, o)"},{"line_number":1397,"context_line":"        # proxy assigns each replica a node, index 0 for test stability"}],"source_content_type":"text/x-python","patch_set":27,"id":"13120643_9817115b","line":1394,"updated":"2024-11-01 21:39:57.000000000","message":"should probably get a logger.","commit_id":"538c82e0fb554328d8ce72e513c583db2c20045a"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"d0f98cfd362e46a234f338320f8ee19044d5e31d","unresolved":false,"context_lines":[{"line_number":1391,"context_line":"                                  node_count\u003d1):"},{"line_number":1392,"context_line":"        delete_at \u003d headers[\u0027X-Delete-At\u0027]"},{"line_number":1393,"context_line":"        expirer_config \u003d ExpirerConfig("},{"line_number":1394,"context_line":"            self.conf, container_ring\u003dself.container_ring)"},{"line_number":1395,"context_line":"        part, nodes, delete_at_container \u003d expirer_config.get_delete_at_nodes("},{"line_number":1396,"context_line":"            delete_at, a, c, o)"},{"line_number":1397,"context_line":"        # proxy assigns each replica a node, index 0 for test stability"}],"source_content_type":"text/x-python","patch_set":27,"id":"bfe5fff8_2e4918b9","line":1394,"in_reply_to":"13120643_9817115b","updated":"2024-11-05 00:21:48.000000000","message":"Done","commit_id":"538c82e0fb554328d8ce72e513c583db2c20045a"}],"test/unit/proxy/controllers/test_obj.py":[{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"9e1341653645bc630e2746759431a3fd177b5398","unresolved":true,"context_lines":[{"line_number":2403,"context_line":"            resp \u003d req.get_response(self.app)"},{"line_number":2404,"context_line":"        self.assertEqual(resp.status_int, 201)"},{"line_number":2405,"context_line":"        found_host_device \u003d set()"},{"line_number":2406,"context_line":"        for i, given_headers in enumerate(put_headers):"},{"line_number":2407,"context_line":"            found_host_device.add(\u0027%s/%s\u0027 % ("},{"line_number":2408,"context_line":"                given_headers[\u0027X-Delete-At-Host\u0027],"},{"line_number":2409,"context_line":"                given_headers[\u0027X-Delete-At-Device\u0027]))"}],"source_content_type":"text/x-python","patch_set":10,"id":"1caeafd7_73b2ef2c","line":2406,"range":{"start_line":2406,"start_character":32,"end_line":2406,"end_character":54},"updated":"2024-07-18 16:52:31.000000000","message":"the enumeration index doesn\u0027t seem to be used, maybe the this test went through some permutations in earlier patchsets","commit_id":"6fe94c3c0074b7e4d74d7cf23a198b869e816ce7"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"296beca32dc11b900b395aa306e293bbda879e69","unresolved":false,"context_lines":[{"line_number":2403,"context_line":"            resp \u003d req.get_response(self.app)"},{"line_number":2404,"context_line":"        self.assertEqual(resp.status_int, 201)"},{"line_number":2405,"context_line":"        found_host_device \u003d set()"},{"line_number":2406,"context_line":"        for i, given_headers in enumerate(put_headers):"},{"line_number":2407,"context_line":"            found_host_device.add(\u0027%s/%s\u0027 % ("},{"line_number":2408,"context_line":"                given_headers[\u0027X-Delete-At-Host\u0027],"},{"line_number":2409,"context_line":"                given_headers[\u0027X-Delete-At-Device\u0027]))"}],"source_content_type":"text/x-python","patch_set":10,"id":"a6c6ee70_bbb25dfb","line":2406,"range":{"start_line":2406,"start_character":32,"end_line":2406,"end_character":54},"in_reply_to":"1caeafd7_73b2ef2c","updated":"2024-07-19 14:05:59.000000000","message":"Done","commit_id":"6fe94c3c0074b7e4d74d7cf23a198b869e816ce7"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"9e1341653645bc630e2746759431a3fd177b5398","unresolved":true,"context_lines":[{"line_number":2414,"context_line":"                             given_headers[\u0027X-Delete-At-Container\u0027])"},{"line_number":2415,"context_line":"        self.assertEqual({\u0027%(ip)s:%(port)s/%(device)s\u0027 % n"},{"line_number":2416,"context_line":"                          for n in expected_nodes},"},{"line_number":2417,"context_line":"                         found_host_device)"},{"line_number":2418,"context_line":""},{"line_number":2419,"context_line":"    def test_POST_delete_at_configure_task_container_per_day(self):"},{"line_number":2420,"context_line":"        self.conf[\u0027expiring_objects_task_container_per_day\u0027] \u003d 1"}],"source_content_type":"text/x-python","patch_set":10,"id":"3e57d291_2a77b5e3","line":2417,"updated":"2024-07-18 16:52:31.000000000","message":"nice improvements","commit_id":"6fe94c3c0074b7e4d74d7cf23a198b869e816ce7"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"3c753577924d66ca4dbe4fe8e6634ada827d5d1b","unresolved":false,"context_lines":[{"line_number":2414,"context_line":"                             given_headers[\u0027X-Delete-At-Container\u0027])"},{"line_number":2415,"context_line":"        self.assertEqual({\u0027%(ip)s:%(port)s/%(device)s\u0027 % n"},{"line_number":2416,"context_line":"                          for n in expected_nodes},"},{"line_number":2417,"context_line":"                         found_host_device)"},{"line_number":2418,"context_line":""},{"line_number":2419,"context_line":"    def test_POST_delete_at_configure_task_container_per_day(self):"},{"line_number":2420,"context_line":"        self.conf[\u0027expiring_objects_task_container_per_day\u0027] \u003d 1"}],"source_content_type":"text/x-python","patch_set":10,"id":"f84db933_5345107c","line":2417,"in_reply_to":"3e57d291_2a77b5e3","updated":"2024-07-31 15:51:16.000000000","message":"Acknowledged","commit_id":"6fe94c3c0074b7e4d74d7cf23a198b869e816ce7"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"9e1341653645bc630e2746759431a3fd177b5398","unresolved":true,"context_lines":[{"line_number":2417,"context_line":"                         found_host_device)"},{"line_number":2418,"context_line":""},{"line_number":2419,"context_line":"    def test_POST_delete_at_configure_task_container_per_day(self):"},{"line_number":2420,"context_line":"        self.conf[\u0027expiring_objects_task_container_per_day\u0027] \u003d 1"},{"line_number":2421,"context_line":"        self._make_app()"},{"line_number":2422,"context_line":"        t \u003d str(int(time.time() + 100))"},{"line_number":2423,"context_line":"        expected_part, expected_nodes, expected_delete_at_container \u003d \\"}],"source_content_type":"text/x-python","patch_set":10,"id":"29b7ca8e_cdd725ee","line":2420,"updated":"2024-07-18 16:52:31.000000000","message":"the test passes even if I delete this line, because the expected values are taken from whatever the expirer_config ends up being\n\nmaybe add a sanity check:\n\n```\n        self.assertEqual(1, self.app.expirer_config.task_container_per_day)\n```","commit_id":"6fe94c3c0074b7e4d74d7cf23a198b869e816ce7"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"296beca32dc11b900b395aa306e293bbda879e69","unresolved":false,"context_lines":[{"line_number":2417,"context_line":"                         found_host_device)"},{"line_number":2418,"context_line":""},{"line_number":2419,"context_line":"    def test_POST_delete_at_configure_task_container_per_day(self):"},{"line_number":2420,"context_line":"        self.conf[\u0027expiring_objects_task_container_per_day\u0027] \u003d 1"},{"line_number":2421,"context_line":"        self._make_app()"},{"line_number":2422,"context_line":"        t \u003d str(int(time.time() + 100))"},{"line_number":2423,"context_line":"        expected_part, expected_nodes, expected_delete_at_container \u003d \\"}],"source_content_type":"text/x-python","patch_set":10,"id":"f058c090_17b39633","line":2420,"in_reply_to":"29b7ca8e_cdd725ee","updated":"2024-07-19 14:05:59.000000000","message":"Done","commit_id":"6fe94c3c0074b7e4d74d7cf23a198b869e816ce7"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"9e1341653645bc630e2746759431a3fd177b5398","unresolved":true,"context_lines":[{"line_number":2422,"context_line":"        t \u003d str(int(time.time() + 100))"},{"line_number":2423,"context_line":"        expected_part, expected_nodes, expected_delete_at_container \u003d \\"},{"line_number":2424,"context_line":"            self.app.expirer_config.get_delete_at_nodes("},{"line_number":2425,"context_line":"                t, \u0027a\u0027, \u0027c\u0027, \u0027o\u0027)"},{"line_number":2426,"context_line":"        req \u003d swob.Request.blank(\u0027/v1/a/c/o\u0027, method\u003d\u0027POST\u0027, body\u003db\u0027\u0027,"},{"line_number":2427,"context_line":"                                 headers\u003d{\u0027Content-Type\u0027: \u0027foo/bar\u0027,"},{"line_number":2428,"context_line":"                                          \u0027X-Delete-At\u0027: t})"}],"source_content_type":"text/x-python","patch_set":10,"id":"0e57f832_2d4ad078","line":2425,"updated":"2024-07-18 16:52:31.000000000","message":"nit: could fit on previous line","commit_id":"6fe94c3c0074b7e4d74d7cf23a198b869e816ce7"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"296beca32dc11b900b395aa306e293bbda879e69","unresolved":false,"context_lines":[{"line_number":2422,"context_line":"        t \u003d str(int(time.time() + 100))"},{"line_number":2423,"context_line":"        expected_part, expected_nodes, expected_delete_at_container \u003d \\"},{"line_number":2424,"context_line":"            self.app.expirer_config.get_delete_at_nodes("},{"line_number":2425,"context_line":"                t, \u0027a\u0027, \u0027c\u0027, \u0027o\u0027)"},{"line_number":2426,"context_line":"        req \u003d swob.Request.blank(\u0027/v1/a/c/o\u0027, method\u003d\u0027POST\u0027, body\u003db\u0027\u0027,"},{"line_number":2427,"context_line":"                                 headers\u003d{\u0027Content-Type\u0027: \u0027foo/bar\u0027,"},{"line_number":2428,"context_line":"                                          \u0027X-Delete-At\u0027: t})"}],"source_content_type":"text/x-python","patch_set":10,"id":"4169f121_77d96ac1","line":2425,"in_reply_to":"0e57f832_2d4ad078","updated":"2024-07-19 14:05:59.000000000","message":"Done","commit_id":"6fe94c3c0074b7e4d74d7cf23a198b869e816ce7"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"9e1341653645bc630e2746759431a3fd177b5398","unresolved":true,"context_lines":[{"line_number":2449,"context_line":"                             given_headers[\u0027X-Delete-At-Container\u0027])"},{"line_number":2450,"context_line":"        self.assertEqual({\u0027%(ip)s:%(port)s/%(device)s\u0027 % n"},{"line_number":2451,"context_line":"                          for n in expected_nodes},"},{"line_number":2452,"context_line":"                         found_host_device)"},{"line_number":2453,"context_line":""},{"line_number":2454,"context_line":"    def test_POST_delete_at_with_x_open_expired(self):"},{"line_number":2455,"context_line":"        t_delete \u003d str(int(time.time() + 30))"}],"source_content_type":"text/x-python","patch_set":10,"id":"ac54f073_e9dae6c7","line":2452,"updated":"2024-07-18 16:52:31.000000000","message":"nice, extend coverage to POST and validate the new conf option","commit_id":"6fe94c3c0074b7e4d74d7cf23a198b869e816ce7"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"3c753577924d66ca4dbe4fe8e6634ada827d5d1b","unresolved":false,"context_lines":[{"line_number":2449,"context_line":"                             given_headers[\u0027X-Delete-At-Container\u0027])"},{"line_number":2450,"context_line":"        self.assertEqual({\u0027%(ip)s:%(port)s/%(device)s\u0027 % n"},{"line_number":2451,"context_line":"                          for n in expected_nodes},"},{"line_number":2452,"context_line":"                         found_host_device)"},{"line_number":2453,"context_line":""},{"line_number":2454,"context_line":"    def test_POST_delete_at_with_x_open_expired(self):"},{"line_number":2455,"context_line":"        t_delete \u003d str(int(time.time() + 30))"}],"source_content_type":"text/x-python","patch_set":10,"id":"202cc274_ec9d14fb","line":2452,"in_reply_to":"ac54f073_e9dae6c7","updated":"2024-07-31 15:51:16.000000000","message":"Acknowledged","commit_id":"6fe94c3c0074b7e4d74d7cf23a198b869e816ce7"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"ed2cb843f69c57e0cb32cf6ce4b2a7d8403bf05d","unresolved":true,"context_lines":[{"line_number":213,"context_line":""},{"line_number":214,"context_line":"        # you can over-ride the container_info just by setting it on the app"},{"line_number":215,"context_line":"        # (see PatchedObjControllerApp for details)"},{"line_number":216,"context_line":"        self.app.container_info \u003d dict(self.fake_container_info())"},{"line_number":217,"context_line":""},{"line_number":218,"context_line":"    def ts(self):"},{"line_number":219,"context_line":"        return next(self._ts_iter)"}],"source_content_type":"text/x-python","patch_set":27,"id":"bcf148da_82795348","line":216,"updated":"2024-11-01 21:39:57.000000000","message":"i wonder if I had extracted this intending to re-use this in `test_POST_delete_at_with_x_open_expired` instead os just \"fixing\" the passing in of the logger?","commit_id":"538c82e0fb554328d8ce72e513c583db2c20045a"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"d0f98cfd362e46a234f338320f8ee19044d5e31d","unresolved":false,"context_lines":[{"line_number":213,"context_line":""},{"line_number":214,"context_line":"        # you can over-ride the container_info just by setting it on the app"},{"line_number":215,"context_line":"        # (see PatchedObjControllerApp for details)"},{"line_number":216,"context_line":"        self.app.container_info \u003d dict(self.fake_container_info())"},{"line_number":217,"context_line":""},{"line_number":218,"context_line":"    def ts(self):"},{"line_number":219,"context_line":"        return next(self._ts_iter)"}],"source_content_type":"text/x-python","patch_set":27,"id":"f99aa3b3_5ecf5697","line":216,"in_reply_to":"bcf148da_82795348","updated":"2024-11-05 00:21:48.000000000","message":"Done","commit_id":"538c82e0fb554328d8ce72e513c583db2c20045a"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"e707e3dcdb5f7a43ad3027ebcc729e8b7baf3f4d","unresolved":true,"context_lines":[{"line_number":2649,"context_line":"                         found_host_device)"},{"line_number":2650,"context_line":""},{"line_number":2651,"context_line":"    def test_POST_delete_at_configure_task_container_per_day(self):"},{"line_number":2652,"context_line":"        self._make_app()"},{"line_number":2653,"context_line":"        self.assertEqual(100, self.app.expirer_config.task_container_per_day)"},{"line_number":2654,"context_line":"        t \u003d str(int(time.time() + 100))"},{"line_number":2655,"context_line":"        expected_part, expected_nodes, expected_delete_at_container \u003d \\"}],"source_content_type":"text/x-python","patch_set":29,"id":"5263e0ce_bc9df981","line":2652,"updated":"2024-11-05 10:10:19.000000000","message":"``self._make_app()`` has already been called in ``setUp``\n\n...but this and the ``configure`` in the test name made me wonder if the intention has been to modify the configuration before a call to _make_app??","commit_id":"a39f35f4b20d7e66639172aa46ccb0d94bf613d9"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"8770fff8b26a1de2cad0405e65c8e4c9e05ed324","unresolved":false,"context_lines":[{"line_number":2649,"context_line":"                         found_host_device)"},{"line_number":2650,"context_line":""},{"line_number":2651,"context_line":"    def test_POST_delete_at_configure_task_container_per_day(self):"},{"line_number":2652,"context_line":"        self._make_app()"},{"line_number":2653,"context_line":"        self.assertEqual(100, self.app.expirer_config.task_container_per_day)"},{"line_number":2654,"context_line":"        t \u003d str(int(time.time() + 100))"},{"line_number":2655,"context_line":"        expected_part, expected_nodes, expected_delete_at_container \u003d \\"}],"source_content_type":"text/x-python","patch_set":29,"id":"31cee09a_cc4edf7c","line":2652,"in_reply_to":"071278fc_1844cf00","updated":"2024-11-18 19:06:00.000000000","message":"sorry this was confusing, I can move the make_app call to the patch where we add the reconfig","commit_id":"a39f35f4b20d7e66639172aa46ccb0d94bf613d9"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"88ef1711f527fcd160696ba077bd2fed6a54ae9e","unresolved":true,"context_lines":[{"line_number":2649,"context_line":"                         found_host_device)"},{"line_number":2650,"context_line":""},{"line_number":2651,"context_line":"    def test_POST_delete_at_configure_task_container_per_day(self):"},{"line_number":2652,"context_line":"        self._make_app()"},{"line_number":2653,"context_line":"        self.assertEqual(100, self.app.expirer_config.task_container_per_day)"},{"line_number":2654,"context_line":"        t \u003d str(int(time.time() + 100))"},{"line_number":2655,"context_line":"        expected_part, expected_nodes, expected_delete_at_container \u003d \\"}],"source_content_type":"text/x-python","patch_set":29,"id":"071278fc_1844cf00","line":2652,"in_reply_to":"5263e0ce_bc9df981","updated":"2024-11-05 11:32:00.000000000","message":"I just found the diff to this test in the next patch (where tas_container_per_day actually becomes configurable)","commit_id":"a39f35f4b20d7e66639172aa46ccb0d94bf613d9"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"8770fff8b26a1de2cad0405e65c8e4c9e05ed324","unresolved":false,"context_lines":[{"line_number":2711,"context_line":""},{"line_number":2712,"context_line":"        # Check when allow_open_expired config is set to true"},{"line_number":2713,"context_line":"        self.conf[\u0027allow_open_expired\u0027] \u003d \u0027true\u0027"},{"line_number":2714,"context_line":"        self._make_app()"},{"line_number":2715,"context_line":"        self.obj_ring \u003d self.app.get_object_ring(int(self.policy))"},{"line_number":2716,"context_line":""},{"line_number":2717,"context_line":"        post_headers \u003d []"}],"source_content_type":"text/x-python","patch_set":29,"id":"625313fc_4c281f95","line":2714,"updated":"2024-11-18 19:06:00.000000000","message":"we establish the \"reconfigure and make app\" pattern here.","commit_id":"a39f35f4b20d7e66639172aa46ccb0d94bf613d9"}]}
