Skip to content

[MIG] queue_job: Migration to 20.0 - #1

Merged
juppe merged 1233 commits into
20.0from
20.0-mig-queue_job
Oct 22, 2026
Merged

juppe merged 1233 commits into
20.0from
20.0-mig-queue_job

Conversation

@juppe

@juppe juppe commented Sep 25, 2026

Copy link
Copy Markdown
  • Imports the queue_job history from 19.0 onto the orphan 20.0 branch with the OCA format-patch method, followed by the pre-commit auto fixes and the migration commit.
  • Access rights and the multi-company record rule move to security/ir.access.csv, as ir.rule and ir.model.access no longer exist as separate models.
  • Retryable concurrency errors are matched with odoo.sql_db.PG_CONCURRENCY_EXCEPTIONS_TO_RETRY (exception classes) instead of the removed pgcode list.
  • Jobrunner database discovery uses odoo.modules.db.list_dbs, environments are cleared through env.transaction.clear(), and the job function cache uses api.ormcache with transaction.invalidate_ormcache().
  • The job dependency graph widget is rewritten for Owl 3 (signal.ref() root reference with onMounted/onWillUnmount).
  • The requests dependency is declared in the manifest external dependencies; the old migration scripts are dropped.

T9750
https://odoo.ahkio.com/odoo/project.task/9750

guewen and others added 30 commits September 25, 2026 12:47
Jobs waiting that their dependencies are executed cannot be requeued.
They have to keep waiting their turn.
* mock_jobs context manager with assert methods to check enqueued jobs
* jobs are not stored in database, yet they can be inspected and performed
  during the test
* the context manager works with graphs enqueued by delayable and with with_delay()
* direct execution of jobs works with graphs by executing them synchronously
  following their topological sort
The previous implementation was incomplete, as it was setting
the graph_uuid when `Job.add_depends()` was called. It had the
advantage of being correct when (for e.g. a test) manually created
a Job and called `add_depends()`, but it could not work when in
some situations involving a group where one of the job has no job
depending on it.

Also, remove ``Job.add_reverse_depends()`` which is not used.
* Fix a js bug when there is no graph.
* Use a single read group for multiple jobs
When showing large graphs, like 300 jobs (not really a real life case maybe),
the graph takes a dozen of seconds to render. Disabling the stabilization
helps a lot.
* Renaming the TestXxx models in test_queue_job is because of pytest that
  complains, confusing them for test classes
* logger.warn is deprecated in favor of logger.warning
* Add invalidation of cache in SQL update that enqueue dependent jobs
* Flush in a test, the same is done currently in the controller
* Weird one: we can no longer compare the bound methods of the models,
  compare their __func__ which is equal.
The assert fails to show the method's details if we store the __func__ in JobCall.
Anyway, it was hackish to change the content of "method".
The fact that mocks are used is an implementation detail, and is actually
hidden to the end user of the test API.
on_done() is maybe a better choice, it is less ambiguous than then() (clearer
on the fact it happens on done()) and done() (less confusion with set_done()).
I'll do the renaming soon, unless you have other suggestions.

Ref: OCA#154 (comment)
Updated by "Update PO files to match POT (msgmerge)" hook in Weblate.

Translation: queue-15.0/queue-15.0-queue_job
Translate-URL: https://translation.odoo-community.org/projects/queue-15-0/queue-15-0-queue_job/
This forward port takes all the changes from 15.0 not yet into 16.0
up to OCA@173b6ca

This FP contains the new queue dependencies functionality.
The dedicated widget used to display the dependecies graph on the job
form is also migrated to owl
fsmw and others added 25 commits September 25, 2026 12:47
The module uses openupgradelib in migration scripts but it was not
declared in external_dependencies, causing installation failures
when openupgradelib is not already installed.

Fixes OCA#809
Currently translated at 100.0% (156 of 156 strings)

Translation: queue-19.0/queue-19.0-queue_job
Translate-URL: https://translation.odoo-community.org/projects/queue-19-0/queue-19-0-queue_job/it/
runjob is declared auth="none", so _auth_method_none pins request.env
and transaction.default_env to a uid=None env. `env = http.request.env(
user=SUPERUSER_ID)` only creates a local superuser env, leaving the
default_env as uid=None. Any flush that goes through
Transaction.flush() -> default_env.flush_all() then recomputes stored
fields as uid=None and fails on anything dereferencing self.env.user.

