my fork of the bluesky client

Reduce calls to getFeedGenerator and getFeed (#2166)

* Reduce calls to getFeedGenerator by the mergefeed

* Dont run end-of-follows mergefeed requests until actually at the end of the feed

* build AWS container

---------

Co-authored-by: Jake Gold <jake@blueskyweb.xyz>

authored by

Paul Frazee
Jake Gold
and committed by
GitHub
b82c5177 3d229b5f

+72 -27
+1 -1
.github/workflows/build-and-push-bskyweb-aws.yaml
··· 3 3 push: 4 4 branches: 5 5 - main 6 - - jake/bskyweb-additions 6 + - traffic-reduction 7 7 env: 8 8 REGISTRY: ${{ secrets.AWS_ECR_REGISTRY_USEAST2_PACKAGES_REGISTRY }} 9 9 USERNAME: ${{ secrets.AWS_ECR_REGISTRY_USEAST2_PACKAGES_USERNAME }}
+10 -18
src/lib/api/feed/merge.ts
··· 62 62 63 63 // always keep following topped up 64 64 if (this.following.numReady < limit) { 65 - promises.push(this.following.fetchNext(60)) 65 + await this.following.fetchNext(60) 66 66 } 67 67 68 68 // pick the next feeds to sample from ··· 73 73 } 74 74 75 75 // top up the feeds 76 - for (const feed of feeds) { 77 - if (feed.numReady < 5) { 78 - promises.push(feed.fetchNext(10)) 76 + const outOfFollows = 77 + !this.following.hasMore && this.following.numReady < limit 78 + if (this.params.mergeFeedEnabled || outOfFollows) { 79 + for (const feed of feeds) { 80 + if (feed.numReady < 5) { 81 + promises.push(feed.fetchNext(10)) 82 + } 79 83 } 80 84 } 81 85 ··· 216 220 super(feedTuners) 217 221 this.sourceInfo = { 218 222 $type: 'reasonFeedSource', 219 - displayName: feedUri.split('/').pop() || '', 220 - uri: feedUriToHref(feedUri), 223 + uri: feedUri, 224 + href: feedUriToHref(feedUri), 221 225 } 222 226 this.minDate = new Date(Date.now() - POST_AGE_CUTOFF) 223 - getAgent() 224 - .app.bsky.feed.getFeedGenerator({ 225 - feed: feedUri, 226 - }) 227 - .then( 228 - res => { 229 - if (this.sourceInfo) { 230 - this.sourceInfo.displayName = res.data.view.displayName 231 - } 232 - }, 233 - _err => {}, 234 - ) 235 227 } 236 228 237 229 protected async _getFeed(
+1 -1
src/lib/api/feed/types.ts
··· 19 19 export interface ReasonFeedSource { 20 20 $type: 'reasonFeedSource' 21 21 uri: string 22 - displayName: string 22 + href: string 23 23 } 24 24 25 25 export function isReasonFeedSource(v: unknown): v is ReasonFeedSource {
+6 -7
src/view/com/posts/FeedItem.tsx
··· 33 33 import {countLines} from 'lib/strings/helpers' 34 34 import {useComposerControls} from '#/state/shell/composer' 35 35 import {Shadow, usePostShadow, POST_TOMBSTONE} from '#/state/cache/post-shadow' 36 + import {FeedNameText} from '../util/FeedInfoText' 36 37 37 38 export function FeedItem({ 38 39 post, ··· 177 178 178 179 <View style={{paddingTop: 12, flexShrink: 1}}> 179 180 {isReasonFeedSource(reason) ? ( 180 - <Link 181 - title={sanitizeDisplayName(reason.displayName)} 182 - href={reason.uri}> 181 + <Link href={reason.href}> 183 182 <Text 184 183 type="sm-bold" 185 184 style={pal.textLight} 186 185 lineHeight={1.2} 187 186 numberOfLines={1}> 188 187 From{' '} 189 - <TextLinkOnWebOnly 188 + <FeedNameText 190 189 type="sm-bold" 191 - style={pal.textLight} 190 + uri={reason.uri} 191 + href={reason.href} 192 192 lineHeight={1.2} 193 193 numberOfLines={1} 194 - text={sanitizeDisplayName(reason.displayName)} 195 - href={reason.uri} 194 + style={pal.textLight} 196 195 /> 197 196 </Text> 198 197 </Link>
+54
src/view/com/util/FeedInfoText.tsx
··· 1 + import React from 'react' 2 + import {StyleProp, StyleSheet, TextStyle} from 'react-native' 3 + import {TextLinkOnWebOnly} from './Link' 4 + import {LoadingPlaceholder} from './LoadingPlaceholder' 5 + import {TypographyVariant} from 'lib/ThemeContext' 6 + import {sanitizeDisplayName} from 'lib/strings/display-names' 7 + import {useFeedSourceInfoQuery} from '#/state/queries/feed' 8 + 9 + export function FeedNameText({ 10 + type = 'md', 11 + uri, 12 + href, 13 + lineHeight, 14 + numberOfLines, 15 + style, 16 + }: { 17 + type?: TypographyVariant 18 + uri: string 19 + href: string 20 + lineHeight?: number 21 + numberOfLines?: number 22 + style?: StyleProp<TextStyle> 23 + }) { 24 + const {data, isError} = useFeedSourceInfoQuery({uri}) 25 + 26 + let inner 27 + if (data?.displayName || isError) { 28 + const displayName = data?.displayName || uri.split('/').pop() || '' 29 + inner = ( 30 + <TextLinkOnWebOnly 31 + type={type} 32 + style={style} 33 + lineHeight={lineHeight} 34 + numberOfLines={numberOfLines} 35 + href={href} 36 + text={sanitizeDisplayName(displayName)} 37 + /> 38 + ) 39 + } else { 40 + inner = ( 41 + <LoadingPlaceholder 42 + width={80} 43 + height={8} 44 + style={styles.loadingPlaceholder} 45 + /> 46 + ) 47 + } 48 + 49 + return inner 50 + } 51 + 52 + const styles = StyleSheet.create({ 53 + loadingPlaceholder: {position: 'relative', top: 1, left: 2}, 54 + })