diff --git a/hive/db/db_state.py b/hive/db/db_state.py index 937983780ae97fef34d802fc5ef36798fcf0b197..7b590b7fd32f096b960628e423b222e82c9967e0 100644 --- a/hive/db/db_state.py +++ b/hive/db/db_state.py @@ -297,7 +297,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 fc3734cac881052f35083935e2128c4c4cc4e81a..67635d0ba883473e1e44882ff603d6aae210477f 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 ) @@ -554,6 +550,82 @@ 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; + + CREATE OR REPLACE VIEW public.hive_accounts_info + AS + SELECT id, + name, + display_name, + about, + reputation, + created_at, + profile_image, + location, + website, + cover_image, + rank, + following, + followers, + ( + CASE + WHEN post_info.post_active_at > vote_info.vote_active_at THEN + ( + CASE + WHEN post_info.post_active_at > created_at THEN + post_info.post_active_at + ELSE + created_at + END + ) + ELSE + ( + CASE + WHEN vote_info.vote_active_at > created_at THEN + vote_info.vote_active_at + ELSE + created_at + END + ) + END + ) active_at, + proxy, + proxy_weight, + lastread_at, + cached_at, + raw_json, + post_info.post_count post_count + FROM hive_accounts ha + INNER JOIN + ( + select COALESCE( count(*), 0 ) post_count, COALESCE( max(hp.created_at), '1970-01-01 00:00:00.0' ) post_active_at, ha.id id_internal + from hive_posts hp + RIGHT JOIN hive_accounts ha ON hp.author_id = ha.id + GROUP BY ha.id + ) post_info ON ha.id = post_info.id_internal + INNER JOIN + ( + select COALESCE( max(hv.last_update), '1970-01-01 00:00:00.0' ) vote_active_at, ha.id id_internal + from hive_votes hv + RIGHT JOIN hive_accounts ha ON hv.voter_id = ha.id + GROUP BY ha.id + ) vote_info ON ha.id = vote_info.id_internal + """ + 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 5ae8bd2b7acef3f4bf4b376d3520733a15bf6a0c..e91e7b6b06e59eb7dd56cb996da9685613a4a009 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 d60791260352025140e3bcfe2cd3e4c09eff6160..5b7a88fe42ae5383a615ce6698c113d29f88a2e5 100644 --- a/hive/indexer/sync.py +++ b/hive/indexer/sync.py @@ -217,7 +217,6 @@ class Sync: # prefetch id->name and id->rank memory maps Accounts.load_ids() - Accounts.fetch_ranks() # load irredeemables mutes = Mutes( @@ -377,7 +376,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..6d525cf7e2fd4403625cc7a6d1198980ed1656de 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 + 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..263028e21d3fac7ccd96cbf3e0134ded985863e0 100644 --- a/hive/server/condenser_api/cursor.py +++ b/hive/server/condenser_api/cursor.py @@ -441,9 +441,9 @@ async def get_accounts(db, accounts: list): 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, + proxy, post_count, proxy_weight, rank, lastread_at, active_at, cached_at, raw_json - FROM hive_accounts WHERE name IN ({})""".format(",".join(names)) + FROM hive_accounts_info WHERE name IN ({})""".format(",".join(names)) result = await db.query_all(sql) for row in result: @@ -463,7 +463,6 @@ 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() diff --git a/hive/server/condenser_api/objects.py b/hive/server/condenser_api/objects.py index 4906a7d6aac28a90a8d5d2419803c0dcf6f283bb..878399c92b831dc0e8b738eab309581ab9acfd6f 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 + 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/tests/tests_api b/tests/tests_api index c673b555aa055358e0f5a1e1401a4110f7f83ca3..8a5c78b1c4e7c3046bea24c07058d644eb8fb608 160000 --- a/tests/tests_api +++ b/tests/tests_api @@ -1 +1 @@ -Subproject commit c673b555aa055358e0f5a1e1401a4110f7f83ca3 +Subproject commit 8a5c78b1c4e7c3046bea24c07058d644eb8fb608