任务助手
尽管我上面使用的 example()
任务是一个简单的独立函数,但导出用户动态的函数却需要应用中具有的一些功能,例如访问数据库和发送电子邮件。 因为这将在单独的进程中运行,所以我需要初始化 Flask-SQLAlchemy 和 Flask-Mail,而 Flask-Mail 又需要 Flask 应用实例以从中获取它们的配置。 因此,我将在 app/tasks.py 模块的顶部添加 Flask 应用实例和应用上下文:
app/tasks.py :创建应用及其上下文。
from app import create_app
app = create_app()
app.app_context().push()
应用在此模块中创建,因为这是 RQ worker 要导入的唯一模块。 当使用 flask
命令时,根目录中的 microblog.py 模块创建应用实例,但 RQ worker 对此却一无所知,所以当任务函数需要它时,它需要创建自己的应用实例。 你已经在好几个地方看到了 app.app_context()
方法,推送一个上下文使应用成为“当前”的应用实例,这样一来 Flask-SQLAlchemy 等插件才可以使用 current_app.config
获取它们的配置。 没有上下文, current_app
表达式会返回一个错误。
然后我开始考虑如何在这个函数运行时报告进度。除了通过 job.meta
字典传递进度信息之外,我还想将通知推送给客户端,以便自动动态更新完成百分比。为此,我将使用我在 第二十一章 中构建的通知机制。更新将以与未读消息徽章非常类似的方式工作。当服务器渲染模板时,它将包含从 job.meta
获得的“静态”进度信息,但是一旦页面位于客户端的浏览器中,通知将使用通知来动态更新百分比。由于通知的原因,更新正在运行的任务的进度将比上一个示例中的操作稍微多一些,所以我将创建一个专用于更新进度的包装函数:
app/tasks.py :设置任务进度。
from rq import get_current_job
from app import db
from app.models import Task
# ...
def _set_task_progress(progress):
job = get_current_job()
if job:
job.meta['progress'] = progress
job.save_meta()
task = Task.query.get(job.get_id())
task.user.add_notification('task_progress', {'task_id': job.get_id(),
'progress': progress})
if progress >= 100:
task.complete = True
db.session.commit()
导出任务可以调用 _set_task_progress()
来记录进度百分比。 该函数首先将百分比写入 job.meta
字典并将其保存到 Redis,然后从数据库加载相应的任务对象,并使用 task.user
已有的 add_notification()
方法将通知推送给请求该任务的用户。 通知将被命名为 task_progress
,并且与其关联的数据将成为具有两个条目的字典:任务标识符和进度数值。 稍后我将添加 JavaScript 代码来处理这种新的通知类型。
该函数查看进度来确认任务函数是否已完成,并在这种情况下更新数据库中任务对象的 complete
属性。 数据库提交调用确保通过 add_notification()
添加的任务和通知对象都立即保存到数据库。 我需要非常精确地设计父任务,确保不执行任何数据库更改,因为执行本调用会将父任务的更改也写入数据库。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论