-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsync_utils.py
More file actions
165 lines (138 loc) · 7.88 KB
/
sync_utils.py
File metadata and controls
165 lines (138 loc) · 7.88 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
import os
import subprocess
import time
from logging_utils import log
from config import Config
class FileAccessError(Exception):
pass
def verificar_archivo(file_path):
"""Verifica que un archivo esté completamente disponible"""
try:
# Obtener tamaño total del archivo
size = os.path.getsize(file_path)
if size == 0:
log(f"WARNING: Archivo vacío detectado: {os.path.basename(file_path)}")
return False
# Leer el inicio del archivo
with open(file_path, "rb") as f:
f.seek(0)
inicio = f.read(Config.SYNC_CONFIG['FILE_CHECK_BLOCK_SIZE'])
# Leer el final del archivo si es lo suficientemente grande
if size > Config.SYNC_CONFIG['MIN_FILE_SIZE_FOR_TAIL_CHECK']:
f.seek(-Config.SYNC_CONFIG['FILE_CHECK_BLOCK_SIZE'], 2)
final = f.read()
return len(inicio) > 0
except (IOError, OSError) as e:
log(f"ERROR verificando archivo {os.path.basename(file_path)}: {e}")
return False
def forzar_sync_powershell():
"""Estimula la sincronización de OneDrive usando PowerShell"""
try:
comando = r'Start-Process "$(Join-Path $env:LOCALAPPDATA \\Microsoft\\OneDrive\\OneDrive.exe)" "/sync"'
subprocess.run(["powershell", "-Command", comando],
capture_output=True,
text=True,
creationflags=subprocess.CREATE_NO_WINDOW)
log("Sincronización de OneDrive estimulada vía PowerShell")
except Exception as e:
log(f"ERROR al estimular sincronización de OneDrive: {e}")
def estimular_onedrive(files, video_dir):
"""
FUNCION CRITICA:
Estimula la sincronización de OneDrive mediante 'toque' de archivos y comandos PowerShell.
Esta función implementa una estrategia de dos niveles para forzar la sincronización:
1. "Toca" archivos individuales actualizando sus timestamps (marca como modificados)
2. Ejecuta comandos PowerShell para estimular OneDrive cuando es necesario
Nota: no se ha detectado que dichos comandos requieran permisos de administrador
Args:
files (list): Lista de nombres de archivos específicos a procesar
video_dir (str): Directorio base donde se encuentran los archivos
Returns:
bool: True si todos los archivos están sincronizados correctamente,
False si hay archivos pendientes que requieren atención
Proceso detallado:
- Verifica la integridad de cada archivo individualmente
- "Toca" archivos válidos para marcarlos como activos en OneDrive
- Mantiene lista de archivos problemáticos para reporte
- Fuerza sincronización inmediata si hay archivos pendientes
- Implementa sincronización periódica basada en timestamps
"""
# ========================================================================
# FASE 1: INICIALIZACIÓN Y PREPARACIÓN
# ========================================================================
# Contenedor para archivos que necesitan atención especial
# (archivos incompletos, inaccesibles o corruptos)
archivos_pendientes = []
# ========================================================================
# FASE 2: PROCESAMIENTO INDIVIDUAL DE ARCHIVOS
# ========================================================================
for f in files:
file_path = os.path.join(video_dir, f)
try:
# ----------------------------------------------------------------
# PASO 2.1: Verificación básica de acceso al archivo
# ----------------------------------------------------------------
# os.stat() falla inmediatamente si:
# - El archivo no existe
# - No hay permisos de lectura
# - El archivo está bloqueado por otro proceso
os.stat(file_path)
# ----------------------------------------------------------------
# PASO 2.2: Verificación de integridad del archivo
# ----------------------------------------------------------------
# verificar_archivo() realiza verificaciones profundas:
# - Tamaño del archivo > 0 bytes
# - Lectura exitosa del bloque inicial (detecta corrupción temprana)
# - Para archivos grandes: lectura del bloque final (detecta transferencias incompletas)
if not verificar_archivo(file_path):
# Archivo incompleto o corrupto - marcar para sincronización especial
archivos_pendientes.append(f)
continue # Saltar al siguiente archivo sin procesamiento adicional
# ----------------------------------------------------------------
# PASO 2.3: "Tocar" archivo para estimular OneDrive
# ----------------------------------------------------------------
# Actualizar timestamp de acceso y modificación al momento actual
# Esto hace que OneDrive detecte el archivo como "recientemente modificado"
# y lo priorice en su cola de sincronización
current_time = time.time()
os.utime(file_path, (current_time, current_time))
# Nota: os.utime(path, (access_time, modification_time))
except Exception as e:
# ----------------------------------------------------------------
# MANEJO DE ERRORES DE ACCESO
# ----------------------------------------------------------------
# Posibles causas de excepción:
# - FileNotFoundError: Archivo eliminado durante procesamiento
# - PermissionError: Sin permisos de acceso/modificación
# - OSError: Problemas de E/O del sistema de archivos
log(f"ERROR accediendo a {f}: {e}")
archivos_pendientes.append(f)
# ========================================================================
# FASE 3: DECISIÓN DE SINCRONIZACIÓN BASADA EN RESULTADOS
# ========================================================================
# ----------------------------------------------------------------
# ESCENARIO A: HAY ARCHIVOS PROBLEMÁTICOS
# ----------------------------------------------------------------
if archivos_pendientes:
# Estrategia: Sincronización inmediata y agresiva
# OneDrive necesita ser "despertado" para procesar archivos problemáticos
# que pueden estar en estado de sincronización parcial o fallida
forzar_sync_powershell()
return False # Indica que hay problemas pendientes de resolución
# ----------------------------------------------------------------
# ESCENARIO B: TODOS LOS ARCHIVOS ESTÁN BIEN
# ----------------------------------------------------------------
# Implementar sincronización periódica preventiva
# Basada en el archivo más recientemente modificado del conjunto
# Encontrar el timestamp de modificación más reciente entre todos los archivos
# max() con default=0 maneja el caso edge de lista vacía
ultimo_archivo = max([os.path.getmtime(os.path.join(video_dir, f)) for f in files], default=0)
# Calcular tiempo transcurrido desde la última modificación
tiempo_transcurrido = time.time() - ultimo_archivo
# Si ha pasado suficiente tiempo (configurado en REFRESH_CYCLE_DELAY de Config.py),
# ejecutar sincronización preventiva para mantener OneDrive activo
# Esto previene que OneDrive entre en modo "dormido" por inactividad prolongada
if tiempo_transcurrido > Config.SYNC_CONFIG['REFRESH_CYCLE_DELAY']:
# Sincronización periódica: menos agresiva que la de archivos problemáticos
forzar_sync_powershell()
return True # Todos los archivos procesados exitosamente