如何在Celery定时任务中每发送20封邮件休眠1秒?
实现Celery任务每发送20封邮件休眠1秒
解决方案思路
- 先从数据库筛选出
due_date为今日的记录,提取目标邮箱列表(或逐个处理每条记录) - 将邮件发送任务按每20封一组拆分,每完成一组发送后(非最后一组)执行1秒休眠;若需针对单条记录定制邮件内容,则逐个发送并计数,每发送20封触发休眠。
代码实现(批量发送场景)
适用于所有邮件模板数据一致,仅收件人不同的情况:
from datetime import date import time from celery import app # 根据你的Celery配置导入 from your_app.models import YourModel # 替换为你的数据库模型类 from your_email_utils import send_email_from_template # 导入邮件发送函数 @app.task(bind=True) def send_email_reminder_on_due_date(self): # 1. 获取今日到期的记录 today = date.today() records = YourModel.objects.filter(due_date=today) # 2. 提取所有收件邮箱 email_list = [record.email for record in records] # 通用模板数据(若需每条记录定制,需调整为逐行生成) template_data = { "greeting": "您好", "subject_prefix": "到期提醒" # 补充你的模板变量 } # 3. 按每20封拆分批次 batch_size = 20 email_batches = [email_list[i:i+batch_size] for i in range(0, len(email_list), batch_size)] # 4. 逐批次发送并休眠 for idx, batch in enumerate(email_batches): send_email_from_template( subject_template_path='emails/subject.txt', body_template_path='emails/template.html', template_data=template_data, to_email_list=batch, fail_silently=False, content_subtype='html' ) # 最后一批无需休眠 if idx != len(email_batches) - 1: time.sleep(1)
代码实现(单条定制场景)
适用于每条记录对应不同模板内容的情况:
from datetime import date import time from celery import app from your_app.models import YourModel from your_email_utils import send_email_from_template @app.task(bind=True) def send_email_reminder_on_due_date(self): today = date.today() records = YourModel.objects.filter(due_date=today) batch_size = 20 send_count = 0 total_records = len(records) for record in records: # 为当前记录生成专属模板数据 template_data = { "username": record.username, "due_task": record.task_name, "due_date": record.due_date.strftime("%Y-%m-%d") # 补充个性化变量 } # 发送单封邮件 send_email_from_template( subject_template_path='emails/subject.txt', body_template_path='emails/template.html', template_data=template_data, to_email_list=[record.email], fail_silently=False, content_subtype='html' ) send_count += 1 # 每发送20封且未到最后一封时休眠 if send_count % batch_size == 0 and send_count != total_records: time.sleep(1)
注意事项
- 替换代码中的
YourModel为实际的数据库模型类,确保字段名(如email、task_name)与你的模型匹配 - 若使用Celery多进程/多线程worker,每个worker进程会独立处理分配到的任务批次,休眠逻辑仅作用于当前进程内的任务流
time.sleep(1)会阻塞当前worker进程,若任务量极大,可根据实际情况调整休眠时长或批次大小
内容的提问来源于stack exchange,提问作者Happy
相关产品推荐
相关产品推荐

