Skip to content

Commit 7846f9f

Browse files
implement tri-partite make (fix #1170)
1 parent 8405853 commit 7846f9f

File tree

2 files changed

+34
-3
lines changed

2 files changed

+34
-3
lines changed

datajoint/autopopulate.py

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import signal
1313
import multiprocessing as mp
1414
import contextlib
15+
import deepdiff
1516

1617
# noinspection PyExceptionInherit,PyCallingNonCallable
1718

@@ -309,17 +310,46 @@ def _populate1(
309310
):
310311
return False
311312

312-
self.connection.start_transaction()
313+
# if make is a generator, it transaction can be delayed until the final stage
314+
is_generator = inspect.isgeneratorfunction(make)
315+
if not is_generator:
316+
self.connection.start_transaction()
317+
313318
if key in self.target: # already populated
314-
self.connection.cancel_transaction()
319+
if not is_generator:
320+
self.connection.cancel_transaction()
315321
if jobs is not None:
316322
jobs.complete(self.target.table_name, self._job_key(key))
317323
return False
318324

319325
logger.debug(f"Making {key} -> {self.target.full_table_name}")
320326
self.__class__._allow_insert = True
327+
321328
try:
322-
make(dict(key), **(make_kwargs or {}))
329+
if not is_generator:
330+
make(dict(key), **(make_kwargs or {}))
331+
else:
332+
# tripartite make - transaction is delayed until the final stage
333+
gen = make(dict(key), **(make_kwargs or {}))
334+
fetched_data = next(gen)
335+
fetch_hash = deepdiff.DeepHash(
336+
fetched_data, ignore_iterable_order=False
337+
)[fetched_data]
338+
computed_result = next(gen) # perform the computation
339+
gen = make(dict(key), **(make_kwargs or {})) # restart make
340+
# fetch and insert inside a transaction
341+
self.connnection.start_transaction()
342+
fetched_data = next(gen)
343+
if (
344+
fetch_hash
345+
!= deepdiff.DeepHash(fetched_data, ignore_iterable_order=False)[
346+
fetched_data
347+
]
348+
): # rollback due to referential integrity fail
349+
self.connection.cancel_transaction()
350+
return False
351+
gen.send(computed_result) # insert
352+
323353
except (KeyboardInterrupt, SystemExit, Exception) as error:
324354
try:
325355
self.connection.cancel_transaction()

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ version = "0.14.3"
44
dependencies = [
55
"numpy",
66
"pymysql>=0.7.2",
7+
"deepdiff",
78
"pyparsing",
89
"ipython",
910
"pandas",

0 commit comments

Comments
 (0)