From ff333971ccba352df968f39e17bf617232a9bea8 Mon Sep 17 00:00:00 2001 From: Dariusz Kedzierski <dkedzierski@syncad.com> Date: Mon, 22 Jun 2020 14:14:41 +0200 Subject: [PATCH] Cache for votes, unique constraint fix for feed_cache --- hive/db/schema.py | 1 + hive/indexer/blocks.py | 2 ++ hive/indexer/feed_cache.py | 2 +- hive/indexer/votes.py | 68 ++++++++++++++++++++++++-------------- 4 files changed, 48 insertions(+), 25 deletions(-) diff --git a/hive/db/schema.py b/hive/db/schema.py index 0548c6ea6..55b3bc09f 100644 --- a/hive/db/schema.py +++ b/hive/db/schema.py @@ -266,6 +266,7 @@ def build_metadata(): sa.Column('account_id', sa.Integer, nullable=False), sa.Column('created_at', sa.DateTime, nullable=False), sa.Index('hive_feed_cache_account_id', 'account_id'), # API (and rebuild?) + sa.UniqueConstraint('account_id', 'post_id', name='hive_feed_cache_ux1') ) sa.Table( diff --git a/hive/indexer/blocks.py b/hive/indexer/blocks.py index 9ee315fe1..bb6e0ec36 100644 --- a/hive/indexer/blocks.py +++ b/hive/indexer/blocks.py @@ -38,6 +38,7 @@ class Blocks: #assert is_trx_active(), "Block.process must be in a trx" ret = cls._process(block, vops_in_block, hived, is_initial_sync=False) PostDataCache.flush() + Votes.flush() return ret @classmethod @@ -57,6 +58,7 @@ class Blocks: # expensive. So is tracking follows at all; hence we track # deltas in memory and update follow/er counts in bulk. PostDataCache.flush() + Votes.flush() cls._flush_blocks() Follow.flush(trx=False) diff --git a/hive/indexer/feed_cache.py b/hive/indexer/feed_cache.py index d302a6020..f263b3833 100644 --- a/hive/indexer/feed_cache.py +++ b/hive/indexer/feed_cache.py @@ -22,7 +22,7 @@ class FeedCache: assert not DbState.is_initial_sync(), 'writing to feed cache in sync' sql = """INSERT INTO hive_feed_cache (account_id, post_id, created_at) VALUES (:account_id, :id, :created_at) - ON CONFLICT (account_id, post_id) DO NOTHING""" + ON CONFLICT ON CONSTRAINT hive_feed_cache_ux1 DO NOTHING""" DB.query(sql, account_id=account_id, id=post_id, created_at=created_at) @classmethod diff --git a/hive/indexer/votes.py b/hive/indexer/votes.py index 76f248951..9c55b7645 100644 --- a/hive/indexer/votes.py +++ b/hive/indexer/votes.py @@ -9,6 +9,7 @@ DB = Db.instance() class Votes: """ Class for managing posts votes """ + _votes_data = {} @classmethod def get_vote_count(cls, author, permlink): @@ -57,28 +58,47 @@ class Votes: voter = vop['value']['voter'] author = vop['value']['author'] permlink = vop['value']['permlink'] - vote_percent = vop['value']['vote_percent'] - weight = vop['value']['weight'] - rshares = vop['value']['rshares'] - sql = """ - INSERT INTO hive_votes - (post_id, voter_id, author_id, permlink_id, weight, rshares, vote_percent, last_update) - SELECT hp.id, ha_v.id, ha_a.id, hpd_p.id, :weight, :rshares, :vote_percent, :last_update - FROM hive_accounts ha_v, - hive_posts hp - INNER JOIN hive_accounts ha_a ON ha_a.id = hp.author_id - INNER JOIN hive_permlink_data hpd_p ON hpd_p.id = hp.permlink_id - WHERE ha_a.name = :author AND hpd_p.permlink = :permlink AND ha_v.name = :voter - ON CONFLICT ON CONSTRAINT hive_votes_ux1 DO - UPDATE - SET - weight = EXCLUDED.weight, - rshares = EXCLUDED.rshares, - vote_percent = EXCLUDED.vote_percent, - last_update = EXCLUDED.last_update, - num_changes = hive_votes.num_changes + 1 - WHERE hive_votes.id = EXCLUDED.id - """ - DB.query(sql, voter=voter, author=author, permlink=permlink, weight=weight, rshares=rshares, - vote_percent=vote_percent, last_update=date) + key = voter + "/" + author + "/" + permlink + + cls._votes_data[key] = dict(voter=voter, + author=author, + permlink=permlink, + vote_percent=vop['value']['vote_percent'], + weight=vop['value']['weight'], + rshares=vop['value']['rshares'], + last_update=date) + + @classmethod + def flush(cls): + """ Flush vote data from cache to database """ + if cls._votes_data: + sql = """ + INSERT INTO hive_votes + (post_id, voter_id, author_id, permlink_id, weight, rshares, vote_percent, last_update) + """ + values = [] + for _, vd in cls._votes_data.items(): + values.append(""" + SELECT hp.id, ha_v.id, ha_a.id, hpd_p.id, {}, {}, {}, '{}'::timestamp + FROM hive_accounts ha_v, + hive_posts hp + INNER JOIN hive_accounts ha_a ON ha_a.id = hp.author_id + INNER JOIN hive_permlink_data hpd_p ON hpd_p.id = hp.permlink_id + WHERE ha_a.name = '{}' AND hpd_p.permlink = '{}' AND ha_v.name = '{}' + """.format(vd['weight'], vd['rshares'], vd['vote_percent'], vd['last_update'], vd['author'], vd['permlink'], vd['voter'])) + sql += ' UNION ALL '.join(values) + + sql += """ + ON CONFLICT ON CONSTRAINT hive_votes_ux1 DO + UPDATE + SET + weight = EXCLUDED.weight, + rshares = EXCLUDED.rshares, + vote_percent = EXCLUDED.vote_percent, + last_update = EXCLUDED.last_update, + num_changes = hive_votes.num_changes + 1 + WHERE hive_votes.id = EXCLUDED.id + """ + DB.query(sql) + cls._votes_data.clear() -- GitLab