Skip to content

Commit 54d0d08

Browse files
committed
Only check for reminders every hour instead of every few seconds to reduce unnecessary server load.
1 parent a4b75d3 commit 54d0d08

File tree

1 file changed

+26
-19
lines changed

1 file changed

+26
-19
lines changed

api/src/dispatch_emails.py

+26-19
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
import requests
99
from core.auth import create_access_token
10-
from membership.membership import get_members_and_membership
10+
from membership.membership import get_members_and_membership, get_membership_summaries
1111
from membership.models import Member, Span
1212
from messages.message import send_message
1313
from messages.models import Message, MessageTemplate
@@ -100,13 +100,13 @@ def send_messages(key: Optional[str], domain: str, sender: str, to_override: Opt
100100
logger.error(f"failed to send {message.id} to {to}: {response.content.decode('utf-8')}")
101101

102102

103-
def already_sent_message(template: MessageTemplate, member: Member, days: int) -> bool:
103+
def already_sent_message(template: MessageTemplate, member_id: int, days: int) -> bool:
104104
"""True if a message has been sent with the given template to the member in the last #days days"""
105105
now = datetime.now(timezone.utc).replace(tzinfo=None)
106106
reminder_sent = (
107107
db_session.query(Message)
108108
.filter(
109-
Message.member == member,
109+
Message.member_id == member_id,
110110
Message.template == template.value,
111111
now - timedelta(days=days) < Message.created_at,
112112
)
@@ -142,7 +142,7 @@ def labaccess_reminder() -> None:
142142
continue
143143

144144
# Don't send a reminder if we sent a reminder the last 28 days.
145-
if already_sent_message(MessageTemplate.LABACCESS_REMINDER, member, LABACCESS_REMINDER_GRACE_PERIOD):
145+
if already_sent_message(MessageTemplate.LABACCESS_REMINDER, member.member_id, LABACCESS_REMINDER_GRACE_PERIOD):
146146
continue
147147

148148
already_purchased = (
@@ -172,11 +172,15 @@ def labaccess_reminder() -> None:
172172
def membership_reminder() -> None:
173173
now = datetime.now(timezone.utc).replace(tzinfo=None).date()
174174

175-
members, memberships = get_members_and_membership()
176-
members = list(members)
175+
t0 = time.time()
176+
member_ids = db_session.scalars(select(Member.member_id).filter(Member.deleted_at == None)).all()
177+
178+
memberships = get_membership_summaries(member_ids)
179+
t1 = time.time()
180+
logger.info(f"get_members_and_membership took {t1 - t0:.2f}s")
177181
end_date_reminder_target = now + timedelta(days=MEMBERSHIP_REMINDER_DAYS_BEFORE)
178182

179-
for member, membership in zip(members, memberships):
183+
for member_id, membership in zip(member_ids, memberships):
180184
if membership.membership_end is None:
181185
# Not a member
182186
continue
@@ -192,13 +196,14 @@ def membership_reminder() -> None:
192196
continue
193197

194198
# Don't send a reminder if we sent a reminder the last 28 days.
195-
if already_sent_message(MessageTemplate.MEMBERSHIP_REMINDER, member, MEMBERSHIP_REMINDER_GRACE_PERIOD):
199+
if already_sent_message(MessageTemplate.MEMBERSHIP_REMINDER, member_id, MEMBERSHIP_REMINDER_GRACE_PERIOD):
196200
continue
197201

198202
already_purchased = (
199-
pending_action_value_sum(member_id=member.member_id, action_type=ProductAction.ADD_MEMBERSHIP_DAYS) > 0
203+
pending_action_value_sum(member_id=member_id, action_type=ProductAction.ADD_MEMBERSHIP_DAYS) > 0
200204
)
201205

206+
member = db_session.get_one(Member, member_id)
202207
already_purchased |= member.stripe_membership_subscription_id is not None
203208

204209
if already_purchased:
@@ -358,8 +363,8 @@ def get_login_link(member: Member, browser: str, path: str) -> str:
358363
description="Dispatch emails in db send queue.", formatter_class=ArgumentDefaultsHelpFormatter
359364
)
360365

361-
parser.add_argument("--sleep", default=4, help="Sleep time (in seconds) between doing ant work.")
362-
parser.add_argument("--limit", default=10, help="Max messages to send every time checking for messages.")
366+
parser.add_argument("--sleep", default=1, help="Sleep time (in seconds) between doing ant work.")
367+
parser.add_argument("--limit", default=4, help="Max messages to send every time checking for messages.")
363368

364369
args = parser.parse_args()
365370

@@ -372,19 +377,21 @@ def get_login_link(member: Member, browser: str, path: str) -> str:
372377
domain = config.get("MAILGUN_DOMAIN")
373378
sender = config.get("MAILGUN_FROM")
374379
to_override = config.get("MAILGUN_TO_OVERRIDE")
375-
last_quiz_check = time.time()
380+
last_reminder_check = 0.0
376381

377382
while True:
378383
sleep(args.sleep)
379384
try:
380-
labaccess_reminder()
381-
membership_reminder()
382-
if time.time() - last_quiz_check > 20:
383-
# This check is kinda slow (takes maybe 100 ms)
384-
# so don't do it as often. It's not time critical anyway.
385-
last_quiz_check = time.time()
385+
if time.time() - last_reminder_check > 60 * 60:
386+
# These checks are kinda slow (takes a few hundred ms)
387+
# so don't do them as often. They are not time critical anyway.
388+
last_reminder_check = time.time()
389+
logger.info("checking for reminders to send")
390+
labaccess_reminder()
391+
membership_reminder()
386392
quiz_reminders()
387-
db_session.commit()
393+
394+
db_session.commit()
388395
send_messages(key, domain, sender, to_override, args.limit)
389396
db_session.commit()
390397
except DatabaseError as e:

0 commit comments

Comments
 (0)