mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -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:
|
if db is None:
|
||||||
raise HTTPNotFound('Library %r not found' % library_id)
|
raise HTTPNotFound('Library %r not found' % library_id)
|
||||||
with db.safe_read_lock:
|
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)
|
raise HTTPNotFound('Book with id %r does not exist' % book_id)
|
||||||
library_id = db.server_library_id # in case library_id was None
|
library_id = db.server_library_id # in case library_id was None
|
||||||
if what == 'thumb':
|
if what == 'thumb':
|
||||||
|
@ -7,6 +7,7 @@ __license__ = 'GPL v3'
|
|||||||
__copyright__ = '2015, Kovid Goyal <kovid at kovidgoyal.net>'
|
__copyright__ = '2015, Kovid Goyal <kovid at kovidgoyal.net>'
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
from collections import OrderedDict
|
||||||
from importlib import import_module
|
from importlib import import_module
|
||||||
from threading import Lock
|
from threading import Lock
|
||||||
|
|
||||||
@ -14,6 +15,7 @@ from calibre import force_unicode
|
|||||||
from calibre.db.cache import Cache
|
from calibre.db.cache import Cache
|
||||||
from calibre.db.legacy import create_backend, LibraryDatabase
|
from calibre.db.legacy import create_backend, LibraryDatabase
|
||||||
from calibre.srv.routes import Router
|
from calibre.srv.routes import Router
|
||||||
|
from calibre.utils.date import utcnow
|
||||||
|
|
||||||
def init_library(library_path):
|
def init_library(library_path):
|
||||||
db = Cache(create_backend(library_path))
|
db = Cache(create_backend(library_path))
|
||||||
@ -36,6 +38,8 @@ class LibraryBroker(object):
|
|||||||
if path is libraries[0]:
|
if path is libraries[0]:
|
||||||
self.default_library = library_id
|
self.default_library = library_id
|
||||||
self.lmap[library_id] = path
|
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):
|
def get(self, library_id=None):
|
||||||
with self.lock:
|
with self.lock:
|
||||||
@ -57,6 +61,8 @@ class Context(object):
|
|||||||
|
|
||||||
log = None
|
log = None
|
||||||
url_for = None
|
url_for = None
|
||||||
|
CATEGORY_CACHE_SIZE = 25
|
||||||
|
SEARCH_CACHE_SIZE = 100
|
||||||
|
|
||||||
def __init__(self, libraries, opts, testing=False):
|
def __init__(self, libraries, opts, testing=False):
|
||||||
self.opts = opts
|
self.opts = opts
|
||||||
@ -72,14 +78,43 @@ class Context(object):
|
|||||||
def get_library(self, library_id=None):
|
def get_library(self, library_id=None):
|
||||||
return self.library_broker.get(library_id)
|
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
|
# TODO: Implement this based on data.username caching result on the
|
||||||
# data object
|
# 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:
|
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
|
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):
|
class Handler(object):
|
||||||
|
|
||||||
def __init__(self, libraries, opts, testing=False):
|
def __init__(self, libraries, opts, testing=False):
|
||||||
|
Loading…
x
Reference in New Issue
Block a user