Skip to content
Closed
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
11 changes: 11 additions & 0 deletions queue_job/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ Features:
description, number of retries
* Related Actions: link an action on the job view, such as open the record
concerned by the job
* Error Handler: trigger a method when job fails, such as calling a webhook

**Table of contents**

Expand Down Expand Up @@ -418,6 +419,15 @@ Based on this configuration, we can tell that:
* retries 10 to 15 postponed 30 seconds later
* all subsequent retries postponed 5 minutes later

**Job function: Error Handler**

The *Error Handler* is a method executed whenever the job fails

It's configured similarly to Related Action




**Job Context**

The context of the recordset of the job, or any recordset passed in arguments of
Expand Down Expand Up @@ -676,6 +686,7 @@ Contributors
* Souheil Bejaoui <[email protected]>
* Eric Antones <[email protected]>
* Simone Orsi <[email protected]>
* Tris Doan <[email protected]>

Maintainers
~~~~~~~~~~~
Expand Down
9 changes: 8 additions & 1 deletion queue_job/controllers/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,14 @@

_logger.debug("%s started", job)

job.perform()
try:
job.perform()
except Exception as exc:
with registry(job.env.cr.dbname).cursor() as new_cr:
job.env = job.env(cr=new_cr)
job.error_handler(exc)
raise

Check warning on line 44 in queue_job/controllers/main.py

View check run for this annotation

Codecov / codecov/patch

queue_job/controllers/main.py#L38-L44

Added lines #L38 - L44 were not covered by tests

# Triggers any stored computed fields before calling 'set_done'
# so that will be part of the 'exec_time'
env.flush_all()
Expand Down
18 changes: 18 additions & 0 deletions queue_job/job.py
Original file line number Diff line number Diff line change
Expand Up @@ -955,6 +955,24 @@
action_kwargs = self.job_config.related_action_kwargs
return action(**action_kwargs)

def error_handler(self, exc):
record = self.db_record()
funcname = self.job_config.error_handler_func_name

Check warning on line 960 in queue_job/job.py

View check run for this annotation

Codecov / codecov/patch

queue_job/job.py#L959-L960

Added lines #L959 - L960 were not covered by tests
if not self.job_config.error_handler_enable or not funcname:
return None

Check warning on line 962 in queue_job/job.py

View check run for this annotation

Codecov / codecov/patch

queue_job/job.py#L962

Added line #L962 was not covered by tests

if not isinstance(funcname, str):
raise ValueError(

Check warning on line 965 in queue_job/job.py

View check run for this annotation

Codecov / codecov/patch

queue_job/job.py#L965

Added line #L965 was not covered by tests
"error_handler must be the name of the method on queue.job as string"
)
action = getattr(record, funcname)
_logger.info("Job %s fails due to %s, execute %s", self.uuid, exc, action)
action_kwargs = {"job": self, **self.job_config.error_handler_kwargs}
try:
return action(**action_kwargs)
except Exception as exc:
_logger.warning("Error handler failed: %s", exc)

Check warning on line 974 in queue_job/job.py

View check run for this annotation

Codecov / codecov/patch

queue_job/job.py#L968-L974

Added lines #L968 - L974 were not covered by tests


def _is_model_method(func):
return inspect.ismethod(func) and isinstance(
Expand Down
44 changes: 44 additions & 0 deletions queue_job/models/queue_job_function.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@
"related_action_enable "
"related_action_func_name "
"related_action_kwargs "
"error_handler_enable "
"error_handler_func_name "
"error_handler_kwargs "
"job_function_id ",
)

Expand Down Expand Up @@ -79,6 +82,33 @@
"enable, func_name, kwargs.\n"
"See the module description for details.",
)
error_handler = JobSerialized(base_type=dict)
edit_error_handler = fields.Text(
string="Error Handler",
compute="_compute_edit_error_handler",
inverse="_inverse_edit_error_handler",
help="The handler is executed when the job fails. "
"Configured as a dictionary with optional keys: "
"enable, func_name, kwargs.\n"
"See the module description for details.",
)

