Skip to content

Commit

Permalink
Non transactional cache hit/miss statistics
Browse files Browse the repository at this point in the history
  • Loading branch information
ddorian committed Mar 4, 2024
1 parent ebfa37c commit e2f3f31
Showing 1 changed file with 61 additions and 27 deletions.
88 changes: 61 additions & 27 deletions diskcache/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -1120,7 +1120,7 @@ def decr(self, key, delta=1, default=0, retry=False):
"""
return self.incr(key, -delta, default, retry)

def get(
def __get(
self,
key,
default=None,
Expand Down Expand Up @@ -1154,42 +1154,35 @@ def get(
' AND (expire_time IS NULL OR expire_time > ?)'
)

did_cache_hit: bool = False

if expire_time and tag:
default = (default, None, None)
elif expire_time or tag:
default = (default, None)

if not self.statistics and update_column is None:
if update_column is None:
# Fast path, no transaction necessary.

rows = self._sql(select, (db_key, raw, time.time())).fetchall()

if not rows:
return default
return (default, did_cache_hit)

((rowid, db_expire_time, db_tag, mode, filename, db_value),) = rows

try:
value = self._disk.fetch(mode, filename, db_value, read)
except IOError:
# Key was deleted before we could retrieve result.
return default
return (default, did_cache_hit)

else: # Slow path, transaction required.
cache_hit = (
'UPDATE Settings SET value = value + 1 WHERE key = "hits"'
)
cache_miss = (
'UPDATE Settings SET value = value + 1 WHERE key = "misses"'
)

with self._transact(retry) as (sql, _):
rows = sql(select, (db_key, raw, time.time())).fetchall()

if not rows:
if self.statistics:
sql(cache_miss)
return default
return (default, did_cache_hit)

(
(rowid, db_expire_time, db_tag, mode, filename, db_value),
Expand All @@ -1199,27 +1192,68 @@ def get(
value = self._disk.fetch(mode, filename, db_value, read)
except IOError:
# Key was deleted before we could retrieve result.
if self.statistics:
sql(cache_miss)
return default

if self.statistics:
sql(cache_hit)

now = time.time()
update = 'UPDATE Cache SET %s WHERE rowid = ?'
return (default, did_cache_hit)

if update_column is not None:
now = time.time()
update = 'UPDATE Cache SET %s WHERE rowid = ?'
sql(update % update_column.format(now=now), (rowid,))

did_cache_hit = True

if expire_time and tag:
return (value, db_expire_time, db_tag)
return ((value, db_expire_time, db_tag), did_cache_hit)
elif expire_time:
return (value, db_expire_time)
return ((value, db_expire_time), did_cache_hit)
elif tag:
return (value, db_tag)
return ((value, db_tag), did_cache_hit)
else:
return value
return value, did_cache_hit

def get(
self,
key,
default=None,
read=False,
expire_time=False,
tag=False,
retry=False,
):
"""Retrieve value from cache. If `key` is missing, return `default`.
Raises :exc:`Timeout` error when database timeout occurs and `retry` is
`False` (default).
:param key: key for item
:param default: value to return if key is missing (default None)
:param bool read: if True, return file handle to value
(default False)
:param bool expire_time: if True, return expire_time in tuple
(default False)
:param bool tag: if True, return tag in tuple (default False)
:param bool retry: retry if database timeout occurs (default False)
:return: value for item or default if key not found
:raises Timeout: if database timeout occurs
"""
data, did_cache_hit = self.__get(
key, default, read, expire_time, tag, retry
)

if self.statistics:
self.track_statistics(did_cache_hit)
return data

def track_statistics(self, did_cache_hit: bool):
"""Track statistics about cache. Can be overridden for custom functionality."""
cache_hit = 'UPDATE Settings SET value = value + 1 WHERE key = "hits"'
cache_miss = (
'UPDATE Settings SET value = value + 1 WHERE key = "misses"'
)
if did_cache_hit is True:
self._sql(cache_hit)
elif did_cache_hit is False:
self._sql(cache_miss)

def __getitem__(self, key):
"""Return corresponding value for `key` from cache.
Expand Down

0 comments on commit e2f3f31

Please sign in to comment.