总体概述
- 我有中型 django 项目
- 我在内存中有一堆前缀树(而不是 DB)
- 这些树的节点表示受超时影响的实体/对象。即,我需要在不同的时间点使这些节点超时
设计:
- 本质上,我需要一个 Timer 构造,它允许我触发一个可重置的 1-shot 计时器并关联并给它一个回调,该回调可以对创建计时器的实体执行一些操作,在本例中是树的一个节点。
在浏览了各种选项后,我找不到任何可以本地使用的东西(比如一些 django 应用程序)。Python 中的 Timer 对象不适合这种情况,因为它不会扩展/执行。因此,我决定根据以下内容编写自己的计时器:
- 包含时间范围的时间增量对象的排序列表
- 触发“滴答”的机制
实施选择:
- 使用 Bisect 的包装器获取排序的增量列表: http ://code.activestate.com/recipes/577197-sortedcollection/
- 与芹菜一起提供滴答声 - 1 分钟的粒度,工作人员将触发我的 Timer 类提供的 timer_tick 函数。timer_tick 本质上应该通过排序列表,每次滴答都会减少头节点。然后,如果任何节点已被标记为 0,则启动回调并将这些节点从排序的计时器列表中删除。
- 创建计时器涉及实例化一个返回对象 id 的 Timer 对象。此 id 存储在 db 中,并与 DB 中的条目相关联,该条目表示创建计时器的实体
附加数据结构:为了跟踪 Timer 实例(为每个计时器创建实例化),我有一个 WeakRef Dictionary 将 id 映射到 obj
所以本质上,我在我的主要 Django 项目的内存中有 2 个数据结构。
问题陈述:
由于 celery worker 需要遍历计时器列表并且还可能修改 id2obj 映射,看起来我需要找到一种方法在我的 celery worker 和 main 之间共享状态
通过 SO/Google,我发现以下建议
- 经理
- 共享内存
不幸的是,bisect wrapper 不适合酸洗和/或状态共享。我通过创建一个字典并尝试将排序列表嵌入到字典中来尝试管理器方法。它出现了一个错误(我猜是因为排序列表持有的内存没有共享并将其嵌入到“共享”内存对象将不起作用)
最后......问题:
- 有没有办法可以与工作线程共享我的 SortedCollection 和 Weakref Dict
替代解决方案:
如何保持工作线程简单...让它在每个滴答声中写入 DB,然后使用 post Db 信号在主线程上获得通知并在主线程中执行过期计时器的处理。当然,缺点是我失去了并行化。