)]}'
{"/PATCHSET_LEVEL":[{"author":{"_account_id":16312,"name":"Alfredo Moralejo","email":"amoralej@redhat.com","username":"amoralej"},"change_message_id":"186553d9977bf1cc02804ec810c1e11a64e71eca","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":1,"id":"b86af471_bbc9a29a","updated":"2025-10-16 10:29:33.000000000","message":"recheck","commit_id":"4fb3ce722fa2506cf63b092448e0b680f214eb4d"},{"author":{"_account_id":16312,"name":"Alfredo Moralejo","email":"amoralej@redhat.com","username":"amoralej"},"change_message_id":"79f887352ab2f3eb37ba697843bdfe658543a7b4","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":4,"id":"347e7f4e_4e67ff56","updated":"2025-10-29 09:29:30.000000000","message":"recheck","commit_id":"cf94d827d66753f4c53e3c190f100ce52a6c2e76"},{"author":{"_account_id":16312,"name":"Alfredo Moralejo","email":"amoralej@redhat.com","username":"amoralej"},"change_message_id":"560832b838802b58eae85dcfc90a44b1422d94d5","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":4,"id":"e4d18ec0_f7c97c0c","updated":"2025-10-30 08:24:39.000000000","message":"recheck","commit_id":"cf94d827d66753f4c53e3c190f100ce52a6c2e76"},{"author":{"_account_id":34452,"name":"Joan Gilabert","display_name":"jgilaber","email":"jgilaber@redhat.com","username":"jgilaber"},"change_message_id":"7d7d2959f152f17416536187319969c21ee796f8","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":5,"id":"f3d09b57_3b72da1a","updated":"2025-11-19 11:51:34.000000000","message":"the fix lgtm, I just left a few possible minor improvements","commit_id":"294de5bdc69e5ffd43ae9cbee71839a7e024383a"},{"author":{"_account_id":30002,"name":"Douglas Viroel","email":"viroel@gmail.com","username":"dviroel"},"change_message_id":"98cf01a2b287b35e7b038889220244c9b86a764b","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":6,"id":"0b7c414b_e6d0b597","updated":"2025-11-21 14:46:06.000000000","message":"LGTM, we can merge soon if there are no objections","commit_id":"11c4e74f7983d042f41948f538c20af36916b9a1"},{"author":{"_account_id":30002,"name":"Douglas Viroel","email":"viroel@gmail.com","username":"dviroel"},"change_message_id":"bece631b3b4ba89223ff8d8c0785fefd0e430471","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":6,"id":"65775992_0e0589cf","updated":"2025-11-21 14:55:28.000000000","message":"Since this is a bug that users could identify and report, I think that would be good to add a release note here too, wdyt?","commit_id":"11c4e74f7983d042f41948f538c20af36916b9a1"},{"author":{"_account_id":34452,"name":"Joan Gilabert","display_name":"jgilaber","email":"jgilaber@redhat.com","username":"jgilaber"},"change_message_id":"0b916de3fe65d40e40963c5455bd37e36c870186","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":6,"id":"2a31e31b_8d6f541f","updated":"2025-11-21 07:26:29.000000000","message":"thanks for the changes Alfredo, this is good to go from my pov","commit_id":"11c4e74f7983d042f41948f538c20af36916b9a1"},{"author":{"_account_id":16312,"name":"Alfredo Moralejo","email":"amoralej@redhat.com","username":"amoralej"},"change_message_id":"26d0d648de0c370d8e0c6aac8e0ddce14c3f0655","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":6,"id":"62b4f39f_39aa84fd","in_reply_to":"65775992_0e0589cf","updated":"2025-11-21 16:16:56.000000000","message":"Sure, done.","commit_id":"11c4e74f7983d042f41948f538c20af36916b9a1"},{"author":{"_account_id":34452,"name":"Joan Gilabert","display_name":"jgilaber","email":"jgilaber@redhat.com","username":"jgilaber"},"change_message_id":"993f95eff21b38aa0413c49bc7c7df7d04abcf24","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":7,"id":"683bd883_fe095426","updated":"2025-11-24 09:42:07.000000000","message":"other than the pep8 issue this lgtm","commit_id":"63db8e50e16852729cc7c54eea77c272abbd5a71"},{"author":{"_account_id":30002,"name":"Douglas Viroel","email":"viroel@gmail.com","username":"dviroel"},"change_message_id":"06df2cf88274c6fd8f11bed3208d493760bf6b7c","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":8,"id":"c22087b2_6e06146f","updated":"2025-11-24 11:49:57.000000000","message":"LGTM, thanks","commit_id":"38d3dfb84a6de7a407cf6002491dc68383f51853"},{"author":{"_account_id":16312,"name":"Alfredo Moralejo","email":"amoralej@redhat.com","username":"amoralej"},"change_message_id":"44477e0f3a4b3d04ab300f748c03025cef0fde1e","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":8,"id":"5e7621b5_67ff7059","updated":"2025-12-09 09:26:46.000000000","message":"recheck","commit_id":"38d3dfb84a6de7a407cf6002491dc68383f51853"},{"author":{"_account_id":16312,"name":"Alfredo Moralejo","email":"amoralej@redhat.com","username":"amoralej"},"change_message_id":"e35f7ca46a680429af240da0b349bdec0297461f","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":8,"id":"7faa77d1_44d3c133","updated":"2025-12-09 07:47:08.000000000","message":"recheck","commit_id":"38d3dfb84a6de7a407cf6002491dc68383f51853"}],"watcher/api/scheduling.py":[{"author":{"_account_id":34452,"name":"Joan Gilabert","display_name":"jgilaber","email":"jgilaber@redhat.com","username":"jgilaber"},"change_message_id":"c5e84dc7ba0284787f73a159198e6a6dc91e6e54","unresolved":true,"context_lines":[{"line_number":55,"context_line":"            if service.id not in self.services_status:"},{"line_number":56,"context_line":"                self.services_status[service.id] \u003d result"},{"line_number":57,"context_line":"                added \u003d True"},{"line_number":58,"context_line":"            if self.services_status[service.id] !\u003d result or added:"},{"line_number":59,"context_line":"                if self.services_status[service.id] !\u003d result:"},{"line_number":60,"context_line":"                    notifications.service.send_service_update(context, service,"},{"line_number":61,"context_line":"                                                              state\u003dresult)"}],"source_content_type":"text/x-python","patch_set":3,"id":"9f7c36d2_4da3139b","line":58,"updated":"2025-10-24 14:34:16.000000000","message":"could we simplify this multiple ifs with a block like:\n```suggestion\n            if self.services_status.get(service.id) !\u003d result:\n               if self.services_status.get(service.id) is not None:\n                   notifications.service.send_service_update(context, service,\n                                                             state\u003dresult)\n               self.services_status[service.id] \u003d result\n               if (result \u003d\u003d failed_s) and (...) \n```\nresult should not be `None` so that would also cover the case where the service is not in `self.service_status` and unless I\u0027m missing something we would not need any extra variable","commit_id":"758d2c55e8dc314a4eeb882cf6f7e42b4cd647b4"},{"author":{"_account_id":34452,"name":"Joan Gilabert","display_name":"jgilaber","email":"jgilaber@redhat.com","username":"jgilaber"},"change_message_id":"7d7d2959f152f17416536187319969c21ee796f8","unresolved":false,"context_lines":[{"line_number":55,"context_line":"            if service.id not in self.services_status:"},{"line_number":56,"context_line":"                self.services_status[service.id] \u003d result"},{"line_number":57,"context_line":"                added \u003d True"},{"line_number":58,"context_line":"            if self.services_status[service.id] !\u003d result or added:"},{"line_number":59,"context_line":"                if self.services_status[service.id] !\u003d result:"},{"line_number":60,"context_line":"                    notifications.service.send_service_update(context, service,"},{"line_number":61,"context_line":"                                                              state\u003dresult)"}],"source_content_type":"text/x-python","patch_set":3,"id":"2b7ccd56_bcae989b","line":58,"in_reply_to":"4191343c_1c08af3e","updated":"2025-11-19 11:51:34.000000000","message":"Done","commit_id":"758d2c55e8dc314a4eeb882cf6f7e42b4cd647b4"},{"author":{"_account_id":16312,"name":"Alfredo Moralejo","email":"amoralej@redhat.com","username":"amoralej"},"change_message_id":"3b93bbc313a035c4eeda14e0118022f20bca933b","unresolved":true,"context_lines":[{"line_number":55,"context_line":"            if service.id not in self.services_status:"},{"line_number":56,"context_line":"                self.services_status[service.id] \u003d result"},{"line_number":57,"context_line":"                added \u003d True"},{"line_number":58,"context_line":"            if self.services_status[service.id] !\u003d result or added:"},{"line_number":59,"context_line":"                if self.services_status[service.id] !\u003d result:"},{"line_number":60,"context_line":"                    notifications.service.send_service_update(context, service,"},{"line_number":61,"context_line":"                                                              state\u003dresult)"}],"source_content_type":"text/x-python","patch_set":3,"id":"4191343c_1c08af3e","line":58,"in_reply_to":"9f7c36d2_4da3139b","updated":"2025-10-29 09:29:17.000000000","message":"Thanks for the suggestion. I think that should work. I will update.","commit_id":"758d2c55e8dc314a4eeb882cf6f7e42b4cd647b4"},{"author":{"_account_id":34452,"name":"Joan Gilabert","display_name":"jgilaber","email":"jgilaber@redhat.com","username":"jgilaber"},"change_message_id":"c5e84dc7ba0284787f73a159198e6a6dc91e6e54","unresolved":true,"context_lines":[{"line_number":62,"context_line":"                    self.services_status[service.id] \u003d result"},{"line_number":63,"context_line":"                if (result \u003d\u003d failed_s) and ("},{"line_number":64,"context_line":"                        service.name \u003d\u003d \u0027watcher-decision-engine\u0027):"},{"line_number":65,"context_line":"                    audit_filters \u003d {"},{"line_number":66,"context_line":"                        \u0027audit_type\u0027: objects.audit.AuditType.CONTINUOUS.value,"},{"line_number":67,"context_line":"                        \u0027state\u0027: objects.audit.State.ONGOING,"},{"line_number":68,"context_line":"                        \u0027hostname\u0027: service.host"}],"source_content_type":"text/x-python","patch_set":3,"id":"707b7813_23f95ba7","line":65,"updated":"2025-10-24 14:34:16.000000000","message":"considering how nested this code is, I think it might be worth it to refactor to a method, it would improve legibility imo","commit_id":"758d2c55e8dc314a4eeb882cf6f7e42b4cd647b4"},{"author":{"_account_id":34452,"name":"Joan Gilabert","display_name":"jgilaber","email":"jgilaber@redhat.com","username":"jgilaber"},"change_message_id":"7670ffed85562ec380ac2a2ba1b712c0082b3f41","unresolved":false,"context_lines":[{"line_number":62,"context_line":"                    self.services_status[service.id] \u003d result"},{"line_number":63,"context_line":"                if (result \u003d\u003d failed_s) and ("},{"line_number":64,"context_line":"                        service.name \u003d\u003d \u0027watcher-decision-engine\u0027):"},{"line_number":65,"context_line":"                    audit_filters \u003d {"},{"line_number":66,"context_line":"                        \u0027audit_type\u0027: objects.audit.AuditType.CONTINUOUS.value,"},{"line_number":67,"context_line":"                        \u0027state\u0027: objects.audit.State.ONGOING,"},{"line_number":68,"context_line":"                        \u0027hostname\u0027: service.host"}],"source_content_type":"text/x-python","patch_set":3,"id":"f0908e6d_066d5906","line":65,"in_reply_to":"707b7813_23f95ba7","updated":"2025-10-30 11:35:21.000000000","message":"Done","commit_id":"758d2c55e8dc314a4eeb882cf6f7e42b4cd647b4"},{"author":{"_account_id":34452,"name":"Joan Gilabert","display_name":"jgilaber","email":"jgilaber@redhat.com","username":"jgilaber"},"change_message_id":"c5e84dc7ba0284787f73a159198e6a6dc91e6e54","unresolved":true,"context_lines":[{"line_number":63,"context_line":"                if (result \u003d\u003d failed_s) and ("},{"line_number":64,"context_line":"                        service.name \u003d\u003d \u0027watcher-decision-engine\u0027):"},{"line_number":65,"context_line":"                    audit_filters \u003d {"},{"line_number":66,"context_line":"                        \u0027audit_type\u0027: objects.audit.AuditType.CONTINUOUS.value,"},{"line_number":67,"context_line":"                        \u0027state\u0027: objects.audit.State.ONGOING,"},{"line_number":68,"context_line":"                        \u0027hostname\u0027: service.host"},{"line_number":69,"context_line":"                    }"}],"source_content_type":"text/x-python","patch_set":3,"id":"ab104519_ffda591e","line":66,"updated":"2025-10-24 14:34:16.000000000","message":"could/should we also migrate `ONESHOT` audits that were ongoing if the decision engine service failed meanwhile?","commit_id":"758d2c55e8dc314a4eeb882cf6f7e42b4cd647b4"},{"author":{"_account_id":34452,"name":"Joan Gilabert","display_name":"jgilaber","email":"jgilaber@redhat.com","username":"jgilaber"},"change_message_id":"7670ffed85562ec380ac2a2ba1b712c0082b3f41","unresolved":false,"context_lines":[{"line_number":63,"context_line":"                if (result \u003d\u003d failed_s) and ("},{"line_number":64,"context_line":"                        service.name \u003d\u003d \u0027watcher-decision-engine\u0027):"},{"line_number":65,"context_line":"                    audit_filters \u003d {"},{"line_number":66,"context_line":"                        \u0027audit_type\u0027: objects.audit.AuditType.CONTINUOUS.value,"},{"line_number":67,"context_line":"                        \u0027state\u0027: objects.audit.State.ONGOING,"},{"line_number":68,"context_line":"                        \u0027hostname\u0027: service.host"},{"line_number":69,"context_line":"                    }"}],"source_content_type":"text/x-python","patch_set":3,"id":"28c208c7_58895562","line":66,"in_reply_to":"6435b59c_0d378186","updated":"2025-10-30 11:35:21.000000000","message":"that\u0027s completely fair and I wasn\u0027t really pushing for it to be fix in this patch tbh. I had not thought about it, but it ocurred to me while reviewing, I think that is a good discussion to have in the PTG, thanks!","commit_id":"758d2c55e8dc314a4eeb882cf6f7e42b4cd647b4"},{"author":{"_account_id":16312,"name":"Alfredo Moralejo","email":"amoralej@redhat.com","username":"amoralej"},"change_message_id":"3b93bbc313a035c4eeda14e0118022f20bca933b","unresolved":true,"context_lines":[{"line_number":63,"context_line":"                if (result \u003d\u003d failed_s) and ("},{"line_number":64,"context_line":"                        service.name \u003d\u003d \u0027watcher-decision-engine\u0027):"},{"line_number":65,"context_line":"                    audit_filters \u003d {"},{"line_number":66,"context_line":"                        \u0027audit_type\u0027: objects.audit.AuditType.CONTINUOUS.value,"},{"line_number":67,"context_line":"                        \u0027state\u0027: objects.audit.State.ONGOING,"},{"line_number":68,"context_line":"                        \u0027hostname\u0027: service.host"},{"line_number":69,"context_line":"                    }"}],"source_content_type":"text/x-python","patch_set":3,"id":"6435b59c_0d378186","line":66,"in_reply_to":"ab104519_ffda591e","updated":"2025-10-29 09:29:17.000000000","message":"That\u0027s a separate discussion that i don\u0027t want to merge with this. Current behavior is that oneshot audits running ata a dead decision-engine are cancelled when it\u0027s back. Currently, decision-engine services can not retake an action plan which is in ONGOING, that good need further changes. I will include that behavior in the discussions in PTG.","commit_id":"758d2c55e8dc314a4eeb882cf6f7e42b4cd647b4"},{"author":{"_account_id":34452,"name":"Joan Gilabert","display_name":"jgilaber","email":"jgilaber@redhat.com","username":"jgilaber"},"change_message_id":"7d7d2959f152f17416536187319969c21ee796f8","unresolved":true,"context_lines":[{"line_number":36,"context_line":"        self.services_status \u003d {}"},{"line_number":37,"context_line":"        super().__init__(gconfig, **options)"},{"line_number":38,"context_line":""},{"line_number":39,"context_line":"    def _get_services_status(self, context):"},{"line_number":40,"context_line":"        services_status \u003d []"},{"line_number":41,"context_line":"        services \u003d objects.service.Service.list(context)"},{"line_number":42,"context_line":"        for service in services:"}],"source_content_type":"text/x-python","patch_set":5,"id":"36bc30d2_f9b25615","line":39,"updated":"2025-11-19 11:51:34.000000000","message":"I\u0027m not sure I would add the underscore here, to me this method does not feel any more private that `get_service_status`, and considering that the patch adds unit testing for it I think we should consider it public","commit_id":"294de5bdc69e5ffd43ae9cbee71839a7e024383a"},{"author":{"_account_id":16312,"name":"Alfredo Moralejo","email":"amoralej@redhat.com","username":"amoralej"},"change_message_id":"aa933c38ab3eabc67fe8c6c6cf7c8d878bd1828f","unresolved":true,"context_lines":[{"line_number":36,"context_line":"        self.services_status \u003d {}"},{"line_number":37,"context_line":"        super().__init__(gconfig, **options)"},{"line_number":38,"context_line":""},{"line_number":39,"context_line":"    def _get_services_status(self, context):"},{"line_number":40,"context_line":"        services_status \u003d []"},{"line_number":41,"context_line":"        services \u003d objects.service.Service.list(context)"},{"line_number":42,"context_line":"        for service in services:"}],"source_content_type":"text/x-python","patch_set":5,"id":"9598ae53_eea5d447","line":39,"in_reply_to":"36bc30d2_f9b25615","updated":"2025-11-20 15:50:24.000000000","message":"That\u0027s fair, making it public.","commit_id":"294de5bdc69e5ffd43ae9cbee71839a7e024383a"},{"author":{"_account_id":34452,"name":"Joan Gilabert","display_name":"jgilaber","email":"jgilaber@redhat.com","username":"jgilaber"},"change_message_id":"0b916de3fe65d40e40963c5455bd37e36c870186","unresolved":false,"context_lines":[{"line_number":36,"context_line":"        self.services_status \u003d {}"},{"line_number":37,"context_line":"        super().__init__(gconfig, **options)"},{"line_number":38,"context_line":""},{"line_number":39,"context_line":"    def _get_services_status(self, context):"},{"line_number":40,"context_line":"        services_status \u003d []"},{"line_number":41,"context_line":"        services \u003d objects.service.Service.list(context)"},{"line_number":42,"context_line":"        for service in services:"}],"source_content_type":"text/x-python","patch_set":5,"id":"d80446e7_43899580","line":39,"in_reply_to":"9598ae53_eea5d447","updated":"2025-11-21 07:26:29.000000000","message":"Done","commit_id":"294de5bdc69e5ffd43ae9cbee71839a7e024383a"},{"author":{"_account_id":34452,"name":"Joan Gilabert","display_name":"jgilaber","email":"jgilaber@redhat.com","username":"jgilaber"},"change_message_id":"7d7d2959f152f17416536187319969c21ee796f8","unresolved":true,"context_lines":[{"line_number":37,"context_line":"        super().__init__(gconfig, **options)"},{"line_number":38,"context_line":""},{"line_number":39,"context_line":"    def _get_services_status(self, context):"},{"line_number":40,"context_line":"        services_status \u003d []"},{"line_number":41,"context_line":"        services \u003d objects.service.Service.list(context)"},{"line_number":42,"context_line":"        for service in services:"},{"line_number":43,"context_line":"            state \u003d self.get_service_status(context, service.id)"}],"source_content_type":"text/x-python","patch_set":5,"id":"b5aa25ee_a74af098","line":40,"updated":"2025-11-19 11:51:34.000000000","message":"this is a nit, so feel free to disregard, but I think it might be good to rename `services_status` to `services_states` to avoid any confusion between this variable and the `services_status` attribute of the class, which is of a different type. The implementation is correct and this will not cause any bug, but I think it could be confusing for someone reading the code for the first time","commit_id":"294de5bdc69e5ffd43ae9cbee71839a7e024383a"},{"author":{"_account_id":34452,"name":"Joan Gilabert","display_name":"jgilaber","email":"jgilaber@redhat.com","username":"jgilaber"},"change_message_id":"0b916de3fe65d40e40963c5455bd37e36c870186","unresolved":false,"context_lines":[{"line_number":37,"context_line":"        super().__init__(gconfig, **options)"},{"line_number":38,"context_line":""},{"line_number":39,"context_line":"    def _get_services_status(self, context):"},{"line_number":40,"context_line":"        services_status \u003d []"},{"line_number":41,"context_line":"        services \u003d objects.service.Service.list(context)"},{"line_number":42,"context_line":"        for service in services:"},{"line_number":43,"context_line":"            state \u003d self.get_service_status(context, service.id)"}],"source_content_type":"text/x-python","patch_set":5,"id":"29a4b4ef_b540e358","line":40,"in_reply_to":"6cd68a37_1a239295","updated":"2025-11-21 07:26:29.000000000","message":"Done","commit_id":"294de5bdc69e5ffd43ae9cbee71839a7e024383a"},{"author":{"_account_id":16312,"name":"Alfredo Moralejo","email":"amoralej@redhat.com","username":"amoralej"},"change_message_id":"aa933c38ab3eabc67fe8c6c6cf7c8d878bd1828f","unresolved":true,"context_lines":[{"line_number":37,"context_line":"        super().__init__(gconfig, **options)"},{"line_number":38,"context_line":""},{"line_number":39,"context_line":"    def _get_services_status(self, context):"},{"line_number":40,"context_line":"        services_status \u003d []"},{"line_number":41,"context_line":"        services \u003d objects.service.Service.list(context)"},{"line_number":42,"context_line":"        for service in services:"},{"line_number":43,"context_line":"            state \u003d self.get_service_status(context, service.id)"}],"source_content_type":"text/x-python","patch_set":5,"id":"6cd68a37_1a239295","line":40,"in_reply_to":"b5aa25ee_a74af098","updated":"2025-11-20 15:50:24.000000000","message":"Good point.","commit_id":"294de5bdc69e5ffd43ae9cbee71839a7e024383a"},{"author":{"_account_id":34452,"name":"Joan Gilabert","display_name":"jgilaber","email":"jgilaber@redhat.com","username":"jgilaber"},"change_message_id":"7d7d2959f152f17416536187319969c21ee796f8","unresolved":true,"context_lines":[{"line_number":48,"context_line":"    def _migrate_audits_to_new_host(self, ongoing_audits, alive_services):"},{"line_number":49,"context_line":"        round_robin \u003d itertools.cycle(alive_services)"},{"line_number":50,"context_line":"        for audit in ongoing_audits:"},{"line_number":51,"context_line":"            failed_host \u003d audit.hostname"},{"line_number":52,"context_line":"            audit.hostname \u003d round_robin.__next__()"},{"line_number":53,"context_line":"            audit.save()"},{"line_number":54,"context_line":"            LOG.info(\u0027Audit %(audit)s has been migrated to \u0027"}],"source_content_type":"text/x-python","patch_set":5,"id":"68225037_1a733f86","line":51,"updated":"2025-11-19 11:51:34.000000000","message":"just a question to ensure I understood correctly how the migration works. Setting the hostname is enough, because the `launch_audits_periodically` of the chosen service will eventually run and the audit will be picked in https://github.com/openstack/watcher/blob/8a884e3d5166678b85eaf264e518ef24b30085e5/watcher/decision_engine/audit/continuous.py#L178 and executed by the service choses from the `alive_services` list, is that correct?","commit_id":"294de5bdc69e5ffd43ae9cbee71839a7e024383a"},{"author":{"_account_id":34452,"name":"Joan Gilabert","display_name":"jgilaber","email":"jgilaber@redhat.com","username":"jgilaber"},"change_message_id":"0b916de3fe65d40e40963c5455bd37e36c870186","unresolved":false,"context_lines":[{"line_number":48,"context_line":"    def _migrate_audits_to_new_host(self, ongoing_audits, alive_services):"},{"line_number":49,"context_line":"        round_robin \u003d itertools.cycle(alive_services)"},{"line_number":50,"context_line":"        for audit in ongoing_audits:"},{"line_number":51,"context_line":"            failed_host \u003d audit.hostname"},{"line_number":52,"context_line":"            audit.hostname \u003d round_robin.__next__()"},{"line_number":53,"context_line":"            audit.save()"},{"line_number":54,"context_line":"            LOG.info(\u0027Audit %(audit)s has been migrated to \u0027"}],"source_content_type":"text/x-python","patch_set":5,"id":"c1c07800_ec9ce8b0","line":51,"in_reply_to":"4fc39c84_32f7f4bc","updated":"2025-11-21 07:26:29.000000000","message":"thanks for the clarification!","commit_id":"294de5bdc69e5ffd43ae9cbee71839a7e024383a"},{"author":{"_account_id":16312,"name":"Alfredo Moralejo","email":"amoralej@redhat.com","username":"amoralej"},"change_message_id":"aa933c38ab3eabc67fe8c6c6cf7c8d878bd1828f","unresolved":true,"context_lines":[{"line_number":48,"context_line":"    def _migrate_audits_to_new_host(self, ongoing_audits, alive_services):"},{"line_number":49,"context_line":"        round_robin \u003d itertools.cycle(alive_services)"},{"line_number":50,"context_line":"        for audit in ongoing_audits:"},{"line_number":51,"context_line":"            failed_host \u003d audit.hostname"},{"line_number":52,"context_line":"            audit.hostname \u003d round_robin.__next__()"},{"line_number":53,"context_line":"            audit.save()"},{"line_number":54,"context_line":"            LOG.info(\u0027Audit %(audit)s has been migrated to \u0027"}],"source_content_type":"text/x-python","patch_set":5,"id":"4fc39c84_32f7f4bc","line":51,"in_reply_to":"68225037_1a733f86","updated":"2025-11-20 15:50:24.000000000","message":"Exactly, the launch_audits_periodically is executed every CONF.watcher_decision_engine.continuous_audit_interval seconds in https://github.com/openstack/watcher/blob/8a884e3d5166678b85eaf264e518ef24b30085e5/watcher/decision_engine/audit/continuous.py#L222-L226\n\nOn each execution, it checks all the continuous audits assigned to it via audit.hostname and execute them or/and sets next_run_time and schedules the execution.","commit_id":"294de5bdc69e5ffd43ae9cbee71839a7e024383a"},{"author":{"_account_id":34452,"name":"Joan Gilabert","display_name":"jgilaber","email":"jgilaber@redhat.com","username":"jgilaber"},"change_message_id":"7d7d2959f152f17416536187319969c21ee796f8","unresolved":true,"context_lines":[{"line_number":84,"context_line":"                        context,"},{"line_number":85,"context_line":"                        filters\u003daudit_filters,"},{"line_number":86,"context_line":"                        eager\u003dTrue)"},{"line_number":87,"context_line":"                    alive_services \u003d ["},{"line_number":88,"context_line":"                        s.host for s in services"},{"line_number":89,"context_line":"                        if (s.state \u003d\u003d active_s and"},{"line_number":90,"context_line":"                            s.name \u003d\u003d \u0027watcher-decision-engine\u0027)]"}],"source_content_type":"text/x-python","patch_set":5,"id":"b5b7c6fe_15cf1e81","line":87,"updated":"2025-11-19 11:51:34.000000000","message":"I would move this list comprehension outside the loop, since the result will be the same for all iteration","commit_id":"294de5bdc69e5ffd43ae9cbee71839a7e024383a"},{"author":{"_account_id":34452,"name":"Joan Gilabert","display_name":"jgilaber","email":"jgilaber@redhat.com","username":"jgilaber"},"change_message_id":"0b916de3fe65d40e40963c5455bd37e36c870186","unresolved":false,"context_lines":[{"line_number":84,"context_line":"                        context,"},{"line_number":85,"context_line":"                        filters\u003daudit_filters,"},{"line_number":86,"context_line":"                        eager\u003dTrue)"},{"line_number":87,"context_line":"                    alive_services \u003d ["},{"line_number":88,"context_line":"                        s.host for s in services"},{"line_number":89,"context_line":"                        if (s.state \u003d\u003d active_s and"},{"line_number":90,"context_line":"                            s.name \u003d\u003d \u0027watcher-decision-engine\u0027)]"}],"source_content_type":"text/x-python","patch_set":5,"id":"35cddb80_ff918573","line":87,"in_reply_to":"819f9b2c_1f2b6891","updated":"2025-11-21 07:26:29.000000000","message":"Done","commit_id":"294de5bdc69e5ffd43ae9cbee71839a7e024383a"},{"author":{"_account_id":16312,"name":"Alfredo Moralejo","email":"amoralej@redhat.com","username":"amoralej"},"change_message_id":"aa933c38ab3eabc67fe8c6c6cf7c8d878bd1828f","unresolved":true,"context_lines":[{"line_number":84,"context_line":"                        context,"},{"line_number":85,"context_line":"                        filters\u003daudit_filters,"},{"line_number":86,"context_line":"                        eager\u003dTrue)"},{"line_number":87,"context_line":"                    alive_services \u003d ["},{"line_number":88,"context_line":"                        s.host for s in services"},{"line_number":89,"context_line":"                        if (s.state \u003d\u003d active_s and"},{"line_number":90,"context_line":"                            s.name \u003d\u003d \u0027watcher-decision-engine\u0027)]"}],"source_content_type":"text/x-python","patch_set":5,"id":"819f9b2c_1f2b6891","line":87,"in_reply_to":"b5b7c6fe_15cf1e81","updated":"2025-11-20 15:50:24.000000000","message":"good point","commit_id":"294de5bdc69e5ffd43ae9cbee71839a7e024383a"}],"watcher/tests/api/test_scheduling.py":[{"author":{"_account_id":34452,"name":"Joan Gilabert","display_name":"jgilaber","email":"jgilaber@redhat.com","username":"jgilaber"},"change_message_id":"7670ffed85562ec380ac2a2ba1b712c0082b3f41","unresolved":true,"context_lines":[{"line_number":167,"context_line":"        scheduler \u003d scheduling.APISchedulingService()"},{"line_number":168,"context_line":"        # Prepare three ongoing audits with the same failed host"},{"line_number":169,"context_line":"        audits \u003d []"},{"line_number":170,"context_line":"        for i in range(3):"},{"line_number":171,"context_line":"            audit \u003d mock.Mock()"},{"line_number":172,"context_line":"            audit.hostname \u003d \u0027failed-host\u0027"},{"line_number":173,"context_line":"            audit.uuid \u003d f\u0027u{i}\u0027"}],"source_content_type":"text/x-python","patch_set":4,"id":"40dd3b19_4fb4eaac","line":170,"updated":"2025-10-30 11:35:21.000000000","message":"I think we should use a spec here to mock the precise object, since we know its type, the test could change things like a type in an attribute name in either the  code or the test. Also, you can pass the attributes to mock as kwargs to the Mock, so this loop could be converted to a list comprehension\n\n```suggestion\n    audits \u003d [\n        mock.Mock(spec\u003dobjects.Audit, hostname\u003d\u0027failed-host\u0027,uuid\u003df\u0027u{i}\u0027)\n        for i in range(3)\n    ]\n```","commit_id":"cf94d827d66753f4c53e3c190f100ce52a6c2e76"},{"author":{"_account_id":16312,"name":"Alfredo Moralejo","email":"amoralej@redhat.com","username":"amoralej"},"change_message_id":"81efb52ed8227fbb9f9c3e502400c739b13f29ef","unresolved":true,"context_lines":[{"line_number":167,"context_line":"        scheduler \u003d scheduling.APISchedulingService()"},{"line_number":168,"context_line":"        # Prepare three ongoing audits with the same failed host"},{"line_number":169,"context_line":"        audits \u003d []"},{"line_number":170,"context_line":"        for i in range(3):"},{"line_number":171,"context_line":"            audit \u003d mock.Mock()"},{"line_number":172,"context_line":"            audit.hostname \u003d \u0027failed-host\u0027"},{"line_number":173,"context_line":"            audit.uuid \u003d f\u0027u{i}\u0027"}],"source_content_type":"text/x-python","patch_set":4,"id":"4b53b628_db817b82","line":170,"in_reply_to":"40dd3b19_4fb4eaac","updated":"2025-10-31 09:52:06.000000000","message":"Good point, I will update it.","commit_id":"cf94d827d66753f4c53e3c190f100ce52a6c2e76"},{"author":{"_account_id":16312,"name":"Alfredo Moralejo","email":"amoralej@redhat.com","username":"amoralej"},"change_message_id":"146e3ef74636519f746fd00b9891f3a08659f04e","unresolved":false,"context_lines":[{"line_number":167,"context_line":"        scheduler \u003d scheduling.APISchedulingService()"},{"line_number":168,"context_line":"        # Prepare three ongoing audits with the same failed host"},{"line_number":169,"context_line":"        audits \u003d []"},{"line_number":170,"context_line":"        for i in range(3):"},{"line_number":171,"context_line":"            audit \u003d mock.Mock()"},{"line_number":172,"context_line":"            audit.hostname \u003d \u0027failed-host\u0027"},{"line_number":173,"context_line":"            audit.uuid \u003d f\u0027u{i}\u0027"}],"source_content_type":"text/x-python","patch_set":4,"id":"cc383479_ae94d5c3","line":170,"in_reply_to":"4b53b628_db817b82","updated":"2025-10-31 09:56:15.000000000","message":"Done","commit_id":"cf94d827d66753f4c53e3c190f100ce52a6c2e76"},{"author":{"_account_id":34452,"name":"Joan Gilabert","display_name":"jgilaber","email":"jgilaber@redhat.com","username":"jgilaber"},"change_message_id":"7d7d2959f152f17416536187319969c21ee796f8","unresolved":true,"context_lines":[{"line_number":108,"context_line":"        self.assertEqual([], services_status)"},{"line_number":109,"context_line":"        mock_service_status.assert_not_called()"},{"line_number":110,"context_line":""},{"line_number":111,"context_line":"    @mock.patch.object(scheduling.APISchedulingService, \u0027get_service_status\u0027)"},{"line_number":112,"context_line":"    @mock.patch.object(objects.Service, \u0027list\u0027)"},{"line_number":113,"context_line":"    def test_get_services_status_with_services_in_list("},{"line_number":114,"context_line":"            self, m_service_list, m_get_service_status):"}],"source_content_type":"text/x-python","patch_set":5,"id":"a3a4c79b_384fdcfc","line":111,"updated":"2025-11-19 11:51:34.000000000","message":"I think we should mock `objects.Service.get` instead of `get_service_status` here like we do in line 89, alternatively, if we mock `get_service_status` we should be asserting that we have the expected calls imo","commit_id":"294de5bdc69e5ffd43ae9cbee71839a7e024383a"},{"author":{"_account_id":16312,"name":"Alfredo Moralejo","email":"amoralej@redhat.com","username":"amoralej"},"change_message_id":"aa933c38ab3eabc67fe8c6c6cf7c8d878bd1828f","unresolved":true,"context_lines":[{"line_number":108,"context_line":"        self.assertEqual([], services_status)"},{"line_number":109,"context_line":"        mock_service_status.assert_not_called()"},{"line_number":110,"context_line":""},{"line_number":111,"context_line":"    @mock.patch.object(scheduling.APISchedulingService, \u0027get_service_status\u0027)"},{"line_number":112,"context_line":"    @mock.patch.object(objects.Service, \u0027list\u0027)"},{"line_number":113,"context_line":"    def test_get_services_status_with_services_in_list("},{"line_number":114,"context_line":"            self, m_service_list, m_get_service_status):"}],"source_content_type":"text/x-python","patch_set":5,"id":"b4e5409e_c4448eac","line":111,"in_reply_to":"a3a4c79b_384fdcfc","updated":"2025-11-20 15:50:24.000000000","message":"In this test I\u0027m validating get_services_status method so IMO it is fine to mock get_service_status as unit tests should test the logic in the method itself not in dependencies.\n\nget_service_status is tested itself in the previous tests mocking Service.get as you mentioned. \n\nBut, as you proposed it\u0027s good to assert we are calling get_service_status properly.","commit_id":"294de5bdc69e5ffd43ae9cbee71839a7e024383a"},{"author":{"_account_id":34452,"name":"Joan Gilabert","display_name":"jgilaber","email":"jgilaber@redhat.com","username":"jgilaber"},"change_message_id":"0b916de3fe65d40e40963c5455bd37e36c870186","unresolved":false,"context_lines":[{"line_number":108,"context_line":"        self.assertEqual([], services_status)"},{"line_number":109,"context_line":"        mock_service_status.assert_not_called()"},{"line_number":110,"context_line":""},{"line_number":111,"context_line":"    @mock.patch.object(scheduling.APISchedulingService, \u0027get_service_status\u0027)"},{"line_number":112,"context_line":"    @mock.patch.object(objects.Service, \u0027list\u0027)"},{"line_number":113,"context_line":"    def test_get_services_status_with_services_in_list("},{"line_number":114,"context_line":"            self, m_service_list, m_get_service_status):"}],"source_content_type":"text/x-python","patch_set":5,"id":"c1c09a47_438e6d1c","line":111,"in_reply_to":"b4e5409e_c4448eac","updated":"2025-11-21 07:26:29.000000000","message":"fair enough, I think adding the assert it\u0027s enough","commit_id":"294de5bdc69e5ffd43ae9cbee71839a7e024383a"},{"author":{"_account_id":30002,"name":"Douglas Viroel","email":"viroel@gmail.com","username":"dviroel"},"change_message_id":"98cf01a2b287b35e7b038889220244c9b86a764b","unresolved":true,"context_lines":[{"line_number":177,"context_line":"        uuid_prefix \u003d \u0027cd975eb2-a72f-442d-bece-e9dd21b1437\u0027"},{"line_number":178,"context_line":"        audits \u003d ["},{"line_number":179,"context_line":"            objects.Audit(context\u003dself.context,"},{"line_number":180,"context_line":"                          uuid\u003df\u0027{uuid_prefix}{i}\u0027,"},{"line_number":181,"context_line":"                          hostname\u003d\u0027failed-host\u0027)"},{"line_number":182,"context_line":"            for i in range(3)"},{"line_number":183,"context_line":"        ]"}],"source_content_type":"text/x-python","patch_set":6,"id":"339f17ec_a72ff63b","line":180,"range":{"start_line":180,"start_character":26,"end_line":180,"end_character":49},"updated":"2025-11-21 14:46:06.000000000","message":"you could just use the watcher.common.utils.generate_uuid instead I think","commit_id":"11c4e74f7983d042f41948f538c20af36916b9a1"},{"author":{"_account_id":16312,"name":"Alfredo Moralejo","email":"amoralej@redhat.com","username":"amoralej"},"change_message_id":"26d0d648de0c370d8e0c6aac8e0ddce14c3f0655","unresolved":false,"context_lines":[{"line_number":177,"context_line":"        uuid_prefix \u003d \u0027cd975eb2-a72f-442d-bece-e9dd21b1437\u0027"},{"line_number":178,"context_line":"        audits \u003d ["},{"line_number":179,"context_line":"            objects.Audit(context\u003dself.context,"},{"line_number":180,"context_line":"                          uuid\u003df\u0027{uuid_prefix}{i}\u0027,"},{"line_number":181,"context_line":"                          hostname\u003d\u0027failed-host\u0027)"},{"line_number":182,"context_line":"            for i in range(3)"},{"line_number":183,"context_line":"        ]"}],"source_content_type":"text/x-python","patch_set":6,"id":"9116dddb_1a47cd16","line":180,"range":{"start_line":180,"start_character":26,"end_line":180,"end_character":49},"in_reply_to":"339f17ec_a72ff63b","updated":"2025-11-21 16:16:56.000000000","message":"Done","commit_id":"11c4e74f7983d042f41948f538c20af36916b9a1"}]}