`http.request.update_env(user=SUPERUSER_ID)` additionally sets
transaction.default_env to the superuser env.

Closes OCA#922
Adds test_run_job_controller_http.py covering OCA#922:
- test_runjob_pins_default_env_to_superuser asserts that when
  _acquire_job is entered, env.transaction.default_env.uid is
  SUPERUSER_ID -- the state a job would inherit at perform time.
- test_runjob_without_updating_default_env_leaves_uid_none patches
  Request.update_env to a no-op and verifies default_env.uid stays
  None, isolating default_env repointing as the load-bearing
  behavior of runjob.

Tests use HttpCase so _auth_method_none, session handling, and
update_env run for real. _acquire_job is patched to return None so
the endpoint exits cleanly without performing DB work (its internal
commit is forbidden inside tests).
Co-authored-by: Guewen Baconnier <guewen@baconnier.me>
Currently translated at 4.4% (7 of 156 strings)

Translation: queue-19.0/queue-19.0-queue_job
Translate-URL: https://translation.odoo-community.org/projects/queue-19-0/queue-19-0-queue_job/fa/
Allows to execute a model function when the job fails and will
not be retried.

[REF] queue_job: Move on fail definition to job function

Rename on_fail_hook to on_fail
Updated by "Update PO files to match POT (msgmerge)" hook in Weblate.

Translation: queue-19.0/queue-19.0-queue_job
Translate-URL: https://translation.odoo-community.org/projects/queue-19-0/queue-19-0-queue_job/
Job.on_fail_method_name was only set as an instance attribute when
the job function configured on_fail_method, so on_fail() raised
AttributeError for every job that didn't opt into it.
Currently translated at 100.0% (158 of 158 strings)

Translation: queue-19.0/queue-19.0-queue_job
Translate-URL: https://translation.odoo-community.org/projects/queue-19-0/queue-19-0-queue_job/it/
Logging the usage of queue_job__no_delay makes sense only in 'production mode'.
We have tons of tests explicitly bypassing jobs and that generates a lot of useless entries in the logs.
Copilot AI lite review requested due to automatic review settings September 25, 2026 12:14

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Unresolved critical and moderate findings remain in delayable graph handling, retry normalization, caching, and the Owl widget.

Get a fresh assessment by requesting another Copilot review.

Review effort: Lite
Findings: 3 High severity · 2 Medium severity · 1 Low severity

Open (6)
What changed in this PR

Migrates queue_job from Odoo 19.0 to 20.0, updating framework APIs, jobrunner behavior, security, Owl UI, tests, and documentation.

Changes:

  • Updates database, transaction, cache, and concurrency integrations.
  • Migrates models, views, wizards, security rules, and jobrunner components.
  • Rewrites the dependency graph widget for Owl 3 and adds the requests dependency.
