Skip to content

Commit

Permalink
Add queue scheduler
Browse files Browse the repository at this point in the history
  • Loading branch information
iameru committed Nov 30, 2023
1 parent a9d8101 commit 3d3ced5
Show file tree
Hide file tree
Showing 3 changed files with 121 additions and 6 deletions.
86 changes: 82 additions & 4 deletions server/dearmep/database/query.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
from .connection import Session, select
from .models import Blob, BlobID, Destination, DestinationID, \
DestinationSelectionLog, DestinationSelectionLogEvent, MediaList, \
NumberVerificationRequest, ScheduledCall, UserFeedback
NumberVerificationRequest, ScheduledCall, ScheduledCallQueue, UserFeedback


_logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -726,11 +726,10 @@ def get_schedule(
) -> List[ScheduledCall]:
""" Get all scheduled calls for a user"""

schedule = session.exec(
return session.exec(
select(ScheduledCall)
.where(ScheduledCall.user_id == user_id)
).all()
return schedule


def set_schedule(
Expand All @@ -755,4 +754,83 @@ def clear_schedule(
session.query(ScheduledCall).filter(
ScheduledCall.user_id == user_id
).delete()
session.commit()


def get_currently_scheduled_calls(
session: Session,
now: datetime,
timeframe: timedelta,
) -> List[ScheduledCall]:
"""
Returns a list of ScheduledCall's that are
- scheduled for today
- scheduled for a time that is in the past but within our
call_schedule_interval
- have not been queued today
"""
return session.query(ScheduledCall).filter(
ScheduledCall.day == now.isoweekday(),
and_(
ScheduledCall.start_time <= now.time(),
ScheduledCall.start_time >= (now - timeframe).time(),
),
or_(
col(ScheduledCall.last_queued_at).is_(None),
ScheduledCall.last_queued_at < now.date(), # type: ignore
),
).all()


def mark_scheduled_calls_queued(
session: Session,
calls: List[ScheduledCall],
now: datetime,
):
"""Timestamps 'last_queued_at' to 'now' for calls."""
for call in calls:
call.last_queued_at = now
session.add_all(calls)


def postpone_queued_call(
session: Session,
user_id: UserPhone,
new_time: datetime,
):
"""
Postpones a queued call to a new time.
"""
try:
queued_call: ScheduledCallQueue = session.query(
ScheduledCallQueue
).filter(
ScheduledCallQueue.user_id == user_id
).one()
except NoResultFound:
raise ValueError("Call has not been queued yet.")

if queued_call.postponed_to:
raise ValueError("Call has already been postponed.")

queued_call.postponed_to = new_time
session.add(queued_call)


def get_currently_queued_call(
session: Session,
now: datetime,
) -> Optional[ScheduledCallQueue]:
"""
Returns a ScheduledCallQueue object which was the first inserted
with priority to the postponed calls.
"""

postponed = session.query(ScheduledCallQueue).filter(
ScheduledCallQueue.postponed_to <= now, # type: ignore
).order_by(
col(ScheduledCallQueue.postponed_to).desc(),
).first()
if postponed:
return postponed # type: ignore
else:
return session.query(ScheduledCallQueue).first()
1 change: 1 addition & 0 deletions server/dearmep/schedules/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ def get_background_tasks(config: Config):
repeat_every(
seconds=cfg.interval,
wait_first=cfg.wait_first,
raise_exceptions=True,
)(func) for cfg, func in tasks]


Expand Down
40 changes: 38 additions & 2 deletions server/dearmep/schedules/calls.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,42 @@
from datetime import datetime, timedelta

from ..config import Config
from ..database import query
from ..database.models import ScheduledCallQueue
from ..database.connection import get_session


def build_queue() -> None:
pass

now = datetime.now()
office_hours = Config.get().telephony.office_hours
if not office_hours.open(now):
return

with get_session() as session:
timeframe = timedelta(minutes=office_hours.call_schedule_interval)
calls = query.get_currently_scheduled_calls(session, now, timeframe)
# we want to sort and preserve this order in sqlalchemy's session.add
# so we iterate it.
calls.sort(key=lambda call: call.start_time)
for call in calls:
session.add(
ScheduledCallQueue(
user_id=call.user_id,
language=call.language,
))
query.mark_scheduled_calls_queued(session, calls, now)
session.commit()


def handle_queue() -> None:
pass

now = datetime.now()
with get_session() as session:
queued_call = query.get_currently_queued_call(session, now)
if queued_call is None:
return
# TODO Start call
# query.get_random_destination(session)
session.delete(queued_call)
session.commit()

0 comments on commit 3d3ced5

Please sign in to comment.