任务的数据库表示
对于上面的例子来说,启动一个任务并观察它运行就足够了。 对于 Web 应用程序,情况会变得更复杂一些,因为一旦任务随着请求的处理而启动,该请求随即结束,而该任务的所有上下文都将丢失。 因为我希望应用程序跟踪每个用户正在运行的任务,所以我需要使用数据库表来维护状态。 你可以在下面看到新的 Task
模型实现:
app/models.py :Task 模型。
# ...
import redis
import rq
class User(UserMixin, db.Model):
# ...
tasks = db.relationship('Task', backref='user', lazy='dynamic')
# ...
class Task(db.Model):
id = db.Column(db.String(36), primary_key=True)
name = db.Column(db.String(128), index=True)
description = db.Column(db.String(128))
user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
complete = db.Column(db.Boolean, default=False)
def get_rq_job(self):
try:
rq_job = rq.job.Job.fetch(self.id, connection=current_app.redis)
except (redis.exceptions.RedisError, rq.exceptions.NoSuchJobError):
return None
return rq_job
def get_progress(self):
job = self.get_rq_job()
return job.meta.get('progress', 0) if job is not None else 100
这个模型和以前的模型有一个有趣的区别是 id
主键字段是字符串类型,而不是整数类型。 这是因为对于这个模型,我不会依赖数据库自己的主键生成,而是使用由 RQ 生成的作业标识符。
该模型将存储符合任务命名规范的名称(会传递给 RQ),适用于向用户显示的任务描述,该任务的所属用户的关系以及任务是否已完成的布尔值。 complete
字段的目的是将正在运行的任务与已完成的任务分开,因为运行中的任务需要特殊处理才能显示最新进度。
get_rq_job()
辅助方法可以用给定的任务 ID 加载 RQ Job
实例。 这是通过 Job.fetch()
完成的,它会从 Redis 中存在的数据中加载 Job
实例。 get_progress()
方法建立在 get_rq_job()
的基础之上,并返回任务的进度百分比。 该方法做一些有趣的假设,如果模型中的作业 ID 不存在于 RQ 队列中,则表示作业已完成并且数据已过期并已从队列中删除,因此在这种情况下返回的百分比为 100。 另一方面,如果 job 存在,但'meta'属性中找不到进度相关的信息,那么可以安全地假定该 job 计划运行,但还没有启动,所以在这种情况下进度是 0。
要将更改应用于数据库,需要生成新的迁移,然后升级数据库:
(venv) $ flask db migrate -m "tasks"
(venv) $ flask db upgrade
新模型也可以添加到 shell 上下文中,以便在 shell 会话中访问它时无需导入:
microblog.py :添加 Task 模型到 shell 上下文中。
from app import create_app, db, cli
from app.models import User, Post, Message, Notification, Task
app = create_app()
cli.register(app)
@app.shell_context_processor
def make_shell_context():
return {'db': db, 'User': User, 'Post': Post, 'Message': Message,
'Notification': Notification, 'Task': Task}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论