Pass object instantiations through a cacher.
I want the system to only have one instance of a particular object at any time, so that we can effectively cache things in them.
This commit is contained in:
		
							parent
							
								
									11fda94968
								
							
						
					
					
						commit
						40c255b0d0
					
				
					 1 changed files with 43 additions and 24 deletions
				
			
		|  | @ -106,7 +106,7 @@ class PDBAlbumMixin: | ||||||
|         } |         } | ||||||
|         self.sql_insert(table='albums', data=data) |         self.sql_insert(table='albums', data=data) | ||||||
| 
 | 
 | ||||||
|         album = objects.Album(self, data) |         album = self.get_cached_instance('album', data) | ||||||
| 
 | 
 | ||||||
|         if associated_directory is not None: |         if associated_directory is not None: | ||||||
|             album.add_associated_directory(associated_directory, commit=False) |             album.add_associated_directory(associated_directory, commit=False) | ||||||
|  | @ -151,7 +151,7 @@ class PDBBookmarkMixin: | ||||||
|         } |         } | ||||||
|         self.sql_insert(table='bookmarks', data=data) |         self.sql_insert(table='bookmarks', data=data) | ||||||
| 
 | 
 | ||||||
|         bookmark = objects.Bookmark(self, data) |         bookmark = self.get_cached_instance('bookmark', data) | ||||||
|         if commit: |         if commit: | ||||||
|             self.log.debug('Committing - new Bookmark') |             self.log.debug('Committing - new Bookmark') | ||||||
|             self.commit() |             self.commit() | ||||||
|  | @ -180,7 +180,7 @@ class PDBPhotoMixin: | ||||||
|         photo_row = self.sql_select_one(query, bindings) |         photo_row = self.sql_select_one(query, bindings) | ||||||
|         if photo_row is None: |         if photo_row is None: | ||||||
|             raise exceptions.NoSuchPhoto(filepath) |             raise exceptions.NoSuchPhoto(filepath) | ||||||
|         photo = objects.Photo(self, photo_row) |         photo = self.get_cached_instance('photo', photo_row) | ||||||
|         return photo |         return photo | ||||||
| 
 | 
 | ||||||
|     def get_photos_by_id(self, ids): |     def get_photos_by_id(self, ids): | ||||||
|  | @ -196,7 +196,7 @@ class PDBPhotoMixin: | ||||||
|         query = 'SELECT * FROM photos ORDER BY created DESC' |         query = 'SELECT * FROM photos ORDER BY created DESC' | ||||||
|         photo_rows = self.sql_select(query) |         photo_rows = self.sql_select(query) | ||||||
|         for photo_row in photo_rows: |         for photo_row in photo_rows: | ||||||
|             photo = objects.Photo(self, photo_row) |             photo = self.get_cached_instance('photo', photo_row) | ||||||
|             yield photo |             yield photo | ||||||
| 
 | 
 | ||||||
|             if count is None: |             if count is None: | ||||||
|  | @ -260,7 +260,7 @@ class PDBPhotoMixin: | ||||||
|         } |         } | ||||||
|         self.sql_insert(table='photos', data=data) |         self.sql_insert(table='photos', data=data) | ||||||
| 
 | 
 | ||||||
|         photo = objects.Photo(self, data) |         photo = self.get_cached_instance('photo', data) | ||||||
| 
 | 
 | ||||||
|         if do_metadata: |         if do_metadata: | ||||||
|             photo.reload_metadata(commit=False) |             photo.reload_metadata(commit=False) | ||||||
|  | @ -635,7 +635,7 @@ class PDBPhotoMixin: | ||||||
|         generator = self.sql_select(query, bindings) |         generator = self.sql_select(query, bindings) | ||||||
|         photos_received = 0 |         photos_received = 0 | ||||||
|         for row in generator: |         for row in generator: | ||||||
|             photo = objects.Photo(self, row) |             photo = self.get_cached_instance('photo', row) | ||||||
| 
 | 
 | ||||||
|             if mimetype and photo.simple_mimetype not in mimetype: |             if mimetype and photo.simple_mimetype not in mimetype: | ||||||
|                 continue |                 continue | ||||||
|  | @ -827,7 +827,6 @@ class PDBTagMixin: | ||||||
|         except (exceptions.TagTooShort, exceptions.TagTooLong): |         except (exceptions.TagTooShort, exceptions.TagTooLong): | ||||||
|             raise exceptions.NoSuchTag(tagname) |             raise exceptions.NoSuchTag(tagname) | ||||||
| 
 | 
 | ||||||
