diff --git a/hive/db/schema.py b/hive/db/schema.py index 1a51eb749d5b34e5e0776880c01746a5fe84779d..a39d163001b1c4ac456391e8ae8de8e71a61aa52 100644 --- a/hive/db/schema.py +++ b/hive/db/schema.py @@ -578,7 +578,11 @@ def setup(db): "database_api_list_comments.sql", "database_api_list_votes.sql", "update_posts_rshares.sql", - "update_hive_post_root_id.sql" + "update_hive_post_root_id.sql", + "condenser_get_by_replies_to_account.sql", + "condenser_get_by_account_comments.sql", + "condenser_get_by_blog_without_reblog.sql", + "condenser_get_by_feed_with_reblog.sql" ] from os.path import dirname, realpath dir_path = dirname(realpath(__file__)) diff --git a/hive/db/sql_scripts/condenser_get_by_account_comments.sql b/hive/db/sql_scripts/condenser_get_by_account_comments.sql new file mode 100644 index 0000000000000000000000000000000000000000..572fca3c90d467a46665fa1acda9f7d3fcd797a2 --- /dev/null +++ b/hive/db/sql_scripts/condenser_get_by_account_comments.sql @@ -0,0 +1,62 @@ +DROP FUNCTION IF EXISTS condenser_get_by_account_comments; + +CREATE OR REPLACE FUNCTION condenser_get_by_account_comments( + in _author VARCHAR, + in _permlink VARCHAR, + in _limit INTEGER +) +RETURNS SETOF bridge_api_post +AS +$function$ +DECLARE + __post_id INTEGER := 0; +BEGIN + + IF _permlink <> '' THEN + __post_id = find_comment_id( _author, _permlink, True ); + END IF; + + RETURN QUERY SELECT + hp.id, + hp.author, + hp.parent_author, + hp.author_rep, + hp.root_title, + hp.beneficiaries, + hp.max_accepted_payout, + hp.percent_hbd, + hp.url, + hp.permlink, + hp.parent_permlink_or_category, + hp.title, + hp.body, + hp.category, + hp.depth, + hp.promoted, + hp.payout, + hp.pending_payout, + hp.payout_at, + hp.is_paidout, + hp.children, + hp.votes, + hp.created_at, + hp.updated_at, + hp.rshares, + hp.abs_rshares, + hp.json, + hp.is_hidden, + hp.is_grayed, + hp.total_votes, + hp.sc_trend, + hp.role_title, + hp.community_title, + hp.role_id, + hp.is_pinned, + hp.curator_payout_value + FROM hive_posts_view hp + WHERE ( hp.author = _author ) AND ( ( __post_id = 0 ) OR ( hp.id <= __post_id ) ) AND hp.depth > 0 + ORDER BY hp.id DESC + LIMIT _limit; +END +$function$ +language plpgsql STABLE; diff --git a/hive/db/sql_scripts/condenser_get_by_blog_without_reblog.sql b/hive/db/sql_scripts/condenser_get_by_blog_without_reblog.sql new file mode 100644 index 0000000000000000000000000000000000000000..c952296f218b761609c77ba59783e7f161457f3f --- /dev/null +++ b/hive/db/sql_scripts/condenser_get_by_blog_without_reblog.sql @@ -0,0 +1,62 @@ +DROP FUNCTION IF EXISTS condenser_get_by_blog_without_reblog; + +CREATE OR REPLACE FUNCTION condenser_get_by_blog_without_reblog( + in _author VARCHAR, + in _permlink VARCHAR, + in _limit INTEGER +) +RETURNS SETOF bridge_api_post +AS +$function$ +DECLARE + __post_id INTEGER := 0; +BEGIN + + IF _permlink <> '' THEN + __post_id = find_comment_id( _author, _permlink, True ); + END IF; + + RETURN QUERY SELECT + hp.id, + hp.author, + hp.parent_author, + hp.author_rep, + hp.root_title, + hp.beneficiaries, + hp.max_accepted_payout, + hp.percent_hbd, + hp.url, + hp.permlink, + hp.parent_permlink_or_category, + hp.title, + hp.body, + hp.category, + hp.depth, + hp.promoted, + hp.payout, + hp.pending_payout, + hp.payout_at, + hp.is_paidout, + hp.children, + hp.votes, + hp.created_at, + hp.updated_at, + hp.rshares, + hp.abs_rshares, + hp.json, + hp.is_hidden, + hp.is_grayed, + hp.total_votes, + hp.sc_trend, + hp.role_title, + hp.community_title, + hp.role_id, + hp.is_pinned, + hp.curator_payout_value + FROM hive_posts_view hp + WHERE ( hp.author = _author ) AND ( ( __post_id = 0 ) OR ( hp.id <= __post_id ) ) AND hp.depth = 0 + ORDER BY hp.id DESC + LIMIT _limit; +END +$function$ +language plpgsql STABLE; diff --git a/hive/db/sql_scripts/condenser_get_by_feed_with_reblog.sql b/hive/db/sql_scripts/condenser_get_by_feed_with_reblog.sql new file mode 100644 index 0000000000000000000000000000000000000000..22f17365fca974d9badff86010445789fbc9a0bd --- /dev/null +++ b/hive/db/sql_scripts/condenser_get_by_feed_with_reblog.sql @@ -0,0 +1,89 @@ +DROP FUNCTION IF EXISTS condenser_get_by_feed_with_reblog; + +CREATE OR REPLACE FUNCTION condenser_get_by_feed_with_reblog( + in _account VARCHAR, + in _author VARCHAR, + in _permlink VARCHAR, + in _limit INTEGER +) +RETURNS SETOF bridge_api_post +AS +$function$ +DECLARE + __post_id INTEGER := 0; + __cutoff INTEGER; + __account_id INTEGER := find_account_id( _account, True ); + __min_data TIMESTAMP; +BEGIN + + IF _permlink <> '' THEN + __post_id = find_comment_id( _author, _permlink, True ); + END IF; + + __cutoff = block_before_head( '1 month' ); + __min_data = + ( + SELECT MIN(hfc.created_at) + FROM hive_feed_cache hfc + JOIN hive_follows hf ON hfc.account_id = hf.following + WHERE hf.state = 1 AND hf.follower = __account_id AND ( ( __post_id = 0 ) OR ( hfc.post_id = __post_id ) ) + ); + + RETURN QUERY SELECT + hp.id, + hp.author, + hp.parent_author, + hp.author_rep, + hp.root_title, + hp.beneficiaries, + hp.max_accepted_payout, + hp.percent_hbd, + hp.url, + hp.permlink, + hp.parent_permlink_or_category, + hp.title, + hp.body, + hp.category, + hp.depth, + hp.promoted, + hp.payout, + hp.pending_payout, + hp.payout_at, + hp.is_paidout, + hp.children, + hp.votes, + hp.created_at, + hp.updated_at, + hp.rshares, + hp.abs_rshares, + hp.json, + hp.is_hidden, + hp.is_grayed, + hp.total_votes, + hp.sc_trend, + hp.role_title, + hp.community_title, + hp.role_id, + hp.is_pinned, + hp.curator_payout_value + FROM hive_posts_view hp + JOIN + ( + SELECT hfc.post_id + FROM hive_feed_cache hfc + JOIN + ( + SELECT following + FROM hive_follows + WHERE state = 1 AND follower = __account_id + ) T ON hfc.account_id = T.following + JOIN hive_feed_cache hfc2 ON hfc2.account_id = T.following AND( __post_id = 0 OR hfc.post_id <= __post_id ) + WHERE hfc.block_num > __cutoff + GROUP BY hfc.post_id + HAVING ( __post_id = 0 ) OR ( MIN(hfc.created_at) <= __min_data ) + ORDER BY MIN(hfc.created_at) DESC + LIMIT _limit + ) T ON hp.id = T.post_id; +END +$function$ +language plpgsql STABLE; diff --git a/hive/db/sql_scripts/condenser_get_by_replies_to_account.sql b/hive/db/sql_scripts/condenser_get_by_replies_to_account.sql new file mode 100644 index 0000000000000000000000000000000000000000..a18cd7e97387837d21a55c20ab3ede00985d8a92 --- /dev/null +++ b/hive/db/sql_scripts/condenser_get_by_replies_to_account.sql @@ -0,0 +1,81 @@ +DROP FUNCTION IF EXISTS condenser_get_by_replies_to_account; + +CREATE OR REPLACE FUNCTION condenser_get_by_replies_to_account( + in _author VARCHAR, + in _permlink VARCHAR, + in _limit INTEGER +) +RETURNS SETOF bridge_api_post +AS +$function$ +DECLARE + __post_id INTEGER := 0; +BEGIN + + IF _permlink <> '' THEN + SELECT + ha_pp.name, hp.id + INTO + _author, __post_id + FROM hive_posts hp + JOIN hive_posts pp ON hp.parent_id = pp.id + JOIN hive_accounts ha_pp ON ha_pp.id = pp.author_id + JOIN hive_permlink_data hpd_pp ON hpd_pp.id = pp.permlink_id + JOIN hive_accounts ha ON hp.author_id = ha.id + WHERE + hpd_pp.permlink = _permlink AND ha.name = _author; + END IF; + + RETURN QUERY SELECT + hp.id, + hp.author, + hp.parent_author, + hp.author_rep, + hp.root_title, + hp.beneficiaries, + hp.max_accepted_payout, + hp.percent_hbd, + hp.url, + hp.permlink, + hp.parent_permlink_or_category, + hp.title, + hp.body, + hp.category, + hp.depth, + hp.promoted, + hp.payout, + hp.pending_payout, + hp.payout_at, + hp.is_paidout, + hp.children, + hp.votes, + hp.created_at, + hp.updated_at, + hp.rshares, + hp.abs_rshares, + hp.json, + hp.is_hidden, + hp.is_grayed, + hp.total_votes, + hp.sc_trend, + hp.role_title, + hp.community_title, + hp.role_id, + hp.is_pinned, + hp.curator_payout_value + FROM hive_posts_view hp + JOIN + ( + SELECT hp.id + FROM hive_posts_view hp + WHERE hp.author = _author + ORDER BY hp.id DESC + LIMIT _limit + ) T ON hp.parent_id = T.id + WHERE ( ( __post_id = 0 ) OR ( hp.id <= __post_id ) ) + ORDER BY hp.id DESC + LIMIT _limit; + +END +$function$ +language plpgsql STABLE; diff --git a/hive/server/bridge_api/cursor.py b/hive/server/bridge_api/cursor.py index 1cfd6f1767f0d5a7ba09faf38138b66cc27627fd..df9d4cbd50a41cc0eee52a5fd6fae07f3288ce2f 100644 --- a/hive/server/bridge_api/cursor.py +++ b/hive/server/bridge_api/cursor.py @@ -90,40 +90,6 @@ async def pids_by_blog(db, account: str, start_author: str = '', return await db.query_col(sql, account_id=account_id, account=account, start_id=start_id, limit=limit) -async def pids_by_feed_with_reblog(db, account: str, start_author: str = '', - start_permlink: str = '', limit: int = 20): - """Get a list of [post_id, reblogged_by_str] for an account's feed.""" - account_id = await _get_account_id(db, account) - - seek = '' - start_id = None - if start_permlink: - start_id = await _get_post_id(db, start_author, start_permlink) - if not start_id: - return [] - - seek = """ - HAVING MIN(hive_feed_cache.created_at) <= ( - SELECT MIN(created_at) FROM hive_feed_cache WHERE post_id = :start_id - AND account_id IN (SELECT following FROM hive_follows - WHERE follower = :account AND state = 1)) - """ - - sql = """ - SELECT post_id, string_agg(name, ',') accounts - FROM hive_feed_cache - JOIN hive_follows ON account_id = hive_follows.following AND state = 1 - JOIN hive_accounts ON hive_follows.following = hive_accounts.id - WHERE hive_follows.follower = :account - AND hive_feed_cache.created_at > :cutoff - GROUP BY post_id %s - ORDER BY MIN(hive_feed_cache.created_at) DESC LIMIT :limit - """ % seek - - result = await db.query_all(sql, account=account_id, start_id=start_id, - limit=limit, cutoff=last_month()) - return [(row[0], row[1]) for row in result] - async def pids_by_comments(db, account: str, start_permlink: str = '', limit: int = 20): """Get a list of post_ids representing comments by an author.""" seek = '' diff --git a/hive/server/bridge_api/methods.py b/hive/server/bridge_api/methods.py index 039dd24b3895932913171adb0bae390f61d8e729..716d15de50e940b04a6fa696315b4a6a279e5a4a 100644 --- a/hive/server/bridge_api/methods.py +++ b/hive/server/bridge_api/methods.py @@ -1,7 +1,7 @@ """Bridge API public endpoints for posts""" import hive.server.bridge_api.cursor as cursor -from hive.server.bridge_api.objects import load_posts, load_posts_reblogs, load_profiles, _bridge_post_object, append_statistics_to_post +from hive.server.bridge_api.objects import load_posts, load_profiles, _bridge_post_object, append_statistics_to_post from hive.server.database_api.methods import find_votes_impl, VotesPresentation from hive.server.common.helpers import ( return_error_info, @@ -13,6 +13,7 @@ from hive.server.hive_api.common import get_account_id from hive.server.hive_api.objects import _follow_contexts from hive.server.hive_api.community import list_top_communities from hive.server.common.mutes import Mutes +from hive.server.hive_api.public import get_by_feed_with_reblog_impl #pylint: disable=too-many-arguments, no-else-return @@ -272,8 +273,7 @@ async def _get_account_posts_by_blog(db, account : str, start_author : str, star return posts async def _get_account_posts_by_feed(db, account : str, start_author : str, start_permlink : str, limit : int): - _ids = await cursor.pids_by_feed_with_reblog(db, account, start_author, start_permlink, limit) - return await load_posts_reblogs(db, _ids) + return await get_by_feed_with_reblog_impl(db, account, start_author, start_permlink, limit) @return_error_info async def get_account_posts(context, sort:str, account:str, start_author:str='', start_permlink:str='', diff --git a/hive/server/bridge_api/objects.py b/hive/server/bridge_api/objects.py index 3862f34b331dc945975a0b66117dd4cb5192e4bb..e2e9550fc8923f87e319151233c28c3dfd67f6ae 100644 --- a/hive/server/bridge_api/objects.py +++ b/hive/server/bridge_api/objects.py @@ -57,21 +57,6 @@ async def load_profiles(db, names): rows = await db.query_all(sql, names=tuple(names)) return [_bridge_profile_object(row) for row in rows] -async def load_posts_reblogs(db, ids_with_reblogs, truncate_body=0): - """Given a list of (id, reblogged_by) tuples, return posts w/ reblog key.""" - post_ids = [r[0] for r in ids_with_reblogs] - reblog_by = dict(ids_with_reblogs) - posts = await load_posts(db, post_ids, truncate_body=truncate_body) - - # Merge reblogged_by data into result set - for post in posts: - rby = set(reblog_by[post['post_id']].split(',')) - rby.discard(post['author']) - if rby: - post['reblogged_by'] = list(rby) - - return posts - async def load_posts_keyed(db, ids, truncate_body=0): """Given an array of post ids, returns full posts objects keyed by id.""" # pylint: disable=too-many-locals diff --git a/hive/server/condenser_api/cursor.py b/hive/server/condenser_api/cursor.py index aa02fabc72b950f8c2fc53f74f42afb29da6f624..e2fd473392503bcd1dbe531316ec0ede6384d42a 100644 --- a/hive/server/condenser_api/cursor.py +++ b/hive/server/condenser_api/cursor.py @@ -2,6 +2,9 @@ from hive.server.common.helpers import last_month +from hive.server.condenser_api.objects import _condenser_post_object +from hive.server.database_api.methods import find_votes_impl, VotesPresentation + # pylint: disable=too-many-lines async def get_post_id(db, author, permlink): @@ -143,131 +146,31 @@ async def pids_by_blog(db, account: str, start_author: str = '', return await db.query_col(sql, account_id=account_id, start_id=start_id, limit=limit) - -async def pids_by_blog_without_reblog(db, account: str, start_permlink: str = '', limit: int = 20): - """Get a list of post_ids for an author's blog without reblogs.""" - - seek = '' - start_id = None - if start_permlink: - start_id = await _get_post_id(db, account, start_permlink) - if not start_id: - return [] - seek = "AND id <= :start_id" - - sql = """ - SELECT id - FROM hive_posts - WHERE author_id = (SELECT id FROM hive_accounts WHERE name = :account) %s - AND counter_deleted = 0 - AND depth = 0 - ORDER BY id DESC - LIMIT :limit - """ % seek - - return await db.query_col(sql, account=account, start_id=start_id, limit=limit) - - -async def pids_by_feed_with_reblog(db, account: str, start_author: str = '', - start_permlink: str = '', limit: int = 20): - """Get a list of [post_id, reblogged_by_str] for an account's feed.""" - account_id = await _get_account_id(db, account) - - seek = '' - start_id = None - if start_permlink: - start_id = await _get_post_id(db, start_author, start_permlink) - if not start_id: - return [] - - seek = """ - HAVING MIN(hive_feed_cache.created_at) <= ( - SELECT MIN(created_at) FROM hive_feed_cache WHERE post_id = :start_id - AND account_id IN (SELECT following FROM hive_follows - WHERE follower = :account AND state = 1)) - """ - - sql = """ - SELECT post_id, string_agg(name, ',') accounts - FROM hive_feed_cache - JOIN hive_follows ON account_id = hive_follows.following AND state = 1 - JOIN hive_accounts ON hive_follows.following = hive_accounts.id - WHERE hive_follows.follower = :account - AND hive_feed_cache.created_at > :cutoff - GROUP BY post_id %s - ORDER BY MIN(hive_feed_cache.created_at) DESC LIMIT :limit - """ % seek - - result = await db.query_all(sql, account=account_id, start_id=start_id, - limit=limit, cutoff=last_month()) - return [(row[0], row[1]) for row in result] - - -async def pids_by_account_comments(db, account: str, start_permlink: str = '', limit: int = 20): +async def get_data(db, sql:str, truncate_body: int = 0): """Get a list of post_ids representing comments by an author.""" - seek = '' - start_id = None - if start_permlink: - start_id = await _get_post_id(db, account, start_permlink) - if not start_id: - return [] - - seek = "AND id <= :start_id" + result = await db.query_all(sql); - # `depth` in ORDER BY is a no-op, but forces an ix3 index scan (see #189) - sql = """ - SELECT id FROM hive_posts - WHERE author_id = (SELECT id FROM hive_accounts WHERE name = :account) %s - AND depth > 0 - AND counter_deleted = 0 - ORDER BY id DESC, depth - LIMIT :limit - """ % seek + posts = [] + for row in result: + row = dict(row) + post = _condenser_post_object(row, truncate_body=truncate_body) - return await db.query_col(sql, account=account, start_id=start_id, limit=limit) + post['active_votes'] = await find_votes_impl(db, row['author'], row['permlink'], VotesPresentation.CondenserApi) + posts.append(post) + return posts -async def pids_by_replies_to_account(db, start_author: str, start_permlink: str = '', - limit: int = 20): - """Get a list of post_ids representing replies to an author. +async def get_by_blog_without_reblog(db, account: str, start_permlink: str = '', limit: int = 20, truncate_body: int = 0): + """Get a list of posts for an author's blog without reblogs.""" + sql = " SELECT * FROM condenser_get_by_blog_without_reblog( '{}', '{}', {} ) ".format( account, start_permlink, limit ) + return await get_data(db, sql, truncate_body ) - To get the first page of results, specify `start_author` as the - account being replied to. For successive pages, provide the - last loaded reply's author/permlink. - """ - seek = '' - start_id = None - if start_permlink: - sql = """ - SELECT (SELECT name FROM hive_accounts WHERE id = parent.author_id), - child.id - FROM hive_posts child - JOIN hive_posts parent - ON child.parent_id = parent.id - WHERE child.author_id = (SELECT id FROM hive_accounts WHERE name = :author) - AND child.permlink_id = (SELECT id FROM hive_permlink_data WHERE permlink = :permlink) - """ - - row = await db.query_row(sql, author=start_author, permlink=start_permlink) - if not row: - return [] - - parent_account = row[0] - start_id = row[1] - seek = "AND id <= :start_id" - else: - parent_account = start_author - - sql = """ - SELECT id FROM hive_posts - WHERE parent_id IN (SELECT id FROM hive_posts - WHERE author_id = (SELECT id FROM hive_accounts WHERE name = :parent) - AND counter_deleted = 0 - ORDER BY id DESC - LIMIT 10000) %s - AND counter_deleted = 0 - ORDER BY id DESC - LIMIT :limit - """ % seek +async def get_by_account_comments(db, account: str, start_permlink: str = '', limit: int = 20, truncate_body: int = 0): + """Get a list of posts representing comments by an author.""" + sql = " SELECT * FROM condenser_get_by_account_comments( '{}', '{}', {} ) ".format( account, start_permlink, limit ) + return await get_data(db, sql, truncate_body ) - return await db.query_col(sql, parent=parent_account, start_id=start_id, limit=limit) +async def get_by_replies_to_account(db, start_author: str, start_permlink: str = '', limit: int = 20, truncate_body: int = 0): + """Get a list of posts representing replies to an author.""" + sql = " SELECT * FROM condenser_get_by_replies_to_account( '{}', '{}', {} ) ".format( start_author, start_permlink, limit ) + return await get_data(db, sql, truncate_body ) diff --git a/hive/server/condenser_api/get_state.py b/hive/server/condenser_api/get_state.py index 269b5945536bf4dadca04b948c092aecaa4c1049..4035e6bdeaa932e1f9b696aed9c7e2e76231f21f 100644 --- a/hive/server/condenser_api/get_state.py +++ b/hive/server/condenser_api/get_state.py @@ -12,8 +12,7 @@ from hive.server.common.mutes import Mutes from hive.server.condenser_api.objects import ( load_accounts, load_posts, - load_posts_keyed, - load_posts_reblogs) + load_posts_keyed) from hive.server.common.helpers import ( ApiError, return_error_info, @@ -29,6 +28,8 @@ import hive.server.condenser_api.cursor as cursor from hive.server.condenser_api.methods import get_posts_by_given_sort +from hive.server.hive_api.public import get_by_feed_with_reblog_impl + log = logging.getLogger(__name__) # steemd account 'tabs' - specific post list queries @@ -162,17 +163,14 @@ async def _get_account_discussion_by_key(db, account, key): assert key, 'discussion key must be specified' if key == 'recent_replies': - pids = await cursor.pids_by_replies_to_account(db, account, '', 20) - posts = await load_posts(db, pids) + posts = await cursor.get_by_replies_to_account(db, account, '', 20) elif key == 'comments': - pids = await cursor.pids_by_account_comments(db, account, '', 20) - posts = await load_posts(db, pids) + posts = await cursor.get_by_account_comments(db, account, '', 20) elif key == 'blog': pids = await cursor.pids_by_blog(db, account, '', '', 20) posts = await load_posts(db, pids) elif key == 'feed': - res = await cursor.pids_by_feed_with_reblog(db, account, '', '', 20) - posts = await load_posts_reblogs(db, res) + posts = await get_by_feed_with_reblog_impl(db, account, '', '', 20) else: raise ApiError("unknown account discussion key %s" % key) diff --git a/hive/server/condenser_api/methods.py b/hive/server/condenser_api/methods.py index 1a5b586eadb9b58a6dca2351222c93a3d3cbd650..5d58fb174dfb8080fb729cc7c5384ab98ba09258 100644 --- a/hive/server/condenser_api/methods.py +++ b/hive/server/condenser_api/methods.py @@ -2,7 +2,7 @@ from functools import wraps import hive.server.condenser_api.cursor as cursor -from hive.server.condenser_api.objects import load_posts, load_posts_reblogs +from hive.server.condenser_api.objects import load_posts from hive.server.condenser_api.objects import _mute_votes, _condenser_post_object from hive.server.common.helpers import ( ApiError, @@ -17,6 +17,8 @@ from hive.server.common.helpers import ( from hive.server.common.mutes import Mutes from hive.server.database_api.methods import find_votes_impl, VotesPresentation +from hive.server.hive_api.public import get_by_feed_with_reblog_impl + # pylint: disable=too-many-arguments,line-too-long,too-many-lines SQL_TEMPLATE = """ @@ -361,13 +363,13 @@ async def get_discussions_by_feed(context, tag: str = None, start_author: str = """Retrieve account's personalized feed.""" assert tag, '`tag` cannot be blank' assert not filter_tags, 'filter_tags not supported' - res = await cursor.pids_by_feed_with_reblog( + return await get_by_feed_with_reblog_impl( context['db'], valid_account(tag), valid_account(start_author, allow_empty=True), valid_permlink(start_permlink, allow_empty=True), - valid_limit(limit, 100, 20)) - return await load_posts_reblogs(context['db'], res, truncate_body=truncate_body) + valid_limit(limit, 100, 20), + truncate_body) @return_error_info @@ -418,13 +420,12 @@ async def get_replies_by_last_update(context, start_author: str = None, start_pe """Get all replies made to any of author's posts.""" assert start_author, '`start_author` cannot be blank' - ids = await cursor.pids_by_replies_to_account( + return await cursor.get_by_replies_to_account( context['db'], valid_account(start_author), valid_permlink(start_permlink, allow_empty=True), - valid_limit(limit, 100, 20)) - return await load_posts(context['db'], ids, truncate_body=truncate_body) - + valid_limit(limit, 100, 20), + truncate_body) @return_error_info @nested_query_compat @@ -438,12 +439,11 @@ async def get_discussions_by_author_before_date(context, author: str = None, sta """ # pylint: disable=invalid-name,unused-argument assert author, '`author` cannot be blank' - ids = await cursor.pids_by_blog_without_reblog( + return await cursor.get_by_blog_without_reblog( context['db'], valid_account(author), valid_permlink(start_permlink, allow_empty=True), valid_limit(limit, 100, 10)) - return await load_posts(context['db'], ids) @return_error_info @nested_query_compat diff --git a/hive/server/condenser_api/objects.py b/hive/server/condenser_api/objects.py index d2e4483ca345dae33f6c59a0b94144e0b8974c2a..0f52228435018bcd86a0bf67fccbadd668ca9116 100644 --- a/hive/server/condenser_api/objects.py +++ b/hive/server/condenser_api/objects.py @@ -19,21 +19,6 @@ async def load_accounts(db, names): rows = await db.query_all(sql, names=tuple(names)) return [_condenser_account_object(row) for row in rows] -async def load_posts_reblogs(db, ids_with_reblogs, truncate_body=0): - """Given a list of (id, reblogged_by) tuples, return posts w/ reblog key.""" - post_ids = [r[0] for r in ids_with_reblogs] - reblog_by = dict(ids_with_reblogs) - posts = await load_posts(db, post_ids, truncate_body=truncate_body) - - # Merge reblogged_by data into result set - for post in posts: - rby = set(reblog_by[post['post_id']].split(',')) - rby.discard(post['author']) - if rby: - post['reblogged_by'] = list(rby) - - return posts - async def load_posts_keyed(db, ids, truncate_body=0): """Given an array of post ids, returns full posts objects keyed by id.""" assert ids, 'no ids passed to load_posts_keyed' diff --git a/hive/server/hive_api/public.py b/hive/server/hive_api/public.py index e91126c0324f0a72549fe2646c89209869c00e54..e3ed5680bcc1fd26346ae9e6751be6a63b3db802 100644 --- a/hive/server/hive_api/public.py +++ b/hive/server/hive_api/public.py @@ -8,10 +8,13 @@ from hive.server.hive_api.common import ( valid_account, valid_permlink, valid_limit) from hive.server.condenser_api.cursor import get_followers, get_following from hive.server.bridge_api.cursor import ( - pids_by_blog, pids_by_comments, pids_by_feed_with_reblog) + pids_by_blog, pids_by_comments) from hive.db.schema import DB_VERSION as SCHEMA_DB_VERSION +from hive.server.condenser_api.objects import _condenser_post_object +from hive.server.database_api.methods import find_votes_impl, VotesPresentation + log = logging.getLogger(__name__) # Accounts @@ -92,24 +95,12 @@ async def list_account_posts(context, account:str, limit:int=10, observer:str=No async def list_account_feed(context, account:str, limit:int=10, observer:str=None, last_post:str=None): """Get all posts (blogs and resteems) from `account`'s follows.""" db = context['db'] - ids_with_reblogs = await pids_by_feed_with_reblog( + return await get_by_feed_with_reblog_impl( context['db'], valid_account(account), *split_url(last_post, allow_empty=True), valid_limit(limit, 50, 10)) - reblog_by = dict(ids_with_reblogs) - post_ids = [r[0] for r in ids_with_reblogs] - posts = await posts_by_id(db, post_ids, observer) - - # Merge reblogged_by data into result set - for post in posts: - rby = set(reblog_by[post['post_id']].split(',')) - rby.discard(post['author']) - if rby: post['reblogged_by'] = list(rby) - - return posts - async def get_info(context): db = context['db'] @@ -126,3 +117,19 @@ async def get_info(context): } return ret + +async def get_by_feed_with_reblog_impl(db, account: str, start_author: str = '', + start_permlink: str = '', limit: int = 20, truncate_body: int = 0): + """Get a list of [post_id, reblogged_by_str] for an account's feed.""" + sql = " SELECT * FROM condenser_get_by_feed_with_reblog( '{}', '{}', '{}', {} ) ".format( account, start_author, start_permlink, limit ) + result = await db.query_all(sql) + + posts = [] + for row in result: + row = dict(row) + post = _condenser_post_object(row, truncate_body=truncate_body) + + post['active_votes'] = await find_votes_impl(db, row['author'], row['permlink'], VotesPresentation.CondenserApi) + posts.append(post) + + return posts diff --git a/tests/tests_api b/tests/tests_api index d8c41b9bbbe8b38744cfe1079e3ff72ce125a554..1ff7e46a13168eebcaabf8e47c01bcfda142832f 160000 --- a/tests/tests_api +++ b/tests/tests_api @@ -1 +1 @@ -Subproject commit d8c41b9bbbe8b38744cfe1079e3ff72ce125a554 +Subproject commit 1ff7e46a13168eebcaabf8e47c01bcfda142832f