mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-08 18:54:09 -04:00
Server: Implement caching for get_categories() and search()
This commit is contained in:
parent
c10ba11e30
commit
c29015a3ad
@ -205,7 +205,7 @@ def get(ctx, rd, what, book_id, library_id):
|
||||
if db is None:
|
||||
raise HTTPNotFound('Library %r not found' % library_id)
|
||||
with db.safe_read_lock:
|
||||
if not db.has_id(book_id):
|
||||
if book_id not in ctx.allowed_book_ids(rd, db):
|
||||
raise HTTPNotFound('Book with id %r does not exist' % book_id)
|
||||
library_id = db.server_library_id # in case library_id was None
|
||||
if what == 'thumb':
|
||||
|
@ -7,6 +7,7 @@ __license__ = 'GPL v3'
|
||||
__copyright__ = '2015, Kovid Goyal <kovid at kovidgoyal.net>'
|
||||
|
||||
import os
|
||||
from collections import OrderedDict
|
||||
from importlib import import_module
|
||||
from threading import Lock
|
||||
|
||||
@ -14,6 +15,7 @@ from calibre import force_unicode
|
||||
from calibre.db.cache import Cache
|
||||
from calibre.db.legacy import create_backend, LibraryDatabase
|
||||
from calibre.srv.routes import Router
|
||||
from calibre.utils.date import utcnow
|
||||
|
||||
def init_library(library_path):
|
||||
db = Cache(create_backend(library_path))
|
||||
@ -36,6 +38,8 @@ class LibraryBroker(object):
|
||||
if path is libraries[0]:
|
||||
self.default_library = library_id
|
||||
self.lmap[library_id] = path
|
||||
self.category_caches = {lid:OrderedDict() for lid in self.lmap}
|
||||
self.search_caches = {lid:OrderedDict() for lid in self.lmap}
|
||||
|
||||
def get(self, library_id=None):
|
||||
with self.lock:
|
||||
@ -57,6 +61,8 @@ class Context(object):
|
||||
|
||||
log = None
|
||||
url_for = None
|
||||
CATEGORY_CACHE_SIZE = 25
|
||||
SEARCH_CACHE_SIZE = 100
|
||||
|
||||
def __init__(self, libraries, opts, testing=False):
|
||||
self.opts = opts
|
||||
@ -72,14 +78,43 @@ class Context(object):
|
||||
def get_library(self, library_id=None):
|
||||
return self.library_broker.get(library_id)
|
||||
|
||||
def restrict_to_ids(self, db, data):
|
||||
def allowed_book_ids(self, data, db):
|
||||
# TODO: Implement this based on data.username caching result on the
|
||||
# data object
|
||||
ans = data.restrict_to_ids.get(db.server_library_id)
|
||||
ans = data.allowed_book_ids.get(db.server_library_id)
|
||||
if ans is None:
|
||||
ans = data.restrict_to_ids[db.server_library_id] = db.all_book_ids()
|
||||
ans = data.allowed_book_ids[db.server_library_id] = db.all_book_ids()
|
||||
return ans
|
||||
|
||||
def get_categories(self, data, db, restrict_to_ids=None):
|
||||
if restrict_to_ids is None:
|
||||
restrict_to_ids = self.allowed_book_ids(data, db)
|
||||
cache = self.library_broker.category_caches[db.server_library_id]
|
||||
old = cache.pop(restrict_to_ids, None)
|
||||
if old is None or old[0] <= db.last_modified():
|
||||
categories = db.get_categories(book_ids=restrict_to_ids)
|
||||
cache[restrict_to_ids] = old = (utcnow(), categories)
|
||||
if len(cache) > self.CATEGORY_CACHE_SIZE:
|
||||
cache.popitem(last=False)
|
||||
else:
|
||||
cache[restrict_to_ids] = old
|
||||
return old[1]
|
||||
|
||||
def search(self, data, db, query, restrict_to_ids=None):
|
||||
if restrict_to_ids is None:
|
||||
restrict_to_ids = self.allowed_book_ids(data, db)
|
||||
cache = self.library_broker.search_caches[db.server_library_id]
|
||||
key = (query, restrict_to_ids)
|
||||
old = cache.pop(key, None)
|
||||
if old is None or old[0] < db.clear_search_cache_count:
|
||||
matches = db.search(query, book_ids=restrict_to_ids)
|
||||
cache[key] = old = (db.clear_search_cache_count, matches)
|
||||
if len(self._search_cache) > self.SEARCH_CACHE_SIZE:
|
||||
cache.popitem(last=False)
|
||||
else:
|
||||
cache[key] = old
|
||||
return old[1]
|
||||
|
||||
class Handler(object):
|
||||
|
||||
def __init__(self, libraries, opts, testing=False):
|
||||
|
Loading…
x
Reference in New Issue
Block a user