diff options
| author | rr- | 2016-08-26 14:59:14 +0200 |
|---|---|---|
| committer | rr- | 2016-08-26 15:09:08 +0200 |
| commit | ffb87f1650885a6227471634825dc28ed3d6737a (patch) | |
| tree | 38b5d3bc0410f053f35b23dd9a872203180f635f /server/szurubooru/func/posts.py | |
| parent | bb369efa995f6ca2f07415f9d0890582f6e17627 (diff) | |
server/posts: defer flush; save content lazily
Rather than flushing the post right away only to find out that there
were validation errors, try to postpone flushing for as long as
possible.
The previous behavior has led to too eager spending of post IDs - each
flush calls nextval(post_id_seq), and postgres sequences are not
affected by transaction rollbacks, so each erroneous post creation
discarded a post ID, which has led to gaps in post IDs.
Diffstat (limited to 'server/szurubooru/func/posts.py')
| -rw-r--r-- | server/szurubooru/func/posts.py | 52 |
1 files changed, 39 insertions, 13 deletions
diff --git a/server/szurubooru/func/posts.py b/server/szurubooru/func/posts.py index 31ab8d1..b7ffe2b 100644 --- a/server/szurubooru/func/posts.py +++ b/server/szurubooru/func/posts.py @@ -86,6 +86,7 @@ def get_post_thumbnail_url(post): def get_post_content_path(post): assert post + assert post.post_id return 'posts/%d.%s' % ( post.post_id, mime.get_extension(post.mime_type) or 'dat') @@ -217,12 +218,10 @@ def create_post(content, tag_names, user): post.creation_time = datetime.datetime.utcnow() post.flags = [] - # we'll need post ID post.type = '' post.checksum = '' post.mime_type = '' db.session.add(post) - db.session.flush() update_post_content(post, content) new_tags = update_post_tags(post, tag_names) @@ -245,6 +244,38 @@ def update_post_source(post, source): post.source = source +@sqlalchemy.events.event.listens_for(db.Post, 'after_insert') +def _after_post_insert(_mapper, _connection, post): + _sync_post_content(post) + + +@sqlalchemy.events.event.listens_for(db.Post, 'after_update') +def _after_post_update(_mapper, _connection, post): + _sync_post_content(post) + + +def _sync_post_content(post): + regenerate_thumb = False + + if hasattr(post, '__content'): + files.save(get_post_content_path(post), getattr(post, '__content')) + delattr(post, '__content') + regenerate_thumb = True + + if hasattr(post, '__thumbnail'): + if getattr(post, '__thumbnail'): + files.save( + get_post_thumbnail_backup_path(post), + getattr(post, '__thumbnail')) + else: + files.delete(get_post_thumbnail_backup_path(post)) + delattr(post, '__thumbnail') + regenerate_thumb = True + + if regenerate_thumb: + generate_post_thumbnail(post) + + def update_post_content(post, content): assert post if not content: @@ -269,7 +300,9 @@ def update_post_content(post, content): .filter(db.Post.checksum == post.checksum) \ .filter(db.Post.post_id != post.post_id) \ .one_or_none() - if other_post: + if other_post \ + and other_post.post_id \ + and other_post.post_id != post.post_id: raise PostAlreadyUploadedError( 'Post already uploaded (%d)' % other_post.post_id) @@ -284,19 +317,12 @@ def update_post_content(post, content): if post.canvas_width <= 0 or post.canvas_height <= 0: post.canvas_width = None post.canvas_height = None - files.save(get_post_content_path(post), content) - update_post_thumbnail(post, content=None, do_delete=False) + setattr(post, '__content', content) -def update_post_thumbnail(post, content=None, do_delete=True): +def update_post_thumbnail(post, content=None): assert post - if not content: - content = files.get(get_post_content_path(post)) - if do_delete: - files.delete(get_post_thumbnail_backup_path(post)) - else: - files.save(get_post_thumbnail_backup_path(post), content) - generate_post_thumbnail(post) + setattr(post, '__thumbnail', content) def generate_post_thumbnail(post): |