Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F32167981
D13976.1765054359.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
8 KB
Referenced Files
None
Subscribers
None
D13976.1765054359.diff
View Options
diff --git a/keyserver/src/updaters/thread-updaters.js b/keyserver/src/updaters/thread-updaters.js
--- a/keyserver/src/updaters/thread-updaters.js
+++ b/keyserver/src/updaters/thread-updaters.js
@@ -67,7 +67,7 @@
verifyUserOrCookieIDs,
} from '../fetchers/user-fetchers.js';
import type { Viewer } from '../session/viewer.js';
-import { neynarClient, fcCache } from '../utils/fc-cache.js';
+import { fcCache } from '../utils/fc-cache.js';
import { findUserIdentities } from '../utils/identity-utils.js';
import { redisCache } from '../utils/redis-cache.js';
import RelationshipChangeset from '../utils/relationship-changeset.js';
@@ -990,7 +990,7 @@
ignorePromiseRejections(
(async () => {
const followedChannels =
- await neynarClient?.fetchFollowedFarcasterChannels(farcasterID);
+ await fcCache?.getFollowedFarcasterChannelsForFID(farcasterID);
if (followedChannels) {
await Promise.allSettled(
followedChannels.map(followedChannel =>
diff --git a/lib/components/base-auto-join-community-handler.react.js b/lib/components/base-auto-join-community-handler.react.js
--- a/lib/components/base-auto-join-community-handler.react.js
+++ b/lib/components/base-auto-join-community-handler.react.js
@@ -63,7 +63,7 @@
const fid = useCurrentUserFID();
- const neynarClient = React.useContext(NeynarClientContext)?.client;
+ const fcCache = React.useContext(NeynarClientContext)?.fcCache;
const identityClientContext = React.useContext(IdentityClientContext);
invariant(identityClientContext, 'IdentityClientContext should be set');
@@ -87,7 +87,7 @@
}
prevCanQueryRef.current = canQuery;
- if (!canQuery || !isActive || !fid || !neynarClient) {
+ if (!canQuery || !isActive || !fid || !fcCache) {
return;
}
@@ -100,13 +100,17 @@
})();
const followedFarcasterChannelsPromise =
- neynarClient.fetchFollowedFarcasterChannels(fid);
+ fcCache.getFollowedFarcasterChannelsForFID(fid);
const [authMetadata, followedFarcasterChannels] = await Promise.all([
authMetadataPromise,
followedFarcasterChannelsPromise,
]);
+ if (!followedFarcasterChannels) {
+ return;
+ }
+
const headers = authMetadata
? createDefaultHTTPRequestHeaders(authMetadata)
: {};
@@ -178,7 +182,7 @@
threadInfos,
fid,
isActive,
- neynarClient,
+ fcCache,
getAuthMetadata,
keyserverInfos,
canQuery,
diff --git a/lib/utils/fc-cache.js b/lib/utils/fc-cache.js
--- a/lib/utils/fc-cache.js
+++ b/lib/utils/fc-cache.js
@@ -25,6 +25,14 @@
+farcasterChannel: ?NeynarChannel | Promise<?NeynarChannel>,
};
+type FollowedFarcasterChannelsQueryCacheEntry = {
+ +fid: string,
+ +expirationTime: number,
+ +followedFarcasterChannels:
+ | ?$ReadOnlyArray<NeynarChannel>
+ | Promise<?$ReadOnlyArray<NeynarChannel>>,
+};
+
class FCCache {
client: NeynarClient;
@@ -36,6 +44,12 @@
farcasterChannelQueryCache: Map<string, FarcasterChannelQueryCacheEntry> =
new Map();
+ // Maps from FIDs to a cache entry for the Farcaster user's followed channels
+ followedFarcasterChannelsQueryCache: Map<
+ string,
+ FollowedFarcasterChannelsQueryCacheEntry,
+ > = new Map();
+
constructor(client: NeynarClient) {
this.client = client;
}
@@ -236,6 +250,83 @@
return farcasterChannel;
}
+
+ getFollowedFarcasterChannelsForFID(
+ fid: string,
+ ): Promise<?$ReadOnlyArray<NeynarChannel>> {
+ const cachedChannelEntry =
+ this.getCachedFollowedFarcasterChannelsEntryForFID(fid);
+
+ if (cachedChannelEntry) {
+ return Promise.resolve(cachedChannelEntry.followedFarcasterChannels);
+ }
+
+ const fetchFollowedFarcasterChannelsPromise = (async () => {
+ let followedFarcasterChannels;
+ try {
+ followedFarcasterChannels = await Promise.race([
+ this.client.fetchFollowedFarcasterChannels(fid),
+ throwOnTimeout(`followed channels for ${fid}`),
+ ]);
+ } catch (e) {
+ console.log(e);
+ return null;
+ }
+
+ this.followedFarcasterChannelsQueryCache.set(fid, {
+ fid,
+ expirationTime: Date.now() + cacheTimeout,
+ followedFarcasterChannels,
+ });
+
+ return followedFarcasterChannels;
+ })();
+
+ this.followedFarcasterChannelsQueryCache.set(fid, {
+ fid,
+ expirationTime: Date.now() + queryTimeout * 2,
+ followedFarcasterChannels: fetchFollowedFarcasterChannelsPromise,
+ });
+
+ return fetchFollowedFarcasterChannelsPromise;
+ }
+
+ getCachedFollowedFarcasterChannelsEntryForFID(
+ fid: string,
+ ): ?FollowedFarcasterChannelsQueryCacheEntry {
+ const cacheResult = this.followedFarcasterChannelsQueryCache.get(fid);
+ if (!cacheResult) {
+ return undefined;
+ }
+
+ const { expirationTime } = cacheResult;
+ if (expirationTime <= Date.now()) {
+ this.followedFarcasterChannelsQueryCache.delete(fid);
+ return undefined;
+ }
+
+ return cacheResult;
+ }
+
+ getCachedFollowedFarcasterChannelsForFID(
+ fid: string,
+ ): ?$ReadOnlyArray<NeynarChannel> {
+ const cacheResult = this.getCachedFollowedFarcasterChannelsEntryForFID(fid);
+ if (!cacheResult) {
+ return undefined;
+ }
+
+ const { followedFarcasterChannels } = cacheResult;
+ if (
+ typeof followedFarcasterChannels !== 'object' ||
+ followedFarcasterChannels instanceof Promise ||
+ !followedFarcasterChannels
+ ) {
+ return undefined;
+ }
+
+ return followedFarcasterChannels;
+ }
}
export { FCCache };
diff --git a/native/community-settings/tag-farcaster-channel/tag-channel-button.react.js b/native/community-settings/tag-farcaster-channel/tag-channel-button.react.js
--- a/native/community-settings/tag-farcaster-channel/tag-channel-button.react.js
+++ b/native/community-settings/tag-farcaster-channel/tag-channel-button.react.js
@@ -41,17 +41,22 @@
const neynarClientContext = React.useContext(NeynarClientContext);
invariant(neynarClientContext, 'NeynarClientContext is missing');
- const { client } = neynarClientContext;
+ const { fcCache } = neynarClientContext;
React.useEffect(() => {
void (async () => {
- const channels = await client.fetchFollowedFarcasterChannels(fid);
+ const channels = await fcCache.getFollowedFarcasterChannelsForFID(fid);
+ if (!channels) {
+ return;
+ }
- const sortedChannels = channels.sort((a, b) => a.id.localeCompare(b.id));
+ const sortedChannels = [...channels].sort((a, b) =>
+ a.id.localeCompare(b.id),
+ );
setChannelOptions(sortedChannels);
})();
- }, [client, fid]);
+ }, [fcCache, fid]);
const activeTheme = useSelector(state => state.globalThemeInfo.activeTheme);
diff --git a/web/tag-farcaster-channel/create-farcaster-channel-tag-modal.react.js b/web/tag-farcaster-channel/create-farcaster-channel-tag-modal.react.js
--- a/web/tag-farcaster-channel/create-farcaster-channel-tag-modal.react.js
+++ b/web/tag-farcaster-channel/create-farcaster-channel-tag-modal.react.js
@@ -33,7 +33,7 @@
const neynarClientContext = React.useContext(NeynarClientContext);
invariant(neynarClientContext, 'NeynarClientContext is missing');
- const { client, fcCache } = neynarClientContext;
+ const { fcCache } = neynarClientContext;
const [channelOptions, setChannelOptions] = React.useState<
$ReadOnlyArray<DropdownOption>,
@@ -44,9 +44,12 @@
React.useEffect(() => {
void (async () => {
- const channels = await client.fetchFollowedFarcasterChannels(fid);
+ const channels = await fcCache.getFollowedFarcasterChannelsForFID(fid);
+ if (!channels) {
+ return;
+ }
- const sortedChannels = channels
+ const sortedChannels = [...channels]
.sort((a, b) => a.id.localeCompare(b.id))
.map(channel => ({
id: channel.id,
@@ -57,7 +60,7 @@
setChannelOptions(options);
})();
- }, [client, fid]);
+ }, [fcCache, fid]);
const onChangeSelectedOption = React.useCallback((option: string) => {
setError(null);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Dec 6, 8:52 PM (9 h, 56 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
5840754
Default Alt Text
D13976.1765054359.diff (8 KB)
Attached To
Mode
D13976: [lib][keyserver][native][web] Introduce FCCache.getFollowedFarcasterChannelsForFID
Attached
Detach File
Event Timeline
Log In to Comment