有没有办法检查Django管理命令是否正在运行?

时间:2015-08-28 15:46:09

标签: python django

视图依赖于Redis的填充。 Redis是通过每10分钟运行一次的管理命令填充的。此管理命令删除所有现有密钥,并使用新数据重新添加它们。如何确定管理命令是否从django视图运行?

现在我正在将管理命令写入外部文件,并在每个请求上都有一个视图读取该文件。如果数据库通过管理命令刷新,我会保持视图直到它完成(轮询样式)。

1 个答案:

答案 0 :(得分:3)

Django没有提供预先打包的方法来检查管理命令是否正在运行。这就是说,在等待某些结果时,你永远不应该编写明确阻止视图的代码。您可以轻松地使用运行应用程序的服务器为您的应用程序提供的所有线程和进程。您的用户在您的网站上的体验会很差,即使是那些不会做任何与您在此处尝试解决的问题有关的人。

我从您的描述中得到的是,您希望用户获得相当新鲜的结果。对于这样的事情,我会使用基于versioning数据的解决方案。它会是这样的:

  1. settings.py文件中声明一个Redis支持的缓存,该缓存将包含命令填充的数据并由视图读取。确保缓存的TIMEOUT设置为NONE

  2. 使用键CURRENT_VERSION记录当前版本号。这个密钥本身是无版本的。

  3. 当命令刷新缓存中的数据时,它会将其存储在版本设置为CURRENT_VERSION + 1的密钥中。你会有类似的东西:

    current_version = cache.get(CURRENT_VERSION)
    
    # Record the new data.
    for ...:
        cache.set(some_key, some_value, version=current_version + 1)
    
  4. Django的缓存系统不容易获得一组对应于特定标准的密钥。但是,您的视图将需要获取属于特定版本的所有密钥。此信息可记录为:

    cache.set(ALL_RECORDS, 
              [... list of keys set in the loop above ...], 
              version=current_version + 1)
    

    ALL_RECORDS是一个密钥值,保证不会与CURRENT_VERSION或为各个记录设置的任何密钥冲突。

  5. 命令完成后,会以原子方式增加CURRENT_VERSION

    的值
    cache.incr(CURRENT_VERSION)
    

    关于Redis后端的文档指出,如果你对适当的值执行增量(左边模糊但整数似乎合适),那么Redis将以原子方式执行增量。

  6. 该命令还应该从缓存中清除旧版本。确保旧数据不会保留在缓存中的一种方法是在设置其值时设置密钥的到期时间。刷新缓存的命令每10分钟运行一次。因此,您将密钥设置为在15分钟后过期。但是假设一个问题阻止了多次运行命令。然后怎样呢?您的数据将过期并从缓存中删除,并且视图将使用空数据集运行。如果这适合您的情况,那么我猜您每次执行timeout时都可以设置cache.set参数,但永远不会过期的CURRENT_VERSION除外。

    如果您对使用空数据集运行的视图不满意(这对我来说似乎更有可能),那么您必须在命令中编写代码以寻找旧版本并明确删除它们。

  7. 您的视图通过以下方式访问缓存:

    1. 阅读CURRENT_VERSION

      的值
      current_version = cache.get(CURRENT_VERSION)
      
    2. 阅读其获得的版本中的记录列表:

      keys = cache.get(ALL_RECORDS, version=current_version)
      
    3. 处理记录:

      for key in keys:
          value = cache.get(key, version=current_version)
      
    4. 视图应检测缓存尚未初始化并正常失败的情况。部署应用程序时,应注意该命令至少运行一次,然后才能访问该站点。

      如果视图在命令更新缓存时开始工作,则无关紧要。从命令的角度来看,缓存只是访问以前的版本。从视图的角度来看,命令正忙于创建下一个版本,但这对于视图是不可见的。视图不必阻止。