Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[14.0][ADD] queue_job_chunk : backport from v16 #739

Draft
wants to merge 20 commits into
base: 14.0
Choose a base branch
from
Draft
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
[IMP] Logic on queue.job.chunk, company_ids, tests, and component sep…
…aration
kevinkhao authored and Clément Mombereau committed Jan 20, 2025
commit 887663d497cd3424a710f38f98754cc01c105545
1 change: 1 addition & 0 deletions queue_job_chunk/components/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
from . import processor
from . import creator
18 changes: 18 additions & 0 deletions queue_job_chunk/components/creator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Copyright (c) Akretion 2020
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html)

import json

from odoo.addons.component.core import Component


class Creator(Component):
""" Just creates a record with given vals """

_inherit = "processor"
_name = "basic.creator"
_usage = "basic_create"

def run(self, data):
data = json.loads(data)
return self.model.create(data)
23 changes: 2 additions & 21 deletions queue_job_chunk/components/processor.py
Original file line number Diff line number Diff line change
@@ -1,29 +1,10 @@
# Copyright (c) Akretion 2020
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html)

import ast

from odoo.addons.component.core import AbstractComponent, Component
from odoo.addons.component.core import AbstractComponent


class Processor(AbstractComponent):
_name = "processor"
_inherit = "base"
_collection = "collection.base"


class Creator(
Component
): # TODO resolve issue with in-module component tests, move to test
""" Just creates a record with given vals """

_inherit = "base"
_name = "basic.creator"
_collection = "collection.base"
_apply_on = ["res.partner", "ir.module.module"]
_usage = "basic_create"

def run(self, data):
create_vals = ast.literal_eval(data)
result = self.model.create(create_vals)
return result
_collection = "queue.job.chunk"
32 changes: 13 additions & 19 deletions queue_job_chunk/models/queue_job_chunk.py
Original file line number Diff line number Diff line change
@@ -9,19 +9,16 @@
class QueueJobChunk(models.Model):
_name = "queue.job.chunk"
_description = "Queue Job Chunk"
_inherit = "collection.base"

def _get_default_company_id(self):
for rec in self:
if rec.reference:
if "company_id" in rec.reference._fields:
rec.company_id = rec.reference.company_id
continue
rec.company_id = self.env.uid.company_id

@api.depends("model_id", "record_id")
@api.depends("model_name", "record_id")
def _compute_reference(self):
for res in self:
res.reference = "{},{}".format(res.model, res.res_id)
for rec in self:
if rec.model_name and rec.record_id:
rec.reference = "{},{}".format(rec.model_name, rec.record_id)
record = self.env[rec.model_name].browse(rec.record_id)
if "company_id" in record._fields:
rec.reference_company_id = record.company_id

# component fields
usage = fields.Char("Usage")
@@ -34,10 +31,10 @@ def _compute_reference(self):
string="State",
)
state_info = fields.Text("Additional state information")
model_id = fields.Char("Model ID")
model_name = fields.Char("Model ID")
record_id = fields.Integer("Record ID")
reference = fields.Char(string="Reference", selection=_compute_reference)
company_id = fields.Many2one("res.company", default=_get_default_company_id)
reference = fields.Char(string="Reference", compute=_compute_reference)
reference_company_id = fields.Many2one("res.company", compute=_compute_reference)

@api.model_create_multi
def create(self, vals):
@@ -56,17 +53,14 @@ def enqueue_job(self):
def _enqueue_job(self):
self.ensure_one()
usage = self.usage
collection = self.env["collection.base"].new()
apply_on = self.apply_on_model
with collection.work_on(apply_on) as work:
processor = work.component(usage=usage)
with self.work_on(apply_on) as work:
try:
processor = work.component(usage=usage)
result = processor.run(self.data_str)
except Exception as e:
self.state = "fail"
self.state_info = str(e)
return False
self.model_id = result._name
self.record_id = result.id
self.state = "done"
return result
101 changes: 72 additions & 29 deletions queue_job_chunk/tests/test_queue_job_chunk.py
Original file line number Diff line number Diff line change
@@ -11,46 +11,89 @@ def setUp(self):
self.env = self.env(
context=dict(self.env.context, test_queue_job_no_delay=True)
)

def test_create_chunk(self):
partner_count = self.env["res.partner"].search_count([])
module_count = self.env["ir.module.module"].search_count([])

chunk_data_1 = "{'name': 'Steve Queue Job'}"
chunk_vals_1 = {
self.main_company = self.env.ref("base.main_company")
self.another_company_partner = self.env["res.partner"].create(
{"name": "Company2"}
)
self.another_company = self.env["res.company"].create(
{
"name": self.another_company_partner.name,
"partner_id": self.another_company_partner.id,
"currency_id": self.env.ref("base.main_company").currency_id.id,
}
)
self.partner = self.env.ref("base.res_partner_3")
self.chunk_data_contact = [
{
"apply_on_model": "res.partner",
"data_str": '{"name": "Steve Queue Job"}',
"usage": "basic_create",
"model_name": "res.partner",
"record_id": self.partner.id,
},
{
"apply_on_model": "res.partner",
"data_str": '{"name": "Other"}',
"usage": "basic_create",
"model_name": "res.partner",
"record_id": self.partner.id,
},
]
self.chunk_data_bad = {
"apply_on_model": "res.partner",
"data_str": chunk_data_1,
"data_str": "{''(;,),x*}",
"usage": "basic_create",
"model_name": "res.partner",
"record_id": self.partner.id,
}

chunk_data_2 = "{'name': 'New Module Name'}"
chunk_vals_2 = {
"apply_on_model": "ir.module.module",
"data_str": chunk_data_2,
USA = self.env.ref("base.us")
self.chunk_data_state = {
"apply_on_model": "res.country.state",
"data_str": '{"name": "New Stateshire", "code": "NS", "country_id": %d}'
% USA.id,
"usage": "basic_create",
"model_name": "res.country",
"record_id": USA.id,
}
chunk_vals = [chunk_vals_1, chunk_vals_2]
self.env["queue.job.chunk"].create(chunk_vals)

def test_create_chunk(self):
partner_count = self.env["res.partner"].search_count([])
chunk = self.env["queue.job.chunk"].create(self.chunk_data_contact)
new_partner_count = self.env["res.partner"].search_count([])
new_module_count = self.env["ir.module.module"].search_count([])
self.assertEqual(partner_count + 1, new_partner_count)
self.assertEqual(module_count + 1, new_module_count)
self.assertEqual(chunk[0].state, "done")
self.assertEqual(chunk[1].state, "done")
self.assertEqual(partner_count + 2, new_partner_count)

def test_create_chunk_fail_retry(self):
partner_count = self.env["res.partner"].search_count([])
chunk_data = "{':::'Bad json format}"
chunk_vals = {
"apply_on_model": "res.partner",
"data_str": chunk_data,
"usage": "basic_create",
}

chunk = self.env["queue.job.chunk"].create(chunk_vals)
new_partner_count = self.env["res.partner"].search_count([])
self.assertEqual(partner_count, new_partner_count)
# fail with bad data
chunk = self.env["queue.job.chunk"].create(self.chunk_data_bad)
self.assertEqual(chunk.state, "fail")

# retry with correct data
chunk.data_str = "{'name': 'Steve Queue Job'}"
chunk.data_str = '{"name": "Steve Queue Job"}'
chunk.button_retry()
new_partner_count = self.env["res.partner"].search_count([])
self.assertEqual(partner_count + 1, new_partner_count)

def test_create_chunk_without_company_id(self):
chunk = self.env["queue.job.chunk"].create(self.chunk_data_state)
self.assertEqual(chunk.reference_company_id, self.env["res.company"])

def test_create_chunk_with_company_id(self):
company = self.partner.company_id
chunk = self.env["queue.job.chunk"].create(self.chunk_data_contact[0])
self.assertEqual(company, chunk.reference_company_id)

def test_reference(self):
chunk = self.env["queue.job.chunk"].create(self.chunk_data_contact[0])
self.assertEqual(chunk.reference, "res.partner,%i" % self.partner.id)

def test_create_chunk_job(self):
job_count = self.env["queue.job"].search_count([])
self.env = self.env(
context=dict(self.env.context, test_queue_job_no_delay=False)
)
self.env["queue.job.chunk"].create(self.chunk_data_contact[0])
new_job_count = self.env["queue.job"].search_count([])
self.assertEqual(job_count + 1, new_job_count)
4 changes: 2 additions & 2 deletions queue_job_chunk/views/queue_job_chunk.xml
Original file line number Diff line number Diff line change
@@ -15,7 +15,7 @@
<group>
<group>
<field name="data_str"/>
<field name="model_id"/>
<field name="model_name"/>
<field name="record_id"/>
<field name="reference" attrs="{'readonly': 1}"/>
<field name="state" attrs="{'readonly': 1}"/>
@@ -37,7 +37,7 @@
<tree>
<field name="id"/>
<field name="state"/>
<field name="model_id"/>
<field name="model_name"/>
<field name="record_id"/>
</tree>
</field>