|         tag_row = None |  | ||||||
|         while True: |         while True: | ||||||
|             # Return if it's a toplevel... |             # Return if it's a toplevel... | ||||||
|             tag_row = self.sql_select_one('SELECT * FROM tags WHERE name == ?', [tagname]) |             tag_row = self.sql_select_one('SELECT * FROM tags WHERE name == ?', [tagname]) | ||||||
|  | @ -843,11 +842,7 @@ class PDBTagMixin: | ||||||
|                 raise exceptions.NoSuchTag(tagname) |                 raise exceptions.NoSuchTag(tagname) | ||||||
|             tagname = name_row[0] |             tagname = name_row[0] | ||||||
| 
 | 
 | ||||||
|         tag_id = tag_row[constants.SQL_INDEX['tags']['id']] |         tag = self.get_cached_instance('tag', tag_row) | ||||||
|         tag = self.caches['tag'].get(tag_id, fallback=None) |  | ||||||
|         if tag is None: |  | ||||||
|             tag = objects.Tag(self, tag_row) |  | ||||||
|             self.caches['tag'][tag_id] = tag |  | ||||||
|         return tag |         return tag | ||||||
| 
 | 
 | ||||||
|     def get_tags(self): |     def get_tags(self): | ||||||
|  | @ -885,7 +880,7 @@ class PDBTagMixin: | ||||||
|         if commit: |         if commit: | ||||||
|             self.log.debug('Committing - new_tag') |             self.log.debug('Committing - new_tag') | ||||||
|             self.commit() |             self.commit() | ||||||
|         tag = objects.Tag(self, data) |         tag = self.get_cached_instance('tag', data) | ||||||
|         return tag |         return tag | ||||||
| 
 | 
 | ||||||
|     def normalize_tagname(self, tagname): |     def normalize_tagname(self, tagname): | ||||||
|  | @ -959,7 +954,7 @@ class PDBUserMixin: | ||||||
|             user_row = self.sql_select_one('SELECT * FROM users WHERE id == ?', [id]) |             user_row = self.sql_select_one('SELECT * FROM users WHERE id == ?', [id]) | ||||||
| 
 | 
 | ||||||
|         if user_row is not None: |         if user_row is not None: | ||||||
|             return objects.User(self, user_row) |             return self.get_cached_instance('user', user_row) | ||||||
|         else: |         else: | ||||||
|             raise exceptions.NoSuchUser(username or id) |             raise exceptions.NoSuchUser(username or id) | ||||||
| 
 | 
 | ||||||
|  | @ -1008,7 +1003,7 @@ class PDBUserMixin: | ||||||
|         if not isinstance(password, bytes): |         if not isinstance(password, bytes): | ||||||
|             password = password.encode('utf-8') |             password = password.encode('utf-8') | ||||||
| 
 | 
 | ||||||
|         user = objects.User(self, user_row) |         user = self.get_cached_instance('user', user_row) | ||||||
| 
 | 
 | ||||||
|         success = bcrypt.checkpw(password, user.password_hash) |         success = bcrypt.checkpw(password, user.password_hash) | ||||||
|         if not success: |         if not success: | ||||||
|  | @ -1045,7 +1040,7 @@ class PDBUserMixin: | ||||||
|             self.log.debug('Committing - register user') |             self.log.debug('Committing - register user') | ||||||
|             self.commit() |             self.commit() | ||||||
| 
 | 
 | ||||||
