diff --git a/hive/db/db_state.py b/hive/db/db_state.py index 937983780ae97fef34d802fc5ef36798fcf0b197..405b944e297b73bd680912478a0f4b451ef38e9e 100644 --- a/hive/db/db_state.py +++ b/hive/db/db_state.py @@ -128,7 +128,6 @@ class DbState: #'hive_posts_cache_ix32', # API: community created #'hive_posts_cache_ix33', # API: community payout #'hive_posts_cache_ix34', # API: community muted - 'hive_accounts_ix1', # (cached_at, name) 'hive_accounts_ix5' # (cached_at, name) ] @@ -297,7 +296,6 @@ class DbState: cls._set_ver(3) if cls._ver == 3: - cls.db().query("CREATE INDEX hive_accounts_ix3 ON hive_accounts (vote_weight, name varchar_pattern_ops)") cls._set_ver(4) if cls._ver == 4: diff --git a/hive/db/schema.py b/hive/db/schema.py index fe8a6a0bd0ed26a41f4fa1c90dca82d8b23a53ae..6106881af8ece89721d2ce529a6d973dd1110aee 100644 --- a/hive/db/schema.py +++ b/hive/db/schema.py @@ -49,19 +49,15 @@ def build_metadata(): sa.Column('following', sa.Integer, nullable=False, server_default='0'), sa.Column('proxy', VARCHAR(16), nullable=False, server_default=''), - sa.Column('post_count', sa.Integer, nullable=False, server_default='0'), sa.Column('proxy_weight', sa.Float(precision=6), nullable=False, server_default='0'), - sa.Column('vote_weight', sa.Float(precision=6), nullable=False, server_default='0'), sa.Column('kb_used', sa.Integer, nullable=False, server_default='0'), # deprecated sa.Column('rank', sa.Integer, nullable=False, server_default='0'), sa.Column('lastread_at', sa.DateTime, nullable=False, server_default='1970-01-01 00:00:00'), - sa.Column('active_at', sa.DateTime, nullable=False, server_default='1970-01-01 00:00:00'), sa.Column('cached_at', sa.DateTime, nullable=False, server_default='1970-01-01 00:00:00'), sa.Column('raw_json', sa.Text), sa.UniqueConstraint('name', name='hive_accounts_ux1'), - sa.Index('hive_accounts_ix1', 'vote_weight'), # core: quick ranks sa.Index('hive_accounts_ix5', 'cached_at'), # core/listen sweep ) @@ -560,6 +556,74 @@ def setup(db): """ db.query_no_return(sql) + # In original hivemind, a value of 'active_at' was calculated from + # max + # { + # created ( account_create_operation ), + # last_account_update ( account_update_operation/account_update2_operation ), + # last_post ( comment_operation - only creation ) + # last_root_post ( comment_operation - only creation + only ROOT ), + # last_vote_time ( vote_operation ) + # } + # In order to simplify calculations, `last_account_update` is not taken into consideration, because this updating accounts is very rare + # and posting/voting after an account updating, fixes `active_at` value immediately. + + sql = """ + DROP VIEW IF EXISTS public.hive_accounts_info_view; + + CREATE OR REPLACE VIEW public.hive_accounts_info_view + AS + SELECT + id, + name, + ( + select count(*) post_count + FROM hive_posts hp + WHERE ha.id=hp.author_id + ) post_count, + created_at, + ( + SELECT GREATEST + ( + created_at, + COALESCE( + ( + select max(hp.created_at) + FROM hive_posts hp + WHERE ha.id=hp.author_id + ), + '1970-01-01 00:00:00.0' + ), + COALESCE( + ( + select max(hv.last_update) + from hive_votes hv + WHERE ha.id=hv.voter_id + ), + '1970-01-01 00:00:00.0' + ) + ) + ) active_at, + display_name, + about, + reputation, + profile_image, + location, + website, + cover_image, + rank, + following, + followers, + proxy, + proxy_weight, + lastread_at, + cached_at, + raw_json + FROM + hive_accounts ha + """ + db.query_no_return(sql) + sql = """ DROP VIEW IF EXISTS public.hive_posts_view; diff --git a/hive/indexer/accounts.py b/hive/indexer/accounts.py index bfd9c9382fb51d978b0e69e5ec7a427584316745..455134e01a1a6cd02603d1f38338620a5988d327 100644 --- a/hive/indexer/accounts.py +++ b/hive/indexer/accounts.py @@ -140,13 +140,6 @@ class Accounts: cls._cache_accounts(accounts, steem, trx=trx) return count - @classmethod - def fetch_ranks(cls): - """Rebuild account ranks and store in memory for next update.""" - sql = "SELECT id FROM hive_accounts ORDER BY vote_weight DESC" - for rank, _id in enumerate(DB.query_col(sql)): - cls._ranks[_id] = rank + 1 - @classmethod def _cache_accounts(cls, accounts, steem, trx=True): """Fetch all `accounts` and write to db.""" @@ -170,9 +163,10 @@ class Accounts: """Prepare a SQL query from a steemd account.""" vests = vests_amount(account['vesting_shares']) - vote_weight = (vests - + vests_amount(account['received_vesting_shares']) - - vests_amount(account['delegated_vesting_shares'])) + #Not used. The member `vote_weight` from `hive_accounts` is removed. + # vote_weight = (vests + # + vests_amount(account['received_vesting_shares']) + # - vests_amount(account['delegated_vesting_shares'])) proxy_weight = 0 if account['proxy'] else float(vests) for satoshis in account['proxied_vsf_votes']: @@ -190,21 +184,12 @@ class Accounts: del account['json_metadata'] del account['posting_json_metadata'] - active_at = max(account['created'], - account['last_account_update'], - account['last_post'], - account['last_root_post'], - account['last_vote_time']) - values = { 'name': account['name'], 'created_at': account['created'], 'proxy': account['proxy'], - 'post_count': account['post_count'], 'reputation': rep_log10(account['reputation']), 'proxy_weight': proxy_weight, - 'vote_weight': vote_weight, - 'active_at': active_at, 'cached_at': cached_at, 'display_name': profile['name'], diff --git a/hive/indexer/sync.py b/hive/indexer/sync.py index b3b63123cf632686fea79f6036b2a915ca59e28f..8635f05a298263ee4c30a429c88d3b7f15a5b7f7 100644 --- a/hive/indexer/sync.py +++ b/hive/indexer/sync.py @@ -224,7 +224,6 @@ class Sync: # prefetch id->name and id->rank memory maps Accounts.load_ids() - Accounts.fetch_ranks() # load irredeemables mutes = Mutes( @@ -388,7 +387,6 @@ class Sync: if num % 1200 == 0: #1hr log.warning("head block %d @ %s", num, block['timestamp']) log.info("[LIVE] hourly stats") - Accounts.fetch_ranks() #Community.recalc_pending_payouts() if num % 200 == 0: #10min Community.recalc_pending_payouts() diff --git a/hive/server/bridge_api/objects.py b/hive/server/bridge_api/objects.py index eec588ef24ca68105a1eee78fcaf051279bf7085..ae9969d144a457011da270e74f3af7cb3e4d0f29 100644 --- a/hive/server/bridge_api/objects.py +++ b/hive/server/bridge_api/objects.py @@ -16,10 +16,8 @@ log = logging.getLogger(__name__) async def load_profiles(db, names): """`get_accounts`-style lookup for `get_state` compat layer.""" - sql = """SELECT id, name, display_name, about, reputation, vote_weight, - created_at, post_count, profile_image, location, website, - cover_image, rank, following, followers, active_at - FROM hive_accounts WHERE name IN :names""" + sql = """SELECT * FROM hive_accounts_info_view + WHERE name IN :names""" rows = await db.query_all(sql, names=tuple(names)) return [_condenser_profile_object(row) for row in rows] @@ -197,6 +195,8 @@ def _condenser_profile_object(row): blacklists = Mutes.lists(row['name'], row['reputation']) + #Important. The member `sp` in `stats` is removed, because currently the hivemind doesn't hold any balances. + # The member `vote_weight` from `hive_accounts` is removed as well. return { 'id': row['id'], 'name': row['name'], @@ -206,16 +206,15 @@ def _condenser_profile_object(row): 'reputation': row['reputation'], 'blacklists': blacklists, 'stats': { - 'sp': int(row['vote_weight'] * 0.0005037), 'rank': row['rank'], 'following': row['following'], 'followers': row['followers'], }, 'metadata': { - 'profile': {'name': row['display_name'], - 'about': row['about'], - 'website': row['website'], - 'location': row['location'], + 'profile': {'name': row['display_name'] if row['display_name'] else "", + 'about': row['about'] if row['about'] else "", + 'website': row['website'] if row['website'] else "", + 'location': row['location'] if row['location'] else "", 'cover_image': row['cover_image'], 'profile_image': row['profile_image'], }}} diff --git a/hive/server/condenser_api/cursor.py b/hive/server/condenser_api/cursor.py index 3d4d0ecf5233f76613176a571f814c6e33486075..6a829832db9f07ea04436768e0e4a150a7d35d89 100644 --- a/hive/server/condenser_api/cursor.py +++ b/hive/server/condenser_api/cursor.py @@ -439,11 +439,8 @@ async def get_accounts(db, accounts: list): ret = [] names = ["'{}'".format(a) for a in accounts] - sql = """SELECT created_at, reputation, display_name, about, - location, website, profile_image, cover_image, followers, following, - proxy, post_count, proxy_weight, vote_weight, rank, - lastread_at, active_at, cached_at, raw_json - FROM hive_accounts WHERE name IN ({})""".format(",".join(names)) + sql = """SELECT * + FROM hive_accounts_info_view WHERE name IN ({})""".format(",".join(names)) result = await db.query_all(sql) for row in result: @@ -463,10 +460,11 @@ async def get_accounts(db, accounts: list): account_data['proxy'] = row.proxy account_data['post_count'] = row.post_count account_data['proxy_weight'] = row.proxy_weight - account_data['vote_weight'] = row.vote_weight account_data['rank'] = row.rank account_data['lastread_at'] = row.lastread_at.isoformat() + account_data['active_at'] = row.active_at.isoformat() + account_data['cached_at'] = row.cached_at.isoformat() ret.append(account_data) diff --git a/hive/server/condenser_api/objects.py b/hive/server/condenser_api/objects.py index 4906a7d6aac28a90a8d5d2419803c0dcf6f283bb..ca231cc1d56fc29ce23e5479ffb7f7dd6dfb39c4 100644 --- a/hive/server/condenser_api/objects.py +++ b/hive/server/condenser_api/objects.py @@ -14,10 +14,8 @@ log = logging.getLogger(__name__) async def load_accounts(db, names): """`get_accounts`-style lookup for `get_state` compat layer.""" - sql = """SELECT id, name, display_name, about, reputation, vote_weight, - created_at, post_count, profile_image, location, website, - cover_image - FROM hive_accounts WHERE name IN :names""" + sql = """SELECT * FROM hive_accounts_info_view + WHERE name IN :names""" rows = await db.query_all(sql, names=tuple(names)) return [_condenser_account_object(row) for row in rows] @@ -156,12 +154,13 @@ async def _query_author_rep_map(db, posts): def _condenser_account_object(row): """Convert an internal account record into legacy-steemd style.""" + #The member `vote_weight` from `hive_accounts` is removed, so currently the member `net_vesting_shares` is equals to zero. return { 'name': row['name'], 'created': str(row['created_at']), 'post_count': row['post_count'], 'reputation': rep_to_raw(row['reputation']), - 'net_vesting_shares': row['vote_weight'], + 'net_vesting_shares': 0, 'transfer_history': [], 'json_metadata': json.dumps({ 'profile': {'name': row['display_name'], diff --git a/hive/server/hive_api/objects.py b/hive/server/hive_api/objects.py index 0fb057a173971270d47365ff959f1d4e083eced0..16979379ec14365b812d42ccfdc4ff71708984de 100644 --- a/hive/server/hive_api/objects.py +++ b/hive/server/hive_api/objects.py @@ -10,7 +10,7 @@ async def accounts_by_name(db, names, observer=None, lite=True): """Find and return accounts by `name`.""" sql = """SELECT id, name, display_name, about, created_at, - vote_weight, rank, followers, following %s + rank, followers, following %s FROM hive_accounts WHERE name IN :names""" fields = '' if lite else ', location, website, profile_image, cover_image' rows = await db.query_all(sql % fields, names=tuple(names)) @@ -21,7 +21,6 @@ async def accounts_by_name(db, names, observer=None, lite=True): 'id': row['id'], 'name': row['name'], 'created': str(row['created_at']).split(' ')[0], - 'sp': int(estimated_sp(row['vote_weight'])), 'rank': row['rank'], 'followers': row['followers'], 'following': row['following'], diff --git a/scripts/upgrade.sql b/scripts/upgrade.sql index e2e3cd536fe19d2d3b8ade70006ecda28007c504..f32748ee189c067ec84c87db682b275d5da62b28 100644 --- a/scripts/upgrade.sql +++ b/scripts/upgrade.sql @@ -90,3 +90,56 @@ $function$ JOIN hive_posts_view hp ON hp.id = trends.id ORDER BY trends.trend DESC $function$ language sql + +DROP VIEW IF EXISTS public.hive_accounts_info_view; + +CREATE OR REPLACE VIEW public.hive_accounts_info_view +AS +SELECT + id, + name, + ( + select count(*) post_count + FROM hive_posts hp + WHERE ha.id=hp.author_id + ) post_count, + created_at, + ( + SELECT GREATEST + ( + created_at, + COALESCE( + ( + select max(hp.created_at) + FROM hive_posts hp + WHERE ha.id=hp.author_id + ), + '1970-01-01 00:00:00.0' + ), + COALESCE( + ( + select max(hv.last_update) + from hive_votes hv + WHERE ha.id=hv.voter_id + ), + '1970-01-01 00:00:00.0' + ) + ) + ) active_at, + display_name, + about, + reputation, + profile_image, + location, + website, + cover_image, + rank, + following, + followers, + proxy, + proxy_weight, + lastread_at, + cached_at, + raw_json +FROM + hive_accounts ha diff --git a/tests/tests_api b/tests/tests_api index fa660ef0ee019ba9c2da91e7a9140423593d944e..2e66bb68852cfbd31f01a7ba9393be088b151b4b 160000 --- a/tests/tests_api +++ b/tests/tests_api @@ -1 +1 @@ -Subproject commit fa660ef0ee019ba9c2da91e7a9140423593d944e +Subproject commit 2e66bb68852cfbd31f01a7ba9393be088b151b4b