Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
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
2 changes: 1 addition & 1 deletion .github/workflows/ci-full.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ concurrency:
cancel-in-progress: true

env:
ODOO_ADDONS_PATH: /opt/odoo/odoo/addons,/opt/odoo/odoo/odoo/addons,/mnt/extra-addons/openspp,/mnt/extra-addons/server-ux,/mnt/extra-addons/server-tools,/mnt/extra-addons/queue,/mnt/extra-addons/server-backend,/mnt/extra-addons/rest-framework,/mnt/extra-addons/muk-it
ODOO_ADDONS_PATH: /opt/odoo/odoo/addons,/opt/odoo/odoo/odoo/addons,/mnt/extra-addons/openspp,/mnt/extra-addons/server-ux,/mnt/extra-addons/server-tools,/mnt/extra-addons/queue,/mnt/extra-addons/odoo-job-worker,/mnt/extra-addons/server-backend,/mnt/extra-addons/rest-framework,/mnt/extra-addons/muk-it

jobs:
# ============================================================================
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ concurrency:
cancel-in-progress: true

env:
ODOO_ADDONS_PATH: /opt/odoo/odoo/addons,/opt/odoo/odoo/odoo/addons,/mnt/extra-addons/openspp,/mnt/extra-addons/server-ux,/mnt/extra-addons/server-tools,/mnt/extra-addons/queue,/mnt/extra-addons/server-backend,/mnt/extra-addons/rest-framework,/mnt/extra-addons/muk-it
ODOO_ADDONS_PATH: /opt/odoo/odoo/addons,/opt/odoo/odoo/odoo/addons,/mnt/extra-addons/openspp,/mnt/extra-addons/server-ux,/mnt/extra-addons/server-tools,/mnt/extra-addons/queue,/mnt/extra-addons/odoo-job-worker,/mnt/extra-addons/server-backend,/mnt/extra-addons/rest-framework,/mnt/extra-addons/muk-it

jobs:
# ============================================================================
Expand Down
14 changes: 7 additions & 7 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ repos:
- PyYAML
types: [python]
# Exclude: scripts, tests, migrations, and third-party modules
exclude: ^scripts/|/tests/|migrations/|^(fastapi|queue_job|base_user_role|extendable|extendable_fastapi|endpoint_route_handler)/
exclude: ^scripts/|/tests/|migrations/|^(fastapi|job_worker|base_user_role|extendable|extendable_fastapi|endpoint_route_handler)/
pass_filenames: true
- id: openspp-check-xml-ids
name: "OpenSPP: XML ID naming conventions"
Expand All @@ -189,7 +189,7 @@ repos:
- PyYAML
types: [xml]
# Exclude: scripts, tests, data, demo, and third-party modules
exclude: ^scripts/|/tests/|/data/|/demo/|^(fastapi|queue_job|base_user_role|extendable|extendable_fastapi|endpoint_route_handler)/
exclude: ^scripts/|/tests/|/data/|/demo/|^(fastapi|job_worker|base_user_role|extendable|extendable_fastapi|endpoint_route_handler)/
pass_filenames: true
# Phase 2: ACL check (warning only, runs on all files)
- id: openspp-check-acl
Expand Down Expand Up @@ -222,7 +222,7 @@ repos:
- PyYAML
types: [python]
# Exclude: scripts, tests, migrations, and third-party modules
exclude: ^scripts/|/tests/|migrations/|^(fastapi|queue_job|base_user_role|extendable|extendable_fastapi|endpoint_route_handler)/
exclude: ^scripts/|/tests/|migrations/|^(fastapi|job_worker|base_user_role|extendable|extendable_fastapi|endpoint_route_handler)/
pass_filenames: true
# Phase 3: Logger setup check (warning only)
- id: openspp-check-logger
Expand All @@ -234,7 +234,7 @@ repos:
- PyYAML
types: [python]
# Exclude: scripts, tests, manifests, inits, and third-party modules
exclude: ^scripts/|/tests/|__manifest__|__init__|^(fastapi|queue_job|base_user_role|extendable|extendable_fastapi|endpoint_route_handler)/
exclude: ^scripts/|/tests/|__manifest__|__init__|^(fastapi|job_worker|base_user_role|extendable|extendable_fastapi|endpoint_route_handler)/
pass_filenames: true
# Phase 3: UI patterns check (warning only)
- id: openspp-check-ui
Expand All @@ -248,7 +248,7 @@ repos:
- PyYAML
types: [xml]
# Exclude: scripts, tests, data, demo, and third-party modules
exclude: ^scripts/|/tests/|/data/|/demo/|^(fastapi|queue_job|base_user_role|extendable|extendable_fastapi|endpoint_route_handler)/
exclude: ^scripts/|/tests/|/data/|/demo/|^(fastapi|job_worker|base_user_role|extendable|extendable_fastapi|endpoint_route_handler)/
pass_filenames: true
# Odoo 19 Compatibility Checks
- id: openspp-check-odoo19-python
Expand All @@ -260,7 +260,7 @@ repos:
- PyYAML
types: [python]
# Exclude: scripts, tests, migrations, and third-party modules
exclude: ^scripts/|/tests/|migrations/|^(fastapi|queue_job|base_user_role|extendable|extendable_fastapi|endpoint_route_handler)/
exclude: ^scripts/|/tests/|migrations/|^(fastapi|job_worker|base_user_role|extendable|extendable_fastapi|endpoint_route_handler)/
pass_filenames: true
- id: openspp-check-odoo19-xml
name: "OpenSPP: Odoo 19 compatibility (XML)"
Expand All @@ -272,7 +272,7 @@ repos:
- lxml
types: [xml]
# Exclude: scripts, tests, data, demo, and third-party modules
exclude: ^scripts/|/tests/|/data/|/demo/|^(fastapi|queue_job|base_user_role|extendable|extendable_fastapi|endpoint_route_handler)/
exclude: ^scripts/|/tests/|/data/|/demo/|^(fastapi|job_worker|base_user_role|extendable|extendable_fastapi|endpoint_route_handler)/
pass_filenames: true
# API authentication enforcement
- id: openspp-check-api-auth
Expand Down
2 changes: 1 addition & 1 deletion .semgrep/odoo-security.yml
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,7 @@ rules:
...
message: |
cr.commit() inside a loop can cause partial data states on failure.
Use queue_job for batch operations or handle transactions properly.
Use job_worker for batch operations or handle transactions properly.
severity: WARNING
languages: [python]
metadata:
Expand Down
3 changes: 0 additions & 3 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -89,9 +89,6 @@ services:
ODOO_WORKERS: "0"
ODOO_CRON_THREADS: "0"

# Job queue configuration (defaults to "root:2")
# ODOO_QUEUE_JOB_CHANNELS: "root:4"

# Modules to initialize (configurable via env)
# For E2E: ODOO_INIT_MODULES=spp_mis_demo_v2
# For UI dev: ODOO_INIT_MODULES=spp_base (or your module)
Expand Down
3 changes: 0 additions & 3 deletions docker/.env.production.example
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,6 @@ DB_SSLMODE=prefer
# Number of Odoo workers (rule: (CPU cores * 2) + 1; ~1 worker per 6 concurrent users)
ODOO_WORKERS=2

# Queue job concurrent channels
ODOO_QUEUE_JOB_CHANNELS=root:2

# Memory limits (Docker format: 512M, 1G, 2G, etc.)
ODOO_MEMORY_LIMIT=4G
ODOO_MEMORY_RESERVATION=2G
Expand Down
1 change: 1 addition & 0 deletions docker/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ RUN --mount=type=cache,target=/tmp/downloads,sharing=locked \
download_module "OCA/server-ux" "server-ux"; \
download_module "OCA/server-tools" "server-tools"; \
download_module "OCA/queue" "queue"; \
download_module "OpenSPP/odoo-job-worker" "odoo-job-worker"; \
download_module "OCA/server-backend" "server-backend"; \
download_module "OCA/rest-framework" "rest-framework"; \
download_module "muk-it/odoo-modules" "muk-it"
Expand Down
17 changes: 8 additions & 9 deletions docker/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -190,15 +190,14 @@ docker compose -f docker/docker-compose.production.yml exec clamav clamscan --ve

### Performance

| Variable | Default | Description |
| ------------------------- | ---------- | ------------------------------------- |
| `ODOO_WORKERS` | 2 | Number of worker processes |
| `ODOO_CRON_THREADS` | 1 | Number of cron threads |
| `ODOO_MEMORY_SOFT` | 2147483648 | Soft memory limit per worker (bytes) |
| `ODOO_MEMORY_HARD` | 2684354560 | Hard memory limit per worker (bytes) |
| `ODOO_TIME_CPU` | 600 | CPU time limit per request (seconds) |
| `ODOO_TIME_REAL` | 1200 | Real time limit per request (seconds) |
| `ODOO_QUEUE_JOB_CHANNELS` | root:2 | Concurrent background jobs |
| Variable | Default | Description |
| ------------------- | ---------- | ------------------------------------- |
| `ODOO_WORKERS` | 2 | Number of worker processes |
| `ODOO_CRON_THREADS` | 1 | Number of cron threads |
| `ODOO_MEMORY_SOFT` | 2147483648 | Soft memory limit per worker (bytes) |
| `ODOO_MEMORY_HARD` | 2684354560 | Hard memory limit per worker (bytes) |
| `ODOO_TIME_CPU` | 600 | CPU time limit per request (seconds) |
| `ODOO_TIME_REAL` | 1200 | Real time limit per request (seconds) |

### Logging

Expand Down
13 changes: 3 additions & 10 deletions docker/docker-compose.production.yml
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ services:
memory: ${ODOO_MEMORY_RESERVATION:-2G}

# ==========================================================================
# Queue Worker - Background job processing (OCA/queue_job)
# Queue Worker - Background job processing (job_worker)
# ==========================================================================
queue-worker:
image: ${OPENSPP_IMAGE:-ghcr.io/openspp/openspp:latest}
Expand All @@ -275,17 +275,10 @@ services:
DB_SSLMODE: ${DB_SSLMODE:-prefer}
ODOO_ADMIN_PASSWD: ${ODOO_ADMIN_PASSWD:?ODOO_ADMIN_PASSWD is required}

# Queue worker mode - no HTTP, just process jobs
ODOO_WORKERS: "0"
ODOO_CRON_THREADS: "0"

# Queue job channels (number of concurrent jobs)
QUEUE_JOB_CHANNELS: ${QUEUE_JOB_CHANNELS:-2}

# Logging
LOG_LEVEL: ${LOG_LEVEL:-info}
# Override command to run queue job worker
command: ["odoo", "gevent", "--limit-time-real=0"]
# Run job_worker standalone runner process
command: ["python", "-m", "odoo.addons.job_worker.cli"]

Choose a reason for hiding this comment

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

high

The command for the queue-worker service has been updated to use the job_worker CLI. Verify that this standalone process has access to all necessary environment variables for database connection, as it no longer runs as part of the main Odoo process.

volumes:
- odoo_data:/var/lib/odoo
- odoo_addons:/mnt/extra-addons
Expand Down
4 changes: 0 additions & 4 deletions docker/entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -175,10 +175,6 @@ export ODOO_TIME_REAL="${ODOO_TIME_REAL:-1200}"
export ODOO_LIMIT_REQUEST="${ODOO_LIMIT_REQUEST:-8192}"
[[ -z "$ODOO_LIMIT_REQUEST" || ! "$ODOO_LIMIT_REQUEST" =~ ^[0-9]+$ ]] && export ODOO_LIMIT_REQUEST="8192"

# Queue Job configuration (OCA/queue)
export ODOO_QUEUE_JOB_CHANNELS="${ODOO_QUEUE_JOB_CHANNELS:-root:2}"
[[ -z "$ODOO_QUEUE_JOB_CHANNELS" || ! "$ODOO_QUEUE_JOB_CHANNELS" =~ ^[a-zA-Z_][a-zA-Z0-9_.]*:[0-9]+(,[a-zA-Z_][a-zA-Z0-9_.]*:[0-9]+)*$ ]] && export ODOO_QUEUE_JOB_CHANNELS="root:2"

# Logging
export LOG_LEVEL="${LOG_LEVEL:-info}"
export LOG_HANDLER="${LOG_HANDLER:-:INFO}"
Expand Down
16 changes: 6 additions & 10 deletions docker/odoo.conf.template
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ list_db = ${LIST_DB}
data_dir = /var/lib/odoo

# Addons path - includes Odoo core, OpenSPP, and OCA modules
addons_path = /opt/odoo/odoo/addons,/opt/odoo/odoo/odoo/addons,/mnt/extra-addons/openspp,/mnt/extra-addons/server-ux,/mnt/extra-addons/server-tools,/mnt/extra-addons/queue,/mnt/extra-addons/server-backend,/mnt/extra-addons/rest-framework,/mnt/extra-addons/muk-it
addons_path = /opt/odoo/odoo/addons,/opt/odoo/odoo/odoo/addons,/mnt/extra-addons/openspp,/mnt/extra-addons/server-ux,/mnt/extra-addons/server-tools,/mnt/extra-addons/queue,/mnt/extra-addons/odoo-job-worker,/mnt/extra-addons/server-backend,/mnt/extra-addons/rest-framework,/mnt/extra-addons/muk-it

# =============================================================================
# Security
Expand Down Expand Up @@ -62,8 +62,8 @@ http_enable = True
http_interface = ${HTTP_INTERFACE}
gevent_port = 8072

# Server-wide modules (queue_job for background jobs)
server_wide_modules = base,web,queue_job
# Server-wide modules
server_wide_modules = base,web

# =============================================================================
# Email configuration
Expand Down Expand Up @@ -100,11 +100,7 @@ unaccent = ${UNACCENT}
without_demo = True

# =============================================================================
# Queue Job Configuration (OCA/queue)
# Job Worker Configuration
# =============================================================================
[queue_job]
channels = ${ODOO_QUEUE_JOB_CHANNELS}
jobrunner_db_host = ${DB_HOST}
jobrunner_db_port = ${DB_PORT}
jobrunner_db_user = ${DB_USER}
jobrunner_db_password = ${DB_PASSWORD}
# The job_worker runner runs as a separate process via:
# python -m odoo.addons.job_worker.cli
5 changes: 3 additions & 2 deletions scripts/lint/check_naming.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
# Whitelist for modules that don't follow spp_* naming
MODULE_WHITELIST = {
"base_user_role",
"queue_job",
"job_worker",
"endpoint_route_handler",
"extendable",
"extendable_fastapi",
Expand Down Expand Up @@ -75,13 +75,14 @@
# Third-party models that don't need to follow spp.* naming
# These are from external/third-party modules we depend on
THIRD_PARTY_MODEL_WHITELIST = {
# queue_job module
# job_worker module
"queue.job",
"queue.job.channel",
"queue.job.function",
"queue.job.lock",
"queue.jobs.to.cancelled",
"queue.jobs.to.done",
"queue.limit",
"queue.requeue.job",
# fastapi module
"fastapi.endpoint",
Expand Down
8 changes: 4 additions & 4 deletions scripts/lint/check_performance.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

Detects common performance issues based on docs/principles/performance-scalability.md:
- Offset-based pagination (should use cursor-based)
- cr.commit() in loops (should use queue_job)
- cr.commit() in loops (should use job_worker)
- N+1 query patterns (attribute access in loops without prefetch)

Features:
Expand Down Expand Up @@ -159,10 +159,10 @@ def visit_Call(self, node):
Violation(
file_path=file_path,
line=line_num,
message="cr.commit() inside loop - use queue_job for batch processing instead",
message="cr.commit() inside loop - use job_worker for batch processing instead",
rule_id="performance.commit_in_loop",
severity=severity,
suggestion="Use queue_job to process records asynchronously",
suggestion="Use job_worker to process records asynchronously",
doc_link="docs/principles/performance-scalability.md#batch-processing-pattern",
)
)
Expand Down Expand Up @@ -457,7 +457,7 @@ def main():

Checks:
- Offset pagination: .search(..., offset=...) should use cursor-based
- Commit in loops: cr.commit() in loops should use queue_job
- Commit in loops: cr.commit() in loops should use job_worker
- N+1 queries: Related field access in loops without prefetch

See docs/principles/performance-scalability.md for guidelines.
Expand Down
2 changes: 1 addition & 1 deletion scripts/test_single_module.sh
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ run_tests_docker() {
--entrypoint "" \
test \
/opt/odoo/odoo/odoo-bin \
--addons-path=/opt/odoo/odoo/addons,/opt/odoo/odoo/odoo/addons,/mnt/extra-addons/openspp,/mnt/extra-addons/server-ux,/mnt/extra-addons/server-tools,/mnt/extra-addons/queue,/mnt/extra-addons/server-backend,/mnt/extra-addons/rest-framework,/mnt/extra-addons/muk-it \
--addons-path=/opt/odoo/odoo/addons,/opt/odoo/odoo/odoo/addons,/mnt/extra-addons/openspp,/mnt/extra-addons/server-ux,/mnt/extra-addons/server-tools,/mnt/extra-addons/queue,/mnt/extra-addons/odoo-job-worker,/mnt/extra-addons/server-backend,/mnt/extra-addons/rest-framework,/mnt/extra-addons/muk-it \
-d "$DB_NAME" \
--db_host=db \
--db_port=5432 \
Expand Down
8 changes: 4 additions & 4 deletions spp
Original file line number Diff line number Diff line change
Expand Up @@ -571,17 +571,17 @@ def cmd_start(args):
is_fresh_start = True

# Two-phase initialization for fresh starts with demo modules
# Phase 1: Install queue_job first, then restart so it can listen to job events
# Phase 1: Install job_worker first, then restart so it can listen to job events
if is_fresh_start and demo_modules:
print("\n" + _color("1;34", "Phase 1: Installing queue_job..."))
print("\n" + _color("1;34", "Phase 1: Installing job_worker..."))
phase1_env = env.copy()
phase1_env["ODOO_INIT_MODULES"] = "queue_job"
phase1_env["ODOO_INIT_MODULES"] = "job_worker"
run(docker_compose("up", "-d", profile=profile), env=phase1_env)

if not _wait_for_odoo_ready(profile):
warn("Odoo did not become ready in time, continuing anyway...")

print("Restarting Odoo so queue_job can listen to events...")
print("Restarting Odoo so job_worker can listen to events...")
service = "openspp-dev" if profile == "dev" else "openspp"
run(docker_compose("restart", service, profile=profile))

Expand Down
4 changes: 2 additions & 2 deletions spp_area/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
"spp_base_common",
"spp_user_roles",
"spp_registry",
"queue_job",
"job_worker",
"spp_security",
],
"external_dependencies": {
Expand All @@ -29,7 +29,7 @@
"data": [
"data/area_type_data.xml",
"data/area_tag_data.xml",
"data/queue_job_channel.xml",
"data/queue_limit_data.xml",
"security/privileges.xml",
"security/groups.xml",
"security/ir.model.access.csv",
Expand Down
6 changes: 0 additions & 6 deletions spp_area/data/queue_job_channel.xml

This file was deleted.

7 changes: 7 additions & 0 deletions spp_area/data/queue_limit_data.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<odoo>
<record id="limit_area_import" model="queue.limit">
<field name="name">area_import</field>
<field name="limit">1</field>
<field name="rate_limit">0</field>
</record>
</odoo>
4 changes: 2 additions & 2 deletions spp_area/models/area_import.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@
from odoo import Command, _, api, fields, models
from odoo.exceptions import ValidationError

from odoo.addons.queue_job.delay import group
from odoo.addons.job_worker.delay import group

_logger = logging.getLogger(__name__)
_area_import_raw_model = "spp.area.import.raw"
_res_lang_model = "res.lang"
_area_import_channel = "root.area_import"
_area_import_channel = "area_import"

# Regex patterns for COD column name normalization
# Pattern 1: admin{N}Name_{lang} or admin{N}Pcode (Sri Lanka style)
Expand Down
2 changes: 1 addition & 1 deletion spp_area/tests/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ def _create_import_from_file(cls, file_path):
def setUpClass(cls):
super().setUpClass()
# Set context to avoid job queue delay for faster tests
# Note: queue_job module uses 'queue_job__no_delay' (double underscore)
# Note: job_worker module uses 'queue_job__no_delay' (double underscore)
cls.env = cls.env(
context=dict(
cls.env.context,
Expand Down
2 changes: 1 addition & 1 deletion spp_area/tests/test_area.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class BaseAreaTest(TransactionCase):
def setUpClass(cls):
super().setUpClass()
# Set context to avoid job queue delay for faster tests
# Note: queue_job module uses 'queue_job__no_delay' (double underscore)
# Note: job_worker module uses 'queue_job__no_delay' (double underscore)
cls.env = cls.env(
context=dict(
cls.env.context,
Expand Down
2 changes: 1 addition & 1 deletion spp_area/tests/test_area_tags.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ def setUpClass(cls):
cls.env = cls.env(
context=dict(
cls.env.context,
test_queue_job_no_delay=True,
queue_job__no_delay=True,
)
)

Expand Down
2 changes: 1 addition & 1 deletion spp_area/tests/test_res_partner.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ def setUpClass(cls):
cls.env = cls.env(
context=dict(
cls.env.context,
test_queue_job_no_delay=True,
queue_job__no_delay=True,
)
)
cls._create_test_data()
Expand Down
Loading