70 lines
2.8 KiB
Python
70 lines
2.8 KiB
Python
from app import db
|
|
from datetime import datetime
|
|
import json
|
|
|
|
class MoodleSyncTask(db.Model):
|
|
"""
|
|
Cola persistente de eventos y tareas de sincronización asíncrona hacia Moodle 4.1.
|
|
Garantiza tolerancia a fallos ante caídas o saturación del servidor Moodle,
|
|
incorporando reintentos exponenciales y Dead Letter Queue (DLQ).
|
|
"""
|
|
__tablename__ = 'moodle_sync_tasks'
|
|
|
|
id = db.Column(db.Integer, primary_key=True)
|
|
action = db.Column(db.String(50), nullable=False, index=True) # CREATE_USER, UPDATE_USER, ENROL_USER, UNENROL_USER, ASSIGN_ROLE
|
|
entity_type = db.Column(db.String(50), nullable=False) # user, commission, enrollment
|
|
entity_id = db.Column(db.String(100), nullable=True)
|
|
_payload = db.Column('payload', db.Text, nullable=False) # JSON serializado en Text
|
|
status = db.Column(db.String(20), default='PENDING', index=True) # PENDING, PROCESSING, RETRYING, COMPLETED, FAILED
|
|
attempts = db.Column(db.Integer, default=0)
|
|
max_attempts = db.Column(db.Integer, default=5)
|
|
error_message = db.Column(db.Text, nullable=True)
|
|
next_retry_at = db.Column(db.DateTime, default=datetime.utcnow, index=True)
|
|
created_at = db.Column(db.DateTime, default=datetime.utcnow)
|
|
updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
|
|
|
|
def __init__(self, **kwargs):
|
|
if 'payload' in kwargs:
|
|
raw_payload = kwargs.pop('payload')
|
|
if isinstance(raw_payload, (dict, list)):
|
|
kwargs['_payload'] = json.dumps(raw_payload)
|
|
else:
|
|
kwargs['_payload'] = str(raw_payload or '{}')
|
|
super().__init__(**kwargs)
|
|
|
|
@property
|
|
def payload(self):
|
|
try:
|
|
return json.loads(self._payload) if self._payload else {}
|
|
except Exception:
|
|
return {}
|
|
|
|
@payload.setter
|
|
def payload(self, val):
|
|
if isinstance(val, (dict, list)):
|
|
self._payload = json.dumps(val)
|
|
else:
|
|
self._payload = str(val or '{}')
|
|
|
|
def get_payload_dict(self):
|
|
return self.payload
|
|
|
|
def to_dict(self):
|
|
return {
|
|
'id': self.id,
|
|
'action': self.action,
|
|
'entity_type': self.entity_type,
|
|
'entity_id': self.entity_id,
|
|
'payload': self.payload,
|
|
'status': self.status,
|
|
'attempts': self.attempts,
|
|
'max_attempts': self.max_attempts,
|
|
'error_message': self.error_message,
|
|
'next_retry_at': self.next_retry_at.isoformat() if self.next_retry_at else None,
|
|
'created_at': self.created_at.isoformat() if self.created_at else None,
|
|
'updated_at': self.updated_at.isoformat() if self.updated_at else None
|
|
}
|
|
|
|
def __repr__(self):
|
|
return f'<MoodleSyncTask #{self.id} {self.action} [{self.status}]>'
|