@@ -0,0 +1,118 @@
|
||||
from sqlalchemy import Boolean, Column, DateTime, Integer, String, Text, UniqueConstraint
|
||||
|
||||
from app import db
|
||||
from .base import SoftDeleteMixin, TimestampMixin, default_uuid
|
||||
|
||||
|
||||
class SyncMetadata(db.Model, TimestampMixin, SoftDeleteMixin):
|
||||
"""Метаданные синхронизации (паспорт узла)."""
|
||||
|
||||
__tablename__ = "sync_metadata"
|
||||
|
||||
id = Column(String(36), primary_key=True, default=default_uuid)
|
||||
node_id = Column(String(36), nullable=False, unique=True)
|
||||
node_type = Column(String(20), nullable=False) # 'server' | 'client'
|
||||
node_name = Column(String(100), nullable=True)
|
||||
node_status = Column(String(20), default="active")
|
||||
last_heartbeat = Column(DateTime, nullable=True)
|
||||
last_sync = Column(DateTime, nullable=True)
|
||||
sync_status = Column(String(20), default="idle")
|
||||
is_enabled = Column(Boolean, default=True)
|
||||
|
||||
|
||||
class SyncClient(db.Model, TimestampMixin, SoftDeleteMixin):
|
||||
"""Реестр клиентов синхронизации."""
|
||||
|
||||
__tablename__ = "sync_clients"
|
||||
|
||||
id = Column(String(36), primary_key=True, default=default_uuid)
|
||||
node_id = Column(String(36), nullable=False, unique=True)
|
||||
client_name = Column(String(100), nullable=False)
|
||||
ip_address = Column(String(45), nullable=True)
|
||||
port = Column(Integer, default=80)
|
||||
status = Column(String(20), default="active")
|
||||
last_seen = Column(DateTime, nullable=True)
|
||||
total_syncs = Column(Integer, default=0)
|
||||
last_error = Column(Text, nullable=True)
|
||||
is_enabled = Column(Boolean, default=True)
|
||||
personal_snapshot_completed_at = Column(DateTime, nullable=True)
|
||||
personal_snapshot_cursor = Column(Integer, nullable=False, default=0)
|
||||
|
||||
|
||||
class SyncEngineState(db.Model, TimestampMixin, SoftDeleteMixin):
|
||||
"""Durable flags/cursors for sync engine bootstrap."""
|
||||
|
||||
__tablename__ = "sync_engine_state"
|
||||
|
||||
id = Column(Integer, primary_key=True, default=1)
|
||||
universal_bootstrap_completed_at = Column(DateTime, nullable=True)
|
||||
universal_bootstrap_cursor = Column(Integer, nullable=False, default=0)
|
||||
universal_bootstrap_last_error = Column(Text, nullable=True)
|
||||
|
||||
|
||||
class SyncClientDisplayName(db.Model):
|
||||
"""Привязка клиента к отображаемому имени (для UI)."""
|
||||
|
||||
__tablename__ = "sync_client_display_name"
|
||||
|
||||
node_id = Column(String(36), primary_key=True)
|
||||
display_name = Column(String(100), nullable=False)
|
||||
updated_at = Column(DateTime, nullable=False)
|
||||
|
||||
|
||||
class SyncQueue(db.Model, TimestampMixin, SoftDeleteMixin):
|
||||
"""Очередь задач синхронизации."""
|
||||
|
||||
__tablename__ = "sync_queue"
|
||||
__table_args__ = (
|
||||
UniqueConstraint(
|
||||
"table_name",
|
||||
"record_id",
|
||||
"action",
|
||||
"target_node_id",
|
||||
name="uq_sync_queue_task",
|
||||
),
|
||||
)
|
||||
|
||||
id = Column(String(36), primary_key=True, default=default_uuid)
|
||||
table_name = Column(String(50), nullable=False)
|
||||
record_id = Column(String(36), nullable=False)
|
||||
action = Column(String(20), nullable=False) # 'create' | 'update' | 'delete'
|
||||
status = Column(String(20), default="pending") # pending|processing|completed|failed
|
||||
target_node_id = Column(String(36), nullable=True)
|
||||
source_node_id = Column(String(36), nullable=True)
|
||||
priority = Column(Integer, default=1)
|
||||
retry_count = Column(Integer, default=0)
|
||||
max_retries = Column(Integer, default=3)
|
||||
error_message = Column(Text, nullable=True)
|
||||
created_at = Column(DateTime, nullable=False)
|
||||
processed_at = Column(DateTime, nullable=True)
|
||||
completed_at = Column(DateTime, nullable=True)
|
||||
|
||||
|
||||
class SyncDelivery(db.Model, TimestampMixin, SoftDeleteMixin):
|
||||
"""Фиксация доставки универсальных задач до клиентов."""
|
||||
|
||||
__tablename__ = "sync_delivery"
|
||||
|
||||
id = Column(String(36), primary_key=True, default=default_uuid)
|
||||
client_id = Column(String(36), nullable=False, index=True)
|
||||
task_id = Column(String(36), nullable=False, index=True)
|
||||
delivered_at = Column(DateTime, nullable=False)
|
||||
|
||||
|
||||
class SyncConflict(db.Model, TimestampMixin, SoftDeleteMixin):
|
||||
"""Конфликты синхронизации."""
|
||||
|
||||
__tablename__ = "sync_conflicts"
|
||||
|
||||
id = Column(String(36), primary_key=True, default=default_uuid)
|
||||
table_name = Column(String(50), nullable=False)
|
||||
record_id = Column(String(36), nullable=False)
|
||||
conflict_type = Column(String(20), nullable=False)
|
||||
local_data = Column(Text, nullable=True)
|
||||
remote_data = Column(Text, nullable=True)
|
||||
resolution = Column(String(20), nullable=True)
|
||||
resolved_by = Column(String(50), nullable=True)
|
||||
resolved_at = Column(DateTime, nullable=True)
|
||||
|
||||
Reference in New Issue
Block a user