|         return objects.User(self, data) |         return self.get_cached_instance('user', data) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class PDBUtilMixin: | class PDBUtilMixin: | ||||||
|  | @ -1406,6 +1401,26 @@ class PhotoDB( | ||||||
|             self._cached_frozen_children = tag_export.flat_dict(self.get_tags()) |             self._cached_frozen_children = tag_export.flat_dict(self.get_tags()) | ||||||
|         return self._cached_frozen_children |         return self._cached_frozen_children | ||||||
| 
 | 
 | ||||||
|  |     def get_cached_instance(self, thing_type, db_row): | ||||||
|  |         thing_map = _THING_CLASSES[thing_type] | ||||||
|  | 
 | ||||||
|  |         thing_table = thing_map['table'] | ||||||
|  |         thing_class = thing_map['class'] | ||||||
|  |         thing_cache = self.caches[thing_type] | ||||||
|  |         thing_index = constants.SQL_INDEX[thing_table] | ||||||
|  | 
 | ||||||
|  |         if isinstance(db_row, dict): | ||||||
|  |             thing_id = db_row['id'] | ||||||
|  |         else: | ||||||
|  |             thing_id = db_row[thing_index['id']] | ||||||
|  | 
 | ||||||
|  |         try: | ||||||
|  |             thing = thing_cache[thing_id] | ||||||
|  |         except KeyError: | ||||||
|  |             thing = thing_class(self, db_row) | ||||||
|  |             thing_cache[thing_id] = thing | ||||||
|  |         return thing | ||||||
|  | 
 | ||||||
|     def get_cached_qualname_map(self): |     def get_cached_qualname_map(self): | ||||||
|         if self._cached_qualname_map is None: |         if self._cached_qualname_map is None: | ||||||
|             self._cached_qualname_map = tag_export.qualified_names(self.get_tags()) |             self._cached_qualname_map = tag_export.qualified_names(self.get_tags()) | ||||||
|  | @ -1415,20 +1430,20 @@ class PhotoDB( | ||||||
|         thing_map = _THING_CLASSES[thing_type] |         thing_map = _THING_CLASSES[thing_type] | ||||||
| 
 | 
 | ||||||
|         thing_class = thing_map['class'] |         thing_class = thing_map['class'] | ||||||
|         table = thing_map['table'] |         thing_table = thing_map['table'] | ||||||
|         group_table = thing_class.group_table |         group_table = thing_class.group_table | ||||||
| 
 | 
 | ||||||
|         query = ''' |         query = f''' | ||||||
|         SELECT * FROM {table} |         SELECT * FROM {thing_table} | ||||||
|         WHERE NOT EXISTS ( |         WHERE NOT EXISTS ( | ||||||
|             SELECT 1 FROM {group_table} |             SELECT 1 FROM {group_table} | ||||||
|             WHERE memberid == {table}.id |             WHERE memberid == {thing_table}.id | ||||||
|         ) |         ) | ||||||
|         '''.format(table=table, group_table=group_table) |         ''' | ||||||
| 
 | 
 | ||||||
|         rows = self.sql_select(query) |         rows = self.sql_select(query) | ||||||
|         for row in rows: |         for row in rows: | ||||||
|             thing = thing_class(self, row) |             thing = self.get_cached_instance(thing_type, row) | ||||||
|             yield thing |             yield thing | ||||||
| 
 | 
 | ||||||
|     def get_thing_by_id(self, thing_type, thing_id): |     def get_thing_by_id(self, thing_type, thing_id): | ||||||
|  | @ -1460,7 +1475,7 @@ class PhotoDB( | ||||||
| 
 | 
 | ||||||
|         things = self.sql_select(query) |         things = self.sql_select(query) | ||||||
|         for thing_row in things: |         for thing_row in things: | ||||||
|             thing = thing_map['class'](self, db_row=thing_row) |             thing = self.get_cached_instance(thing_type, thing_row) | ||||||
|             yield thing |             yield thing | ||||||
| 
 | 
 | ||||||
|     def get_things_by_id(self, thing_type, thing_ids): |     def get_things_by_id(self, thing_type, thing_ids): | ||||||
|  | @ -1487,7 +1502,11 @@ class PhotoDB( | ||||||
|             query = 'SELECT * FROM %s WHERE id IN %s' % (thing_map['table'], qmarks) |             query = 'SELECT * FROM %s WHERE id IN %s' % (thing_map['table'], qmarks) | ||||||
|             more_things = self.sql_select(query, id_batch) |             more_things = self.sql_select(query, id_batch) | ||||||
|             for thing_row in more_things: |             for thing_row in more_things: | ||||||
|                 thing = thing_map['class'](self, db_row=thing_row) |                 # Normally we would call `get_cached_instance` instead of | ||||||
|  |                 # constructing here. But we already know for a fact that this | ||||||
|  |                 # object is not in the cache because it made it past the | ||||||
|  |                 # previous loop. | ||||||
|  |                 thing = thing_class(self, db_row=thing_row) | ||||||
|                 thing_cache[thing.id] = thing |                 thing_cache[thing.id] = thing | ||||||
|                 yield thing |                 yield thing | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue