From 315b832420eb8314e809b1c0f549304d423b45f3 Mon Sep 17 00:00:00 2001 From: Rafi Zadanly Date: Sat, 26 Aug 2023 12:13:28 +0700 Subject: Create apache solr queue and implement to product.template and website.categories.homepage --- indoteknik_custom/__manifest__.py | 1 + indoteknik_custom/models/solr/__init__.py | 1 + indoteknik_custom/models/solr/apache_solr_queue.py | 69 ++++++++++++++++++++ indoteknik_custom/models/solr/product_product.py | 26 +++----- indoteknik_custom/models/solr/product_template.py | 48 ++++++++------ .../models/solr/website_categories_homepage.py | 52 +++++++++++---- indoteknik_custom/security/ir.model.access.csv | 1 + indoteknik_custom/views/apache_solr_queue.xml | 74 ++++++++++++++++++++++ indoteknik_custom/views/product_product.xml | 2 +- indoteknik_custom/views/product_template.xml | 2 +- .../views/website_categories_homepage.xml | 2 +- 11 files changed, 226 insertions(+), 52 deletions(-) create mode 100644 indoteknik_custom/models/solr/apache_solr_queue.py create mode 100644 indoteknik_custom/views/apache_solr_queue.xml diff --git a/indoteknik_custom/__manifest__.py b/indoteknik_custom/__manifest__.py index 7c38382c..2e2b6761 100755 --- a/indoteknik_custom/__manifest__.py +++ b/indoteknik_custom/__manifest__.py @@ -91,6 +91,7 @@ 'views/product_attribute_value.xml', 'views/mail_template_po.xml', 'views/price_group.xml', + 'views/apache_solr_queue.xml', 'report/report.xml', 'report/report_banner_banner.xml', 'report/report_banner_banner2.xml', diff --git a/indoteknik_custom/models/solr/__init__.py b/indoteknik_custom/models/solr/__init__.py index 450e1dae..45ef4299 100644 --- a/indoteknik_custom/models/solr/__init__.py +++ b/indoteknik_custom/models/solr/__init__.py @@ -1,4 +1,5 @@ from . import apache_solr +from . import apache_solr_queue from . import product_pricelist_item from . import product_product from . import product_template diff --git a/indoteknik_custom/models/solr/apache_solr_queue.py b/indoteknik_custom/models/solr/apache_solr_queue.py new file mode 100644 index 00000000..eb5a99a8 --- /dev/null +++ b/indoteknik_custom/models/solr/apache_solr_queue.py @@ -0,0 +1,69 @@ +from odoo import models, fields +from datetime import datetime +import logging + + +_logger = logging.getLogger(__name__) + +class ApacheSolrQueue(models.Model): + _name = 'apache.solr.queue' + + display_name = fields.Char('Display Name', compute="_compute_display_name") + res_model = fields.Char('Resource Model') + res_id = fields.Integer('Resource ID') + function_name = fields.Char('Function Name') + execute_status = fields.Selection([ + ('success', 'Success'), + ('failed', 'Failed'), + ('not_found', 'Record not found') + ], 'Execute Status') + execute_date = fields.Datetime('Execute Date') + + def _compute_display_name(self): + for rec in self: + try: + res_model = rec.res_model + res_id = int(rec.res_id) + model_instance = self.env[res_model].browse(res_id) + rec.display_name = model_instance.display_name or '' + except: + rec.display_name = '' + + def process_queue_item(self, limit=100): + records = self.search([('execute_status', '=', False)], order='create_date asc', limit=limit) + for rec in records: + rec.execute_queue() + + def execute_queue(self): + for rec in self: + try: + res_model = rec.res_model + res_id = int(rec.res_id) + function_name = rec.function_name + _logger.info(f'Execute Queue: {res_model}.{function_name}() -> {res_id}') + + domain = [('id', '=', res_id)] + if res_model in ['product.template']: + domain.append(('active', 'in', [True, False])) + + model_instance = self.env[res_model].search(domain) + if model_instance: + getattr(model_instance, function_name)() + rec.execute_status = 'success' + else: + rec.execute_status = 'not_found' + except: + rec.execute_status = 'failed' + rec.execute_date = datetime.utcnow() + self.env.cr.commit() + + def create_unique(self, payload={}): + count = self.search_count([ + ('res_model', '=', payload['res_model']), + ('res_id', '=', payload['res_id']), + ('function_name', '=', payload['function_name']), + ('execute_status', '=', False) + ]) + if count == 0: + self.create(payload) + diff --git a/indoteknik_custom/models/solr/product_product.py b/indoteknik_custom/models/solr/product_product.py index 5090b8d5..f3107afa 100644 --- a/indoteknik_custom/models/solr/product_product.py +++ b/indoteknik_custom/models/solr/product_product.py @@ -14,6 +14,12 @@ class ProductProduct(models.Model): def solr(self): return self.env['apache.solr'].connect('variants') + + def action_sync_to_solr(self): + product_ids = self.env.context.get('active_ids', []) + products = self.search([('id', 'in', product_ids)]) + for product in products: + product.product_tmpl_id._create_solr_queue('_sync_product_template_to_solr') def _sync_variants_to_solr(self): solr_model = self.env['apache.solr'] @@ -59,8 +65,6 @@ class ProductProduct(models.Model): if not document.get('has_price_info_b'): variant._sync_price_to_solr() - self.solr().commit() - def _sync_price_to_solr(self): solr_model = self.env['apache.solr'] @@ -105,17 +109,7 @@ class ProductProduct(models.Model): if not document.get('has_product_info_b'): variant._sync_variants_to_solr() - - self.solr().commit() - - def sync_to_solr(self): - product_ids = self.env.context.get('active_ids', []) - products = self.search([('id', 'in', product_ids)]) - - updated_template_ids = [] - for product in products: - template = product.product_tmpl_id - if template.id in updated_template_ids: - continue - template._sync_product_template_to_solr() - updated_template_ids.append(template.id) \ No newline at end of file + + def _sync_delete_solr(self): + for rec in self: + self.solr().delete(rec.id) \ No newline at end of file diff --git a/indoteknik_custom/models/solr/product_template.py b/indoteknik_custom/models/solr/product_template.py index 6089adda..ba670a81 100644 --- a/indoteknik_custom/models/solr/product_template.py +++ b/indoteknik_custom/models/solr/product_template.py @@ -15,16 +15,31 @@ class ProductTemplate(models.Model): def solr(self): return self.env['apache.solr'].connect('product') + def _create_solr_queue(self, function_name): + for rec in self: + self.env['apache.solr.queue'].create_unique({ + 'res_model': self._name, + 'res_id': rec.id, + 'function_name': function_name + }) + @api.constrains('active') + def _create_solr_queue_sync_active(self): + self._create_solr_queue('_sync_active_template_solr') + + @api.constrains('name', 'default_code', 'weight', 'x_manufacture', 'public_categ_ids', 'search_rank', 'search_rank_weekly', 'image_1920') + def _create_solr_queue_sync_product_template(self): + self._create_solr_queue('_sync_product_template_to_solr') + + def action_sync_to_solr(self): + template_ids = self.env.context.get('active_ids', []) + templates = self.search([('id', 'in', template_ids)]) + templates._create_solr_queue('_sync_product_template_to_solr') + def _sync_active_template_solr(self): for template in self: if not template.active or template.type != 'product': - self.solr().delete(template.id) - - variant_ids = [x.id for x in template.product_variant_ids] - template.product_variant_ids.solr().delete(variant_ids) - - self.solr().commit() + template._sync_delete_solr() else: template._sync_product_template_to_solr() template._sync_price_to_solr() @@ -32,16 +47,6 @@ class ProductTemplate(models.Model): products = self.env['product.product'].search([('product_tmpl_id', '=', template.id), ('active', 'in', [True, False])]) products._sync_variants_to_solr() - @api.constrains( - 'name', - 'default_code', - 'weight', - 'x_manufacture', - 'public_categ_ids', - 'search_rank', - 'search_rank_weekly', - 'image_1920' - ) def _sync_product_template_to_solr(self): solr_model = self.env['apache.solr'] @@ -152,7 +157,10 @@ class ProductTemplate(models.Model): self.solr().commit() - def sync_to_solr(self): - template_ids = self.env.context.get('active_ids', []) - templates = self.search([('id', 'in', template_ids)]) - templates._sync_product_template_to_solr() \ No newline at end of file + def _sync_delete_solr(self): + for rec in self: + self.solr().delete(rec.id) + for variant in rec.product_variant_ids: + variant._sync_delete_solr() + self.solr().optimize() + self.solr().commit() \ No newline at end of file diff --git a/indoteknik_custom/models/solr/website_categories_homepage.py b/indoteknik_custom/models/solr/website_categories_homepage.py index 59e7f32f..21812acf 100644 --- a/indoteknik_custom/models/solr/website_categories_homepage.py +++ b/indoteknik_custom/models/solr/website_categories_homepage.py @@ -14,20 +14,51 @@ class WebsiteCategoriesHomepage(models.Model): def update_last_update_solr(self): self.last_update_solr = datetime.utcnow() + def _create_solr_queue(self, function_name): + for rec in self: + self.env['apache.solr.queue'].create_unique({ + 'res_model': self._name, + 'res_id': rec.id, + 'function_name': function_name + }) + @api.constrains('status') + def _create_solr_queue_sync_status(self): + self._create_solr_queue('_sync_status_category_homepage_solr') + + @api.constrains('category_id', 'image', 'url', 'sequence', 'product_ids') + def _create_solr_queue_sync_category_homepage(self): + self._create_solr_queue('_sync_category_homepage_to_solr') + + def action_sync_to_solr(self): + category_ids = self.env.context.get('active_ids', []) + categories = self.search([('id', 'in', category_ids)]) + categories._create_solr_queue('_sync_category_homepage_to_solr') + + def unlink(self): + res = super(WebsiteCategoriesHomepage, self).unlink() + for rec in self: + self.env['apache.solr.queue'].create_unique({ + 'res_model': self._name, + 'res_id': rec.id, + 'function_name': '_sync_delete_solr' + }) + return res + def _sync_status_category_homepage_solr(self): for rec in self: if rec.status == 'tayang': rec._sync_category_homepage_to_solr() else: - self.solr().delete(rec.id) - self.solr().commit() + rec._sync_delete_solr() - @api.constrains('category_id', 'image', 'url', 'sequence', 'product_ids') def _sync_category_homepage_to_solr(self): solr_model = self.env['apache.solr'] for category in self: + if category.status == 'tidak_tayang': + continue + document = solr_model.get_single_doc('product_category_homepage', category.id) products = [self.env['product.template'].api_single_response(x) for x in category.product_ids] @@ -45,13 +76,8 @@ class WebsiteCategoriesHomepage(models.Model): self.solr().commit() - def sync_to_solr(self): - category_ids = self.env.context.get('active_ids', []) - categories = self.search([('id', 'in', category_ids)]) - categories._sync_category_homepage_to_solr() - - def unlink(self): - res = super(WebsiteCategoriesHomepage, self).unlink() - self.solr().delete([x.id for x in self]) - self.solr().commit() - return res \ No newline at end of file + def _sync_delete_solr(self): + for rec in self: + self.solr().delete(rec.id) + self.solr().optimize() + self.solr().commit() \ No newline at end of file diff --git a/indoteknik_custom/security/ir.model.access.csv b/indoteknik_custom/security/ir.model.access.csv index 6f9ba9e4..c9732614 100755 --- a/indoteknik_custom/security/ir.model.access.csv +++ b/indoteknik_custom/security/ir.model.access.csv @@ -67,3 +67,4 @@ access_account_move_multi_update,access.account.move.multi_update,model_account_ access_airway_bill,access.airway.bill,model_airway_bill,,1,1,1,1 access_airway_bill_manifest,access.airway.bill.manifest,model_airway_bill_manifest,,1,1,1,1 access_price_group,access.price.group,model_price_group,,1,1,1,1 +access_apache_solr_queue,access.apache.solr.queue,model_apache_solr_queue,,1,1,1,1 diff --git a/indoteknik_custom/views/apache_solr_queue.xml b/indoteknik_custom/views/apache_solr_queue.xml new file mode 100644 index 00000000..092871d6 --- /dev/null +++ b/indoteknik_custom/views/apache_solr_queue.xml @@ -0,0 +1,74 @@ + + + apache.solr.queue.tree + apache.solr.queue + + + + + + + + + + + + + + + apache.solr.queue.search + apache.solr.queue + primary + + + + + + + + + + + + Solr Queue + apache.solr.queue + + {'search_default_active_queue': 1} + tree + + + + + + Execute + + + code + records.execute_queue() + + + + + Solr Queue: Process + 6 + minutes + -1 + + + model.process_queue_item(limit=100) + code + 55 + True + + + \ No newline at end of file diff --git a/indoteknik_custom/views/product_product.xml b/indoteknik_custom/views/product_product.xml index 3a10b4e0..6d547712 100644 --- a/indoteknik_custom/views/product_product.xml +++ b/indoteknik_custom/views/product_product.xml @@ -18,7 +18,7 @@ code - model.sync_to_solr() + model.action_sync_to_solr() \ No newline at end of file diff --git a/indoteknik_custom/views/product_template.xml b/indoteknik_custom/views/product_template.xml index bbbcc4e1..b2939867 100755 --- a/indoteknik_custom/views/product_template.xml +++ b/indoteknik_custom/views/product_template.xml @@ -82,7 +82,7 @@ code - model.sync_to_solr() + model.action_sync_to_solr() \ No newline at end of file diff --git a/indoteknik_custom/views/website_categories_homepage.xml b/indoteknik_custom/views/website_categories_homepage.xml index bd64f201..aa54ca7a 100644 --- a/indoteknik_custom/views/website_categories_homepage.xml +++ b/indoteknik_custom/views/website_categories_homepage.xml @@ -56,7 +56,7 @@ code - model.sync_to_solr() + model.action_sync_to_solr()