Implement destructive CalDAV move saga
This commit is contained in:
@@ -256,9 +256,63 @@ class CalendarOutboxOperation(Base, TimestampMixin):
|
||||
event: Mapped[CalendarEvent | None] = relationship()
|
||||
|
||||
|
||||
class CalendarMigrationBatch(Base, TimestampMixin):
|
||||
"""Durable destructive remote-move saga and its authorization evidence."""
|
||||
|
||||
__tablename__ = "calendar_migration_batches"
|
||||
__table_args__ = (
|
||||
Index("ix_calendar_migration_batches_tenant_status", "tenant_id", "status", "created_at"),
|
||||
Index("ix_calendar_migration_batches_calendars", "tenant_id", "source_calendar_id", "target_calendar_id"),
|
||||
)
|
||||
|
||||
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=new_uuid)
|
||||
tenant_id: Mapped[str] = mapped_column(String(36), nullable=False, index=True)
|
||||
migration_kind: Mapped[str] = mapped_column(String(30), default="remote_move", nullable=False)
|
||||
status: Mapped[str] = mapped_column(String(30), default="active", nullable=False, index=True)
|
||||
phase: Mapped[str] = mapped_column(String(40), default="copying_destination", nullable=False, index=True)
|
||||
source_calendar_id: Mapped[str] = mapped_column(ForeignKey("calendar_collections.id", ondelete="RESTRICT"), nullable=False, index=True)
|
||||
target_calendar_id: Mapped[str] = mapped_column(ForeignKey("calendar_collections.id", ondelete="RESTRICT"), nullable=False, index=True)
|
||||
source_sync_source_id: Mapped[str] = mapped_column(ForeignKey("calendar_sync_sources.id", ondelete="RESTRICT"), nullable=False, index=True)
|
||||
target_sync_source_id: Mapped[str] = mapped_column(ForeignKey("calendar_sync_sources.id", ondelete="RESTRICT"), nullable=False, index=True)
|
||||
total_resources: Mapped[int] = mapped_column(Integer, default=0, nullable=False)
|
||||
total_events: Mapped[int] = mapped_column(Integer, default=0, nullable=False)
|
||||
created_by_user_id: Mapped[str | None] = mapped_column(ForeignKey("access_users.id", ondelete="SET NULL"), nullable=True, index=True)
|
||||
created_by_api_key_id: Mapped[str | None] = mapped_column(String(36), nullable=True, index=True)
|
||||
authorization_evidence: Mapped[dict[str, Any]] = mapped_column(JSON, default=dict, nullable=False)
|
||||
cancellation_evidence: Mapped[dict[str, Any] | None] = mapped_column(JSON, nullable=True)
|
||||
last_error: Mapped[str | None] = mapped_column(Text)
|
||||
completed_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True, index=True)
|
||||
|
||||
resources: Mapped[list["CalendarMigrationResource"]] = relationship(back_populates="batch", cascade="all, delete-orphan")
|
||||
|
||||
|
||||
class CalendarMigrationResource(Base, TimestampMixin):
|
||||
__tablename__ = "calendar_migration_resources"
|
||||
__table_args__ = (
|
||||
UniqueConstraint("batch_id", "source_href", name="uq_calendar_migration_resources_batch_href"),
|
||||
Index("ix_calendar_migration_resources_batch_status", "batch_id", "status"),
|
||||
)
|
||||
|
||||
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=new_uuid)
|
||||
tenant_id: Mapped[str] = mapped_column(String(36), nullable=False, index=True)
|
||||
batch_id: Mapped[str] = mapped_column(ForeignKey("calendar_migration_batches.id", ondelete="CASCADE"), nullable=False, index=True)
|
||||
source_href: Mapped[str] = mapped_column(String(1000), nullable=False)
|
||||
source_expected_etag: Mapped[str] = mapped_column(String(255), nullable=False)
|
||||
destination_href: Mapped[str] = mapped_column(String(1000), nullable=False)
|
||||
event_ids: Mapped[list[str]] = mapped_column(JSON, default=list, nullable=False)
|
||||
status: Mapped[str] = mapped_column(String(30), default="copy_pending", nullable=False, index=True)
|
||||
destination_operation_id: Mapped[str | None] = mapped_column(ForeignKey("calendar_outbox_operations.id", ondelete="SET NULL"), nullable=True, unique=True)
|
||||
source_delete_operation_id: Mapped[str | None] = mapped_column(ForeignKey("calendar_outbox_operations.id", ondelete="SET NULL"), nullable=True, unique=True)
|
||||
last_error: Mapped[str | None] = mapped_column(Text)
|
||||
|
||||
batch: Mapped[CalendarMigrationBatch] = relationship(back_populates="resources")
|
||||
|
||||
|
||||
__all__ = [
|
||||
"CalendarCollection",
|
||||
"CalendarEvent",
|
||||
"CalendarMigrationBatch",
|
||||
"CalendarMigrationResource",
|
||||
"CalendarOutboxOperation",
|
||||
"CalendarSyncCredential",
|
||||
"CalendarSyncSource",
|
||||
|
||||
Reference in New Issue
Block a user