Skip to content

Commit 2a5008d

Browse files
committed
fix: read saved no-ai setting from replica
Use the read replica for the saved no-ai feed flag and cover the TIME ranking path so the v2 resolver behaves consistently across both feed generators. Made-with: Cursor
1 parent 6147be1 commit 2a5008d

2 files changed

Lines changed: 83 additions & 32 deletions

File tree

__tests__/feeds.ts

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -775,6 +775,54 @@ describe('query feed', () => {
775775
expect(res.data.feed.edges.length).toEqual(2);
776776
});
777777

778+
it('should include no-ai blocked tags and title words for TIME ranking when the saved setting is enabled', async () => {
779+
loggedUser = '1';
780+
await saveFeedFixtures();
781+
await saveFixtures(con, Settings, [
782+
{
783+
userId: '1',
784+
flags: {
785+
noAiFeedEnabled: true,
786+
},
787+
},
788+
]);
789+
nock('http://localhost:6002')
790+
.post('/config')
791+
.reply(200, {
792+
user_id: '1',
793+
config: {
794+
providers: {},
795+
},
796+
});
797+
nock('http://localhost:6000')
798+
.post('/feed.json', (body) => {
799+
expect(body.blocked_tags).toEqual(
800+
expect.arrayContaining(['golang', 'ai', 'openai']),
801+
);
802+
expect(body.blocked_title_words).toEqual(
803+
expect.arrayContaining(['Claude', 'Elon Musk']),
804+
);
805+
expect(body.feed_config_name).toBe('for_you_by_date');
806+
807+
return true;
808+
})
809+
.reply(200, {
810+
data: [{ post_id: 'p1' }, { post_id: 'p4' }],
811+
cursor: 'b',
812+
});
813+
814+
const res = await client.query(QUERY, {
815+
variables: {
816+
...variables,
817+
ranking: Ranking.TIME,
818+
version: 20,
819+
},
820+
});
821+
822+
expect(res.errors).toBeFalsy();
823+
expect(res.data.feed.edges.length).toEqual(2);
824+
});
825+
778826
describe('youtube content', () => {
779827
beforeEach(async () => {
780828
await saveFixtures(con, YouTubePost, videoPostsFixture);

src/schema/feeds.ts

Lines changed: 35 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ import { SourceMemberRoles } from '../roles';
8989
import { ContentPreferenceKeyword } from '../entity/contentPreference/ContentPreferenceKeyword';
9090
import { briefingPostIdsMaxItems } from '../common/brief';
9191
import { NO_AI_BLOCKED_TAGS, NO_AI_BLOCKED_WORDS } from '../common/noAiFilter';
92+
import { queryReadReplica } from '../common/queryReadReplica';
9293

9394
interface GQLTagsCategory {
9495
id: string;
@@ -1394,9 +1395,11 @@ const wrapGeneratorWithNoAi = (generator: FeedGenerator): FeedGenerator =>
13941395
}));
13951396

13961397
const isSavedNoAiEnabled = async (ctx: AuthContext): Promise<boolean> => {
1397-
const settings = await ctx.con.getRepository(Settings).findOneBy({
1398-
userId: ctx.userId,
1399-
});
1398+
const settings = await queryReadReplica(ctx.con, ({ queryRunner }) =>
1399+
queryRunner.manager.getRepository(Settings).findOneBy({
1400+
userId: ctx.userId,
1401+
}),
1402+
);
14001403

14011404
return settings?.flags?.noAiFeedEnabled ?? false;
14021405
};
@@ -1601,37 +1604,37 @@ export const resolvers: IResolvers<unknown, BaseContext> = {
16011604
return anonymousFeedResolverV1(source, args, ctx, info);
16021605
},
16031606
feed: async (source, args: ConfiguredFeedArgs, ctx: AuthContext, info) => {
1604-
if (args.version >= 2 && args.ranking === Ranking.POPULARITY) {
1605-
const generator = versionToFeedGenerator(args.version);
1607+
if (args.version >= 2) {
16061608
const shouldApplyNoAi = args.noAi || (await isSavedNoAiEnabled(ctx));
1609+
const getGeneratorWithNoAi = (generator: FeedGenerator): FeedGenerator =>
1610+
shouldApplyNoAi ? wrapGeneratorWithNoAi(generator) : generator;
16071611

1608-
return feedResolverCursor(
1609-
source,
1610-
{
1611-
...(args as FeedArgs),
1612-
generator: shouldApplyNoAi
1613-
? wrapGeneratorWithNoAi(generator)
1614-
: generator,
1615-
},
1616-
ctx,
1617-
info,
1618-
);
1619-
}
1620-
if (args.version >= 2 && args.ranking === Ranking.TIME) {
1621-
const generator = versionToTimeFeedGenerator(args.version);
1622-
const shouldApplyNoAi = args.noAi || (await isSavedNoAiEnabled(ctx));
1623-
1624-
return feedResolverCursor(
1625-
source,
1626-
{
1627-
...(args as FeedArgs),
1628-
generator: shouldApplyNoAi
1629-
? wrapGeneratorWithNoAi(generator)
1630-
: generator,
1631-
},
1632-
ctx,
1633-
info,
1634-
);
1612+
if (args.ranking === Ranking.POPULARITY) {
1613+
return feedResolverCursor(
1614+
source,
1615+
{
1616+
...(args as FeedArgs),
1617+
generator: getGeneratorWithNoAi(
1618+
versionToFeedGenerator(args.version),
1619+
),
1620+
},
1621+
ctx,
1622+
info,
1623+
);
1624+
}
1625+
if (args.ranking === Ranking.TIME) {
1626+
return feedResolverCursor(
1627+
source,
1628+
{
1629+
...(args as FeedArgs),
1630+
generator: getGeneratorWithNoAi(
1631+
versionToTimeFeedGenerator(args.version),
1632+
),
1633+
},
1634+
ctx,
1635+
info,
1636+
);
1637+
}
16351638
}
16361639
return feedResolverV1(source, args, ctx, info);
16371640
},

0 commit comments

Comments
 (0)