Skip to main content

ADR-004: Unified Scheduling Strategy

Status: Accepted Date: December 17, 2025 Deciders: CODITECT Architecture Team

Context

CODITECT meeting integrations need robust scheduling capabilities that work consistently across providers (Google Meet, Zoom, future providers). Customers need:

  • Unified scheduling interface regardless of provider
  • Calendar synchronization with external systems
  • Complex recurring meeting patterns
  • Attendee management with invitations/RSVPs
  • Availability checking across participants
  • Pre-meeting reminder notifications

Decision

We will implement a MeetingSchedulerOrchestrator that provides:

1. Unified Scheduling Interface

class MeetingSchedulerOrchestrator:
"""Provider-agnostic meeting scheduler."""

async def schedule_meeting(
self,
provider: str,
title: str,
start_time: datetime,
duration: int,
attendees: List[Attendee],
recurrence: RecurrenceRule = None,
reminders: List[Reminder] = None
) -> ScheduledMeeting

async def check_availability(
self,
attendees: List[str],
time_range: TimeRange,
duration: int
) -> List[AvailableSlot]

async def sync_calendar(
self,
calendar_id: str,
direction: SyncDirection
) -> SyncResult

2. Calendar Sync Architecture

┌─────────────────────────────────────────────────────────────────┐
│ MeetingSchedulerOrchestrator │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │
│ │ CalendarSync │ │ Availability │ │ Reminder │ │
│ │ Manager │ │ Service │ │ Service │ │
│ └────────┬────────┘ └────────┬────────┘ └────────┬────────┘ │
│ │ │ │ │
└───────────┼────────────────────┼────────────────────┼──────────┘
│ │ │
▼ ▼ ▼
┌───────────────────┐ ┌───────────────────┐ ┌───────────────────┐
│ Google Calendar │ │ Microsoft Graph │ │ Notification │
│ API │ │ API (Outlook) │ │ Service │
└───────────────────┘ └───────────────────┘ └───────────────────┘

3. Zoom-Specific Scheduling Considerations

Zoom meetings don't have native calendar integration, so we need to:

  1. Create Zoom meeting via REST API
  2. Create calendar event with Zoom link in external calendar
  3. Sync changes bidirectionally
class ZoomSchedulingAdapter:
"""Adapts Zoom meetings to calendar-centric model."""

async def create_with_calendar_event(
self,
meeting: ZoomMeetingCreate,
calendar_provider: str, # "google" | "outlook"
calendar_id: str
) -> ScheduledMeeting:
# 1. Create Zoom meeting
zoom_meeting = await self.zoom_api.create_meeting(meeting)

# 2. Create calendar event with Zoom link
calendar_event = await self.calendar_sync.create_event(
calendar_provider=calendar_provider,
calendar_id=calendar_id,
event=CalendarEvent(
title=meeting.topic,
start_time=meeting.start_time,
duration=meeting.duration,
conference_url=zoom_meeting.join_url,
conference_data={'zoom_id': zoom_meeting.id}
)
)

return ScheduledMeeting(
meeting=zoom_meeting,
calendar_event=calendar_event
)

4. Recurrence Pattern Support

Based on RFC 5545 (iCalendar) RRULE format:

@dataclass
class RecurrenceRule:
frequency: Frequency # DAILY, WEEKLY, MONTHLY, YEARLY
interval: int = 1
count: Optional[int] = None
until: Optional[datetime] = None
by_day: Optional[List[Weekday]] = None
by_month_day: Optional[List[int]] = None
by_month: Optional[List[int]] = None
exceptions: List[datetime] = field(default_factory=list)

# Zoom recurrence mapping
ZOOM_RECURRENCE_TYPES = {
Frequency.DAILY: 1,
Frequency.WEEKLY: 2,
Frequency.MONTHLY: 3,
}

5. Attendee Management

@dataclass
class Attendee:
email: str
name: Optional[str] = None
role: AttendeeRole = AttendeeRole.REQUIRED
response_status: ResponseStatus = ResponseStatus.PENDING
notify: bool = True

class ZoomAttendeeManager:
"""Manages attendees for Zoom meetings."""

async def add_registrants(
self,
meeting_id: str,
attendees: List[Attendee]
) -> List[RegistrantResponse]:
"""Add registrants to meeting (if registration required)."""
pass

async def send_invitations(
self,
meeting: ZoomMeeting,
attendees: List[Attendee],
via_calendar: bool = True
) -> None:
"""Send meeting invitations via email or calendar."""
pass

6. Availability Checking

Since Zoom doesn't have native calendar, we rely on external calendars:

class AvailabilityService:
"""Check availability across calendar providers."""

async def get_free_busy(
self,
calendars: List[CalendarReference],
time_min: datetime,
time_max: datetime
) -> Dict[str, List[BusyPeriod]]:
"""Get busy times from multiple calendars."""

results = {}
for cal in calendars:
if cal.provider == 'google':
results[cal.email] = await self.google_calendar.get_freebusy(...)
elif cal.provider == 'outlook':
results[cal.email] = await self.ms_graph.get_schedule(...)

return results

async def find_available_slots(
self,
attendees: List[str],
time_range: TimeRange,
duration_minutes: int,
working_hours: WorkingHours = None
) -> List[AvailableSlot]:
"""Find times when all attendees are free."""
pass

7. Reminder System

@dataclass
class Reminder:
minutes_before: int
method: ReminderMethod # EMAIL, PUSH, SMS, WEBHOOK

class ReminderService:
"""Manages meeting reminders."""

async def schedule_reminder(
self,
meeting_id: str,
reminder: Reminder
) -> str:
"""Schedule a reminder for a meeting."""
pass

async def process_due_reminders(self) -> List[SentReminder]:
"""Process and send due reminders (background job)."""
pass

Consequences

Positive

  • Consistent scheduling experience across all providers
  • Two-way calendar sync maintains data consistency
  • Complex recurrence patterns handled uniformly
  • Attendee management simplifies meeting coordination
  • Availability checking reduces scheduling conflicts
  • Reminder system improves meeting attendance

Negative

  • Zoom requires external calendar for full scheduling experience
  • Additional complexity in orchestration layer
  • Calendar sync requires handling conflicts
  • Must respect rate limits across multiple APIs

Neutral

  • Some Zoom-specific features (breakout rooms, waiting room) not in unified interface
  • Calendar sync frequency must balance freshness vs API costs

Implementation Priority

ComponentPriorityComplexityDependencies
Unified SchedulingP0MediumProvider interfaces
Attendee ManagementP0LowProvider interfaces
Recurrence SupportP1MediumUnified Scheduling
Calendar SyncP1HighExternal calendar APIs
Availability CheckingP1MediumCalendar Sync
Reminder SystemP2MediumNotification service

References

  • RFC 5545 (iCalendar specification)
  • Zoom recurring meeting API
  • Google Calendar API freebusy endpoint
  • Microsoft Graph calendar API
  • ADR-001: Provider Abstraction Pattern