File Summary
queue_job/​wizards/​queue_requeue_job.py Requeue wizard
queue_job/​wizards/​queue_requeue_job_views.xml Requeue wizard view
queue_job/​wizards/​queue_jobs_to_done.py Set-jobs-done wizard
queue_job/​wizards/​queue_jobs_to_done_views.xml Set-jobs-done wizard view
queue_job/​wizards/​queue_jobs_to_cancelled.py Cancellation wizard
queue_job/​wizards/​queue_jobs_to_cancelled_views.xml Cancellation wizard view
queue_job/​wizards/​__init__.py Wizard registration
queue_job/​views/​queue_job_views.xml Job views and actions
queue_job/​views/​queue_job_menus.xml Job menus
queue_job/​views/​queue_job_function_views.xml Function views
queue_job/​views/​queue_job_channel_views.xml Channel views
queue_job/​utils.py No-delay utility. Nit (2): docstring begins with “Retrun”.
queue_job/​tests/​test_wizards.py Wizard tests
queue_job/​tests/​test_runner_runner.py Runner tests
queue_job/​tests/​test_runner_channels.py Channel runner tests
queue_job/​tests/​test_run_rob_controller.py Moderate (1): assertions after assertRaises are unreachable.
queue_job/​tests/​test_run_job_controller_http.py HTTP controller tests
queue_job/​tests/​test_queue_job_protected_write.py Protected-write tests
queue_job/​tests/​test_model_job_function.py Function model tests
queue_job/​tests/​test_model_job_channel.py Channel model tests
queue_job/​tests/​test_json_field.py JSON field tests
queue_job/​tests/​test_delayable.py Delayable tests
queue_job/​tests/​test_delayable_split.py Split tests
queue_job/​tests/​common.py Shared test utilities
queue_job/​tests/​__init__.py Test registration
queue_job/​static/​src/​views/​fields/​job_direct_graph/​job_direct_graph.xml Graph template. Moderate (3): id="props.id" creates duplicate literal IDs.
queue_job/​static/​src/​views/​fields/​job_direct_graph/​job_direct_graph.scss Graph styling
queue_job/​static/​src/​views/​fields/​job_direct_graph/​job_direct_graph.esm.js Owl graph widget. Moderate (2): network is not destroyed on teardown. Critical (3): props data is mutated when replacing titles with DOM elements.
queue_job/​static/​description/​icon.svg Module icon
queue_job/​security/​security.xml Security groups
queue_job/​security/​ir.access.csv Access rules
queue_job/​readme/​USAGE.md Usage documentation. Nit (1): “exceute” typo. Nit (1): “Enqueing” typo.
queue_job/​readme/​ROADMAP.md Roadmap documentation
queue_job/​readme/​INSTALL.md Installation documentation
queue_job/​readme/​HISTORY.md History documentation
queue_job/​readme/​DESCRIPTION.md Module description
queue_job/​readme/​CONTRIBUTORS.md Contributor list
queue_job/​readme/​CONTEXT.md Usage context
queue_job/​readme/​CONFIGURE.md Configuration documentation
queue_job/​README.rst Generated module README
queue_job/​pyproject.toml Build configuration
queue_job/​post_init_hook.py Queue notification trigger
queue_job/​models/​queue_job.py Queue job model
queue_job/​models/​queue_job_lock.py Job locking model
queue_job/​models/​queue_job_function.py Job function configuration. Critical (1): scalar retry values can become character tuples. Moderate (1): TypeError is not handled for invalid retry values. Nit (1): repeated “of” in help text.
queue_job/​models/​queue_job_channel.py Channel model. Moderate (1): channel changes do not invalidate the cached configuration.
queue_job/​models/​ir_model_fields.py Serialized field registration
queue_job/​models/​base.py Delayable model APIs
queue_job/​models/​__init__.py Model registration
queue_job/​jobrunner/​runner.py Jobrunner implementation
queue_job/​jobrunner/​__main__.py Jobrunner entry point
queue_job/​jobrunner/​__init__.py Runner integration
queue_job/​fields.py Job serialization fields
queue_job/​exception.py Queue job exceptions
queue_job/​delay.py Delayable graph implementation. Critical (4): return inside the loop leaves subsequent identity-keyed jobs unsaved; also present at line 540.
queue_job/​data/​queue_job_function_data.xml Test job configuration
queue_job/​data/​queue_data.xml Queue data and cron
queue_job/​controllers/​main.py Job execution controllers
queue_job/​controllers/​__init__.py Controller registration
queue_job/​__manifest__.py Module metadata and dependencies
queue_job/​__init__.py Module initialization

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread queue_job/delay.py
Comment on lines +286 to +288
for vertex, existing in existing_mapping.items():
vertex._generated_job = existing
return
Comment on lines +175 to +180
for try_count, postpone_value in self.retry_pattern.items():
if isinstance(postpone_value, int):
retry_pattern[int(try_count)] = postpone_value
else:
retry_pattern[int(try_count)] = tuple(postpone_value)
except ValueError:
Comment on lines +69 to +70
nodes = nodes.map((node) => {
node.title = this.htmlTitle(node.title || "");
Comment on lines +31 to +34
onWillUnmount(() => {
if (this.network) {
this.$el.innerHTML = "";
}
<templates xml:space="preserve">

<t t-name="queue.JobDirectGraph">
<div id="props.id" t-ref="this.rootRef" class="root_vis" />
Comment thread queue_job/utils.py


def must_run_without_delay(env):
"""Retrun true if jobs have to run immediately.
@juppe
juppe merged commit 24a0007 into 20.0 Oct 22, 2026
2 of 5 checks passed
@juppe
juppe deleted the 20.0-mig-queue_job branch October 22, 2026 08:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.