确实,我会缓存查询结果。您需要决定将结果缓存多长时间,如果长期存储,如何使缓存无效或检查更改。
这些决策没有最佳实践,因为它们完全取决于存储的数据类型和后端的 API。例如,如果它们支持某种新鲜度查询,那么您将永远存储所有内容并轮询后端以查看缓存是否需要更新。
你可以从一个简单的请求缓存开始;每个请求查询一次,将其存储在请求对象上。随着请求对象被清理,您的缓存将在请求结束时自动失效,下一个请求将是一个干净的状态。
如果您的后端用户很少更改,您可以在本地缓存中缓存更长时间的信息。我会在插件上使用 volatile 属性。任何以 开头的属性_v_
都会被持久性机制忽略。因此,存储在_v_
volatile 属性中的任何内容都是线程本地的,并且仅在进程的生命周期内存在,重新启动服务器会自动清除这些。
至少您应该使用_v_
volatile 属性来存储您的后端 SQL 连接。这样它们就可以在请求之间保持打开状态,并且可以重复使用。类似以下方法的方法会很好:
def _connection(self):
# Return a backend connection
if getattr(self, '_v_connection', None) is None:
# Create connection here
self._v_connection = yourdatabaseconnection
return self._v_connection
您还可以在插件上使用持久属性来存储缓存。此缓存将提交给 ZODB 并在重新启动后持续存在。然后,您确实需要弄清楚如何使内容无效;存储时间戳并在旧时驱逐数据等。
您的缓存数据结构完全取决于您的应用程序需求。如果您不保留信息,那么字典(用户名-> 信息)可能就足够了。持久化缓存可以从使用 aOOBTree
而不是字典中受益,因为它们减少了不同线程之间发生冲突的机会,并且在处理大量数据时效率更高。
无论您做什么,都不需要使用 Session。会话容易发生冲突,不能很好地扩展,并且无论如何都不是存储这种缓存的地方。