personal memory agent
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Replace Plaud sync timeouts with inactivity-based approach

Remove the 3600s wall-clock subprocess timeout that killed active,
progressing imports (e.g. 26/28 segments done but >1hr elapsed).
The inner import process already has its own 600s inactivity timeout
for stall detection, making the outer backstop redundant.

Convert the overall sync timeout from wall-clock to inactivity-based:
timer now resets after each file completes (success or failure), so
a batch of long imports will process fully as long as each one
eventually finishes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

+39 -50
+39 -50
think/importers/plaud.py
··· 399 399 verbose = logger.isEnabledFor(logging.INFO) 400 400 debug = logger.isEnabledFor(logging.DEBUG) 401 401 402 - # Total sync timeout: 1 hour for all imports combined 402 + # Inactivity-based sync timeout: bail if no file completes 403 + # within this window. The inner import process has its own 404 + # 600s inactivity timeout for stall detection, so this is a 405 + # generous outer safety net. 403 406 sync_timeout = 3600 404 - sync_start = time.monotonic() 407 + last_completed = time.monotonic() 405 408 406 409 for idx, (file_id, info) in enumerate(to_process, 1): 407 - # Check total sync timeout 408 - sync_elapsed = time.monotonic() - sync_start 409 - if sync_elapsed > sync_timeout: 410 + # Check inactivity timeout (time since last file completed) 411 + idle_duration = time.monotonic() - last_completed 412 + if idle_duration > sync_timeout: 410 413 remaining = len(to_process) - idx + 1 411 414 msg = ( 412 - f"Sync timeout after {int(sync_elapsed)}s — " 413 - f"{remaining} files remaining" 415 + f"Sync stalled after {int(idle_duration)}s with no " 416 + f"completed import — {remaining} files remaining" 414 417 ) 415 418 logger.warning(" %s", msg) 416 419 errors.append(msg) ··· 489 492 490 493 logger.info(" Importing %s...", ts) 491 494 import_start = time.monotonic() 492 - import_timeout = 3600 493 495 494 - try: 495 - # In verbose/debug mode, stream subprocess output to terminal 496 + # No subprocess timeout — the inner import process has its 497 + # own inactivity-based timeout (600s) for stall detection. 498 + if verbose: 499 + proc = subprocess.run(import_cmd) 500 + else: 501 + proc = subprocess.run( 502 + import_cmd, 503 + capture_output=True, 504 + text=True, 505 + ) 506 + import_elapsed = int(time.monotonic() - import_start) 507 + last_completed = time.monotonic() 508 + 509 + if proc.returncode == 0: 510 + info["status"] = "imported" 511 + info["import_timestamp"] = ts 512 + info["imported_at"] = dt.datetime.now().isoformat() 513 + downloaded += 1 514 + logger.info(" Imported successfully (%ss)", import_elapsed) 515 + else: 496 516 if verbose: 497 - proc = subprocess.run( 498 - import_cmd, 499 - timeout=import_timeout, 517 + msg = ( 518 + f"{filename}: import failed " 519 + f"(exit code {proc.returncode}, {import_elapsed}s)" 500 520 ) 501 521 else: 502 - proc = subprocess.run( 503 - import_cmd, 504 - capture_output=True, 505 - text=True, 506 - timeout=import_timeout, 522 + stderr_tail = ( 523 + proc.stderr.strip().split("\n")[-1] if proc.stderr else "" 507 524 ) 508 - import_elapsed = int(time.monotonic() - import_start) 509 - if proc.returncode == 0: 510 - info["status"] = "imported" 511 - info["import_timestamp"] = ts 512 - info["imported_at"] = dt.datetime.now().isoformat() 513 - downloaded += 1 514 - logger.info(" Imported successfully (%ss)", import_elapsed) 515 - else: 516 - if verbose: 517 - # User already saw subprocess output 518 - msg = ( 519 - f"{filename}: import failed " 520 - f"(exit code {proc.returncode}, {import_elapsed}s)" 521 - ) 522 - else: 523 - stderr_tail = ( 524 - proc.stderr.strip().split("\n")[-1] 525 - if proc.stderr 526 - else "" 527 - ) 528 - msg = f"{filename}: import failed — {stderr_tail}" 529 - logger.warning( 530 - "Import failed for %s: %s", filename, proc.stderr 531 - ) 532 - logger.warning(" FAILED — %s", msg) 533 - errors.append(msg) 534 - except subprocess.TimeoutExpired: 535 - import_elapsed = int(time.monotonic() - import_start) 536 - msg = ( 537 - f"{filename}: import subprocess timed out " 538 - f"after {import_timeout}s (elapsed {import_elapsed}s)" 539 - ) 525 + msg = f"{filename}: import failed — {stderr_tail}" 526 + logger.warning( 527 + "Import failed for %s: %s", filename, proc.stderr 528 + ) 540 529 logger.warning(" FAILED — %s", msg) 541 530 errors.append(msg) 542 531