|
1 | 1 | """Bridge API public endpoints for posts""" |
2 | 2 |
|
| 3 | +import hashlib |
3 | 4 | import hive.server.bridge_api.cursor as cursor |
4 | 5 | from hive.server.bridge_api.objects import load_posts, load_posts_reblogs, load_profiles |
5 | 6 | from hive.server.common.helpers import ( |
|
11 | 12 | from hive.server.hive_api.common import get_account_id |
12 | 13 | from hive.server.hive_api.objects import _follow_contexts |
13 | 14 | from hive.server.hive_api.community import list_top_communities |
| 15 | +from hive.server.db import CACHE_NAMESPACE |
14 | 16 |
|
15 | 17 | #pylint: disable=too-many-arguments, no-else-return |
16 | 18 |
|
@@ -80,16 +82,62 @@ async def get_ranked_posts(context, sort, start_author='', start_permlink='', |
80 | 82 |
|
81 | 83 | assert sort in ['trending', 'hot', 'created', 'promoted', |
82 | 84 | 'payout', 'payout_comments', 'muted'], 'invalid sort' |
| 85 | + |
| 86 | + # Validate and normalize parameters |
| 87 | + start_author = valid_account(start_author, allow_empty=True) |
| 88 | + start_permlink = valid_permlink(start_permlink, allow_empty=True) |
| 89 | + limit = valid_limit(limit, 100) |
| 90 | + tag = valid_tag(tag, allow_empty=True) |
| 91 | + |
| 92 | + # Generate cache key (based on all query parameters, excluding observer |
| 93 | + # as it only affects personalized content) |
| 94 | + cache_key_parts = [ |
| 95 | + 'get_ranked_posts', |
| 96 | + sort, |
| 97 | + start_author or '', |
| 98 | + start_permlink or '', |
| 99 | + str(limit), |
| 100 | + tag or '', |
| 101 | + ] |
| 102 | + cache_key_str = '_'.join(cache_key_parts) |
| 103 | + # Use hash to shorten overly long cache keys |
| 104 | + cache_key = 'bridge_get_ranked_posts_' + hashlib.md5(cache_key_str.encode()).hexdigest() |
| 105 | + |
| 106 | + # Set different cache TTL based on sort type (in seconds) |
| 107 | + cache_ttl_map = { |
| 108 | + 'created': 3, # 3 seconds cache |
| 109 | + 'trending': 300, # 300 seconds cache |
| 110 | + 'hot': 300, # 300 seconds cache |
| 111 | + 'promoted': 300, # 300 seconds cache |
| 112 | + 'payout': 30, # 30 seconds cache |
| 113 | + 'payout_comments': 30, # 30 seconds cache |
| 114 | + 'muted': 600, # 600 seconds cache |
| 115 | + } |
| 116 | + cache_ttl = cache_ttl_map.get(sort, 60) # Default 60 seconds |
| 117 | + |
| 118 | + # Try to get result from cache |
| 119 | + if db.redis_cache is not None: |
| 120 | + cached_result = await db.redis_cache.get(cache_key, namespace=CACHE_NAMESPACE) |
| 121 | + if cached_result is not None: |
| 122 | + return cached_result |
| 123 | + |
| 124 | + # Cache miss, execute query |
83 | 125 | ids = await cursor.pids_by_ranked( |
84 | 126 | context['db'], |
85 | 127 | sort, |
86 | | - valid_account(start_author, allow_empty=True), |
87 | | - valid_permlink(start_permlink, allow_empty=True), |
88 | | - valid_limit(limit, 100), |
89 | | - valid_tag(tag, allow_empty=True), |
| 128 | + start_author, |
| 129 | + start_permlink, |
| 130 | + limit, |
| 131 | + tag, |
90 | 132 | observer_id) |
91 | 133 |
|
92 | | - return await load_posts(context['db'], ids) |
| 134 | + result = await load_posts(context['db'], ids) |
| 135 | + |
| 136 | + # Store result in cache |
| 137 | + if db.redis_cache is not None: |
| 138 | + await db.redis_cache.set(cache_key, result, ttl=cache_ttl, namespace=CACHE_NAMESPACE) |
| 139 | + |
| 140 | + return result |
93 | 141 |
|
94 | 142 | @return_error_info |
95 | 143 | async def get_account_posts(context, sort, account, start_author='', start_permlink='', |
|
0 commit comments