66import random
77import time
88import traceback
9+ from contextlib import contextmanager
910from io import StringIO
1011
1112from psycopg2 import OperationalError , errorcodes
2526DEPENDS_MAX_TRIES_ON_CONCURRENCY_FAILURE = 5
2627
2728
29+ @contextmanager
30+ def _prevent_commit (cr ):
31+ """Context manager to prevent commits on a cursor.
32+
33+ Commiting while the job is not finished would release the job lock, causing
34+ it to be started again by the dead jobs requeuer.
35+ """
36+
37+ def forbidden_commit (* args , ** kwargs ):
38+ raise RuntimeError ("Commit is forbidden in queue jobs" )
39+
40+ original_commit = cr .commit
41+ cr .commit = forbidden_commit
42+ try :
43+ yield
44+ finally :
45+ cr .commit = original_commit
46+
47+
2848class RunJobController (http .Controller ):
2949 def _try_perform_job (self , env , job ):
3050 """Try to perform the job."""
@@ -35,13 +55,15 @@ def _try_perform_job(self, env, job):
3555
3656 _logger .debug ("%s started" , job )
3757
38- job .perform ()
39- # Triggers any stored computed fields before calling 'set_done'
40- # so that will be part of the 'exec_time'
41- env .flush_all ()
42- job .set_done ()
43- job .store ()
44- env .flush_all ()
58+ assert env is job .env # TODO refactor
59+ with _prevent_commit (env .cr ):
60+ job .perform ()
61+ # Triggers any stored computed fields before calling 'set_done'
62+ # so that will be part of the 'exec_time'
63+ env .flush_all ()
64+ job .set_done ()
65+ job .store ()
66+ env .flush_all ()
4567 env .cr .commit ()
4668 _logger .debug ("%s done" , job )
4769
0 commit comments