Improve Album bytes caching, start caching photo count.
More careful uncaching of the summed bytes, to minimize recalculation. Fewer cases where the album itself is removed from the photodb's getter cache. This also helps the download link on album pages disappear if the child albums don't actually have any photos.
This commit is contained in:
parent
e1a904da6f
commit
a510c7b55c
3 changed files with 56 additions and 28 deletions
|
@ -85,7 +85,6 @@ class GroupableMixin:
|
||||||
'INSERT INTO %s VALUES(?, ?)' % self.group_table,
|
'INSERT INTO %s VALUES(?, ?)' % self.group_table,
|
||||||
[self.id, member.id]
|
[self.id, member.id]
|
||||||
)
|
)
|
||||||
self._uncache()
|
|
||||||
if commit:
|
if commit:
|
||||||
self.photodb.log.debug('Committing - add to group')
|
self.photodb.log.debug('Committing - add to group')
|
||||||
self.photodb.commit()
|
self.photodb.commit()
|
||||||
|
@ -197,7 +196,6 @@ class GroupableMixin:
|
||||||
'DELETE FROM %s WHERE memberid == ?' % self.group_table,
|
'DELETE FROM %s WHERE memberid == ?' % self.group_table,
|
||||||
[self.id]
|
[self.id]
|
||||||
)
|
)
|
||||||
self._uncache()
|
|
||||||
if commit:
|
if commit:
|
||||||
self.photodb.log.debug('Committing - leave group')
|
self.photodb.log.debug('Committing - leave group')
|
||||||
self.photodb.commit()
|
self.photodb.commit()
|
||||||
|
@ -228,8 +226,10 @@ class Album(ObjectBase, GroupableMixin):
|
||||||
self.description = db_row['description'] or ''
|
self.description = db_row['description'] or ''
|
||||||
self.name = 'Album %s' % self.id
|
self.name = 'Album %s' % self.id
|
||||||
self.group_getter = self.photodb.get_album
|
self.group_getter = self.photodb.get_album
|
||||||
self._sum_bytes_photos = None
|
|
||||||
self._sum_bytes_albums = None
|
self._sum_bytes_local = None
|
||||||
|
self._sum_bytes_recursive = None
|
||||||
|
self._sum_photos_recursive = None
|
||||||
|
|
||||||
def __hash__(self):
|
def __hash__(self):
|
||||||
return hash(self.id)
|
return hash(self.id)
|
||||||
|
@ -238,13 +238,24 @@ class Album(ObjectBase, GroupableMixin):
|
||||||
return 'Album:{id}'.format(id=self.id)
|
return 'Album:{id}'.format(id=self.id)
|
||||||
|
|
||||||
def _uncache(self):
|
def _uncache(self):
|
||||||
|
self._uncache_sums()
|
||||||
self.photodb.caches['album'].remove(self.id)
|
self.photodb.caches['album'].remove(self.id)
|
||||||
self._sum_bytes_photos = None
|
|
||||||
self._sum_bytes_albums = None
|
def _uncache_sums(self):
|
||||||
|
self._sum_photos_recursive = None
|
||||||
|
self._sum_bytes_local = None
|
||||||
|
self._sum_bytes_recursive = None
|
||||||
|
parent = self.parent()
|
||||||
|
if parent is not None:
|
||||||
|
parent._sum_photos_recursive = None
|
||||||
|
parent._sum_bytes_recursive = None
|
||||||
|
|
||||||
|
|
||||||
@decorators.required_feature('album.edit')
|
@decorators.required_feature('album.edit')
|
||||||
def add_child(self, *args, **kwargs):
|
def add_child(self, *args, **kwargs):
|
||||||
return super().add_child(*args, **kwargs)
|
result = super().add_child(*args, **kwargs)
|
||||||
|
self._uncache_sums()
|
||||||
|
return result
|
||||||
|
|
||||||
@decorators.required_feature('album.edit')
|
@decorators.required_feature('album.edit')
|
||||||
@decorators.transaction
|
@decorators.transaction
|
||||||
|
@ -293,7 +304,7 @@ class Album(ObjectBase, GroupableMixin):
|
||||||
self.photodb.log.debug('Adding photo %s to %s' % (photo, self))
|
self.photodb.log.debug('Adding photo %s to %s' % (photo, self))
|
||||||
cur = self.photodb.sql.cursor()
|
cur = self.photodb.sql.cursor()
|
||||||
cur.execute('INSERT INTO album_photo_rel VALUES(?, ?)', [self.id, photo.id])
|
cur.execute('INSERT INTO album_photo_rel VALUES(?, ?)', [self.id, photo.id])
|
||||||
self._uncache()
|
self._uncache_sums()
|
||||||
if commit:
|
if commit:
|
||||||
self.photodb.log.debug('Committing - add photo to album')
|
self.photodb.log.debug('Committing - add photo to album')
|
||||||
self.photodb.commit()
|
self.photodb.commit()
|
||||||
|
@ -369,7 +380,7 @@ class Album(ObjectBase, GroupableMixin):
|
||||||
)
|
)
|
||||||
self.title = title
|
self.title = title
|
||||||
self.description = description
|
self.description = description
|
||||||
self._uncache()
|
|
||||||
if commit:
|
if commit:
|
||||||
self.photodb.log.debug('Committing - edit album')
|
self.photodb.log.debug('Committing - edit album')
|
||||||
self.photodb.commit()
|
self.photodb.commit()
|
||||||
|
@ -386,11 +397,15 @@ class Album(ObjectBase, GroupableMixin):
|
||||||
|
|
||||||
@decorators.required_feature('album.edit')
|
@decorators.required_feature('album.edit')
|
||||||
def join_group(self, *args, **kwargs):
|
def join_group(self, *args, **kwargs):
|
||||||
return super().join_group(*args, **kwargs)
|
result = super().join_group(*args, **kwargs)
|
||||||
|
return result
|
||||||
|
|
||||||
@decorators.required_feature('album.edit')
|
@decorators.required_feature('album.edit')
|
||||||
def leave_group(self, *args, **kwargs):
|
def leave_group(self, *args, **kwargs):
|
||||||
return super().leave_group(*args, **kwargs)
|
parent = self.parent()
|
||||||
|
if parent is not None:
|
||||||
|
parent._uncache_sums()
|
||||||
|
result = super().leave_group(*args, **kwargs)
|
||||||
|
|
||||||
def photos(self):
|
def photos(self):
|
||||||
photos = []
|
photos = []
|
||||||
|
@ -416,27 +431,40 @@ class Album(ObjectBase, GroupableMixin):
|
||||||
'DELETE FROM album_photo_rel WHERE albumid == ? AND photoid == ?',
|
'DELETE FROM album_photo_rel WHERE albumid == ? AND photoid == ?',
|
||||||
[self.id, photo.id]
|
[self.id, photo.id]
|
||||||
)
|
)
|
||||||
self._uncache()
|
self._uncache_sums()
|
||||||
if commit:
|
if commit:
|
||||||
self.photodb.log.debug('Committing - remove photo from album')
|
self.photodb.log.debug('Committing - remove photo from album')
|
||||||
self.photodb.commit()
|
self.photodb.commit()
|
||||||
|
|
||||||
def sum_bytes(self, recurse=True, string=False):
|
def sum_bytes(self, recurse=True, string=False):
|
||||||
if self._sum_bytes_photos is None:
|
if self._sum_bytes_local is None:
|
||||||
photos = (photo.bytes for photo in self.photos() if photo.bytes is not None)
|
#print(self, 'sumbytes cache miss local')
|
||||||
self._sum_bytes_photos = sum(photos)
|
photos = (photo for photo in self.photos() if photo.bytes is not None)
|
||||||
total = self._sum_bytes_photos
|
self._sum_bytes_local = sum(photo.bytes for photo in photos)
|
||||||
|
total = self._sum_bytes_local
|
||||||
|
|
||||||
if recurse:
|
if recurse:
|
||||||
if self._sum_bytes_albums is None:
|
if self._sum_bytes_recursive is None:
|
||||||
self._sum_bytes_albums = sum(a.sum_bytes(recurse=True) for a in self.children())
|
#print(self, 'sumbytes cache miss recursive')
|
||||||
total += self._sum_bytes_albums
|
child_bytes = sum(child.sum_bytes(recurse=True) for child in self.children())
|
||||||
|
self._sum_bytes_recursive = self._sum_bytes_local + child_bytes
|
||||||
|
total = self._sum_bytes_recursive
|
||||||
|
|
||||||
if string:
|
if string:
|
||||||
return bytestring.bytestring(total)
|
return bytestring.bytestring(total)
|
||||||
else:
|
else:
|
||||||
return total
|
return total
|
||||||
|
|
||||||
|
def sum_photos(self):
|
||||||
|
if self._sum_photos_recursive is None:
|
||||||
|
#print(self, 'sumphotos cache miss')
|
||||||
|
total = 0
|
||||||
|
total += sum(1 for x in self.photos())
|
||||||
|
total += sum(child.sum_photos() for child in self.children())
|
||||||
|
self._sum_photos_recursive = total
|
||||||
|
|
||||||
|
return self._sum_photos_recursive
|
||||||
|
|
||||||
def walk_photos(self):
|
def walk_photos(self):
|
||||||
yield from self.photos()
|
yield from self.photos()
|
||||||
children = self.walk_children()
|
children = self.walk_children()
|
||||||
|
|
|
@ -1387,12 +1387,9 @@ class PhotoDB(PDBAlbumMixin, PDBBookmarkMixin, PDBPhotoMixin, PDBTagMixin, PDBUs
|
||||||
if isinstance(thing_id, thing_map['class']):
|
if isinstance(thing_id, thing_map['class']):
|
||||||
thing_id = thing_id.id
|
thing_id = thing_id.id
|
||||||
|
|
||||||
cache = {
|
cache = self.caches[thing_type]
|
||||||
'album': self._album_cache,
|
|
||||||
'photo': self._photo_cache,
|
|
||||||
'tag': self._tag_cache,
|
|
||||||
}[thing_type]
|
|
||||||
try:
|
try:
|
||||||
|
#self.log.debug('Cache hit for %s %s', thing_type, thing_id)
|
||||||
val = cache[thing_id]
|
val = cache[thing_id]
|
||||||
return val
|
return val
|
||||||
except KeyError:
|
except KeyError:
|
||||||
|
|
|
@ -91,16 +91,19 @@ p
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
{% if photos or sub_albums %}
|
{% set has_local_photos = photos|length > 0 %}
|
||||||
|
{% set has_child_photos = album.sum_photos() > photos|length %}
|
||||||
|
{% if has_local_photos or has_child_photos %}
|
||||||
Download:
|
Download:
|
||||||
{% if photos %}
|
{% if has_local_photos %}
|
||||||
<a href="/album/{{album.id}}.zip?recursive=no">
|
<a href="/album/{{album.id}}.zip?recursive=no">
|
||||||
These files ({{album.sum_bytes(recurse=False, string=True)}})
|
These files ({{album.sum_bytes(recurse=False, string=True)}})
|
||||||
</a>
|
</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if photos and sub_albums %}—{% endif %}
|
{% if has_local_photos and has_child_photos %}—{% endif %}
|
||||||
{% if sub_albums %}
|
{% if has_child_photos %}
|
||||||
<a href="/album/{{album.id}}.zip?recursive=yes">
|
<a href="/album/{{album.id}}.zip?recursive=yes">
|
||||||
Include children ({{album.sum_bytes(recurse=True, string=True)}})
|
Include children ({{album.sum_bytes(recurse=True, string=True)}})
|
||||||
</a>
|
</a>
|
||||||
|
|
Loading…
Reference in a new issue