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:
- Create Zoom meeting via REST API
- Create calendar event with Zoom link in external calendar
- 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
| Component | Priority | Complexity | Dependencies |
|---|---|---|---|
| Unified Scheduling | P0 | Medium | Provider interfaces |
| Attendee Management | P0 | Low | Provider interfaces |
| Recurrence Support | P1 | Medium | Unified Scheduling |
| Calendar Sync | P1 | High | External calendar APIs |
| Availability Checking | P1 | Medium | Calendar Sync |
| Reminder System | P2 | Medium | Notification service |
References
- RFC 5545 (iCalendar specification)
- Zoom recurring meeting API
- Google Calendar API freebusy endpoint
- Microsoft Graph calendar API
- ADR-001: Provider Abstraction Pattern