@danhachuel/thunderbolt 0.7.15 → 0.7.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -450,6 +450,7 @@ _LOCK_TIMEOUT_SECONDS = 30.0
450
450
  _LOCK_POLL_SECONDS = 0.05
451
451
  _LOCK_STALE_SECONDS = 120
452
452
  _PROTECTED_STATE_FILES = {"channels.json", "tasks.json", "batches.json", "queues.json", "uploads.json"}
453
+ _REPLACE_RETRY_DELAYS_SECONDS = (0.05, 0.1, 0.2, 0.4, 0.8, 1.0, 1.0, 1.0)
453
454
 
454
455
 
455
456
  class StorageIntegrityError(RuntimeError):
@@ -533,10 +534,31 @@ def _atomic_write_unlocked(path: Path, data: Any) -> None:
533
534
  handle.write("\n")
534
535
  handle.flush()
535
536
  os.fsync(handle.fileno())
536
- os.replace(temp_name, path)
537
+ replace_error: PermissionError | None = None
538
+ for delay in (0.0, *_REPLACE_RETRY_DELAYS_SECONDS):
539
+ if delay:
540
+ time.sleep(delay)
541
+ try:
542
+ os.replace(temp_name, path)
543
+ replace_error = None
544
+ break
545
+ except PermissionError as exc:
546
+ # Windows can briefly keep the destination open while Streamlit,
547
+ # an antivirus scanner, or the previous reader releases it.
548
+ # Keep the atomic replace, but give that transient handle time
549
+ # to disappear instead of failing the pipeline at its next
550
+ # progress checkpoint.
551
+ replace_error = exc
552
+ if replace_error is not None:
553
+ raise replace_error
537
554
  finally:
538
- if os.path.exists(temp_name):
539
- os.unlink(temp_name)
555
+ try:
556
+ if os.path.exists(temp_name):
557
+ os.unlink(temp_name)
558
+ except OSError:
559
+ # A scanner may also briefly hold the temporary file. The next
560
+ # write can clean it up; never hide the replace error with cleanup.
561
+ pass
540
562
 
541
563
 
542
564
  def atomic_write(path: Path, data: Any) -> None:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@danhachuel/thunderbolt",
3
- "version": "0.7.15",
3
+ "version": "0.7.16",
4
4
  "description": "Thunderbolt — interface local para operação de canais faceless e motor MoneyPrinterTurbo",
5
5
  "license": "MIT",
6
6
  "main": "scripts/cli.mjs",