Skip to content

Commit 90ac82b

Browse files
committed
handle the race condition when creating unique run_ids for the SQL database: retry adding a new run until success
1 parent 00a3cf2 commit 90ac82b

1 file changed

Lines changed: 29 additions & 20 deletions

File tree

sacred/observers/sql.py

Lines changed: 29 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import json
55
from threading import Lock
66
import warnings
7+
from sqlalchemy.exc import IntegrityError
78

89
from sacred.commandline_options import cli_option
910
from sacred.observers.base import RunObserver
@@ -76,26 +77,34 @@ def _add_event(
7677
):
7778
from .sql_bases import Base, Experiment, Host, Run
7879

79-
Base.metadata.create_all(self.engine)
80-
sql_exp = Experiment.get_or_create(ex_info, self.session)
81-
sql_host = Host.get_or_create(host_info, self.session)
82-
if _id is None:
83-
i = self.session.query(Run).order_by(Run.id.desc()).first()
84-
_id = 0 if i is None else i.id + 1
85-
86-
self.run = Run(
87-
run_id=str(_id),
88-
config=json.dumps(flatten(config)),
89-
command=command,
90-
priority=meta_info.get("priority", 0),
91-
comment=meta_info.get("comment", ""),
92-
experiment=sql_exp,
93-
host=sql_host,
94-
status=status,
95-
**kwargs,
96-
)
97-
self.session.add(self.run)
98-
self.save()
80+
while True:
81+
Base.metadata.create_all(self.engine)
82+
sql_exp = Experiment.get_or_create(ex_info, self.session)
83+
sql_host = Host.get_or_create(host_info, self.session)
84+
if _id is None:
85+
i = self.session.query(Run).order_by(Run.id.desc()).first()
86+
_id = 0 if i is None else i.id + 1
87+
88+
self.run = Run(
89+
run_id=str(_id),
90+
config=json.dumps(flatten(config)),
91+
command=command,
92+
priority=meta_info.get("priority", 0),
93+
comment=meta_info.get("comment", ""),
94+
experiment=sql_exp,
95+
host=sql_host,
96+
status=status,
97+
**kwargs,
98+
)
99+
self.session.add(self.run)
100+
101+
with self.lock:
102+
try:
103+
self.session.commit()
104+
except IntegrityError:
105+
self.session.rollback()
106+
else:
107+
break
99108
return _id or self.run.run_id
100109

101110
def heartbeat_event(self, info, captured_out, beat_time, result):

0 commit comments

Comments
 (0)