lawofcycles commented on code in PR #3320:
URL: https://github.com/apache/iceberg-python/pull/3320#discussion_r3609677737
##########
pyiceberg/table/__init__.py:
##########
@@ -1043,17 +1084,82 @@ def commit_transaction(self) -> Table:
The table with the updates applied.
"""
if len(self._updates) > 0:
- self._requirements +=
(AssertTableUUID(uuid=self.table_metadata.table_uuid),)
- self._table._do_commit( # pylint: disable=W0212
- updates=self._updates,
- requirements=self._requirements,
+ properties = self._table.metadata.properties
+ num_retries: int = property_as_int( # type: ignore # The default
is set with non-None value.
+ properties, TableProperties.COMMIT_NUM_RETRIES,
TableProperties.COMMIT_NUM_RETRIES_DEFAULT
)
+ min_wait_ms: int = property_as_int( # type: ignore # The default
is set with non-None value.
+ properties, TableProperties.COMMIT_MIN_RETRY_WAIT_MS,
TableProperties.COMMIT_MIN_RETRY_WAIT_MS_DEFAULT
+ )
+ max_wait_ms: int = property_as_int( # type: ignore # The default
is set with non-None value.
+ properties, TableProperties.COMMIT_MAX_RETRY_WAIT_MS,
TableProperties.COMMIT_MAX_RETRY_WAIT_MS_DEFAULT
+ )
+ total_timeout_ms: int = property_as_int( # type: ignore # The
default is set with non-None value.
+ properties, TableProperties.COMMIT_TOTAL_RETRY_TIME_MS,
TableProperties.COMMIT_TOTAL_RETRY_TIME_MS_DEFAULT
+ )
+ start_time = time.monotonic()
+ self._requirements +=
(AssertTableUUID(uuid=self.table_metadata.table_uuid),)
+
+ try:
+ for attempt in range(num_retries + 1):
+ try:
+ self._table._do_commit( # pylint: disable=W0212
+ updates=self._updates,
+ requirements=self._requirements,
+ )
+ self._cleanup_uncommitted_manifests()
+ break
+ except CommitFailedException:
+ elapsed_ms = (time.monotonic() - start_time) * 1000
+ if attempt == num_retries or not
self._snapshot_producers or elapsed_ms >= total_timeout_ms:
+ raise
+
+ wait = min(min_wait_ms * (2**attempt), max_wait_ms)
+ jitter = random.uniform(0, 0.1 * wait)
+ logger.warning(
+ "Commit failed due to a concurrent update,
retrying (%s/%s) in %s ms",
+ attempt + 1,
+ num_retries,
+ round(wait + jitter),
+ )
+ time.sleep((wait + jitter) / 1000.0)
+
+ self._table.refresh()
+ self._rebuild_snapshot_updates()
+ except Exception:
Review Comment:
Good catch. The retry loop now only cleans up on CommitFailedException and
ValidationException, which guarantee the commit did not land. Anything else
(unknown outcome, or a failure after the commit already succeeded) is re-raised
without deleting, so files behind a live snapshot are never removed. Added
your test as a regression.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]