@api.depends("error_handler")
def _compute_edit_error_handler(self):
for record in self:
record.edit_error_handler = str(record.error_handler)

Check warning on line 99 in queue_job/models/queue_job_function.py

View check run for this annotation

Codecov / codecov/patch

queue_job/models/queue_job_function.py#L99

Added line #L99 was not covered by tests

def _inverse_edit_error_handler(self):
try:
edited = (self.edit_error_handler or "").strip()

Check warning on line 103 in queue_job/models/queue_job_function.py

View check run for this annotation

Codecov / codecov/patch

queue_job/models/queue_job_function.py#L102-L103

Added lines #L102 - L103 were not covered by tests
if edited:
self.error_handler = ast.literal_eval(edited)

Check warning on line 105 in queue_job/models/queue_job_function.py

View check run for this annotation

Codecov / codecov/patch

queue_job/models/queue_job_function.py#L105

Added line #L105 was not covered by tests
else:
self.error_handler = {}
except (ValueError, TypeError, SyntaxError) as ex:
raise exceptions.UserError(

Check warning on line 109 in queue_job/models/queue_job_function.py

View check run for this annotation

Codecov / codecov/patch

queue_job/models/queue_job_function.py#L107-L109

Added lines #L107 - L109 were not covered by tests
self._error_handler_format_error_message()
) from ex

@api.depends("model_id.model", "method")
def _compute_name(self):
Expand Down Expand Up @@ -149,6 +179,9 @@
related_action_func_name=None,
related_action_kwargs={},
job_function_id=None,
error_handler_enable=True,
error_handler_func_name=None,
error_handler_kwargs={},
)

def _parse_retry_pattern(self):
Expand Down Expand Up @@ -184,6 +217,9 @@
related_action_func_name=config.related_action.get("func_name"),
related_action_kwargs=config.related_action.get("kwargs", {}),
job_function_id=config.id,
error_handler_enable=config.error_handler.get("enable", True),
error_handler_func_name=config.error_handler.get("func_name"),
error_handler_kwargs=config.error_handler.get("kwargs", {}),
)

def _retry_pattern_format_error_message(self):
Expand Down Expand Up @@ -226,6 +262,14 @@
' "kwargs" {{"limit": 10}}}}'
).format(self.name)

def _error_handler_format_error_message(self):
return _(

Check warning on line 266 in queue_job/models/queue_job_function.py

View check run for this annotation

Codecov / codecov/patch

queue_job/models/queue_job_function.py#L266

Added line #L266 was not covered by tests
"Unexpected format of Error Handler for {}.\n"
"Example of valid format:\n"
'{{"enable": True, "func_name": "_call_webhook",'
' "kwargs" {"webhook_url": "XXX","payload": {"text":"Hello World!"}}}}'
).format(self.name)

@api.constrains("related_action")
def _check_related_action(self):
valid_keys = ("enable", "func_name", "kwargs")
Expand Down
1 change: 1 addition & 0 deletions queue_job/readme/CONTRIBUTORS.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@
* Souheil Bejaoui <[email protected]>
* Eric Antones <[email protected]>
* Simone Orsi <[email protected]>
* Tris Doan <[email protected]>
1 change: 1 addition & 0 deletions queue_job/readme/DESCRIPTION.rst
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,4 @@ Features:
description, number of retries
* Related Actions: link an action on the job view, such as open the record
concerned by the job
* Error Handler: trigger a method when job fails, such as calling a webhook
9 changes: 9 additions & 0 deletions queue_job/readme/USAGE.rst
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,15 @@ Based on this configuration, we can tell that:
* retries 10 to 15 postponed 30 seconds later
* all subsequent retries postponed 5 minutes later

**Job function: Error Handler**

The *Error Handler* is a method executed whenever the job fails

It's configured similarly to Related Action




**Job Context**

The context of the recordset of the job, or any recordset passed in arguments of
Expand Down
Loading