Skip to content

Commit 303da31

Browse files
authored
feat: publish highlighted posts (#3781)
Signed-off-by: Viktor Poluksht <viktor@daily.dev>
1 parent 21ddc1d commit 303da31

6 files changed

Lines changed: 136 additions & 20 deletions

File tree

.infra/application.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ debezium.source.database.user=%database_user%
88
debezium.source.database.password=%database_pass%
99
debezium.source.database.dbname=%database_dbname%
1010
debezium.source.database.server.name=api
11-
debezium.source.table.include.list=public.comment,public.user_comment,public.comment_mention,public.source_request,public.post,public.user,public.post_report,public.source_feed,public.settings,public.reputation_event,public.submission,public.user_state,public.notification_v2,public.source_member,public.feature,public.source,public.post_mention,public.content_image,public.comment_report,public.user_post,public.banner,public.post_relation,public.marketing_cta,public.squad_public_request,public.user_streak,public.bookmark,public.bookmark_list,public.user_company,public.source_report,public.user_top_reader,public.source_post_moderation,public.user_report,public.user_transaction,public.content_preference,public.campaign,public.opportunity_match,public.opportunity,public.organization,public.user_candidate_preference,public.user_experience,public.feedback,public.hot_take,public.user_stack,public.quest,public.quest_reward,public.quest_rotation,public.user_quest,public.user_quest_profile
11+
debezium.source.table.include.list=public.comment,public.user_comment,public.comment_mention,public.source_request,public.post,public.user,public.post_report,public.source_feed,public.settings,public.reputation_event,public.submission,public.user_state,public.notification_v2,public.source_member,public.feature,public.source,public.post_mention,public.content_image,public.comment_report,public.user_post,public.banner,public.post_relation,public.marketing_cta,public.squad_public_request,public.user_streak,public.bookmark,public.bookmark_list,public.user_company,public.source_report,public.user_top_reader,public.source_post_moderation,public.user_report,public.user_transaction,public.content_preference,public.campaign,public.opportunity_match,public.opportunity,public.organization,public.user_candidate_preference,public.user_experience,public.feedback,public.hot_take,public.user_stack,public.quest,public.quest_reward,public.quest_rotation,public.user_quest,public.user_quest_profile,public.post_highlight
1212
debezium.source.column.exclude.list=public.post.tsv,public.post.placeholder,public.source.flags,public.user_top_reader.image
1313
debezium.source.skip.messages.without.change=true
1414
debezium.source.plugin.name=pgoutput

__tests__/workers/cdc/primary.ts

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import {
33
CandidateStatus,
44
OpportunityState,
55
OpportunityType,
6+
PostHighlightedMessage,
67
} from '@dailydotdev/schema';
78
import {
89
Achievement,
@@ -36,6 +37,8 @@ import {
3637
Post,
3738
PostKeyword,
3839
PostMention,
40+
PostHighlight,
41+
PostHighlightSignificance,
3942
PostRelation,
4043
PostRelationType,
4144
PostReport,
@@ -3209,6 +3212,72 @@ describe('marketing cta', () => {
32093212
});
32103213
});
32113214

3215+
describe('post highlight', () => {
3216+
type ObjectType = PostHighlight;
3217+
3218+
const base: ChangeObject<ObjectType> = {
3219+
id: 'ph_1',
3220+
channel: 'javascript',
3221+
postId: 'p1',
3222+
highlightedAt: 1_770_000_000_000_000,
3223+
headline: 'JavaScript in 2026',
3224+
significance: PostHighlightSignificance.Major,
3225+
reason: 'Fast ecosystem update',
3226+
retiredAt: null,
3227+
createdAt: 1_770_000_000_000_000,
3228+
updatedAt: 1_770_000_000_000_000,
3229+
};
3230+
3231+
beforeEach(() => {
3232+
jest.clearAllMocks();
3233+
});
3234+
3235+
it('should publish highlighted event on create', async () => {
3236+
await expectSuccessfulBackground(
3237+
worker,
3238+
mockChangeMessage<ObjectType>({
3239+
after: base,
3240+
before: null,
3241+
op: 'c',
3242+
table: 'post_highlight',
3243+
}),
3244+
);
3245+
3246+
expectTypedEvent(
3247+
'api.v1.post-highlighted',
3248+
new PostHighlightedMessage({
3249+
highlightId: base.id,
3250+
channel: base.channel,
3251+
postId: base.postId,
3252+
headline: base.headline,
3253+
significance: base.significance,
3254+
reason: base.reason ?? undefined,
3255+
highlightedAt: base.highlightedAt,
3256+
}),
3257+
);
3258+
});
3259+
3260+
it('should not publish highlighted event on update', async () => {
3261+
const after: ChangeObject<ObjectType> = {
3262+
...base,
3263+
headline: 'Updated headline',
3264+
updatedAt: 1_770_000_100_000_000,
3265+
};
3266+
3267+
await expectSuccessfulBackground(
3268+
worker,
3269+
mockChangeMessage<ObjectType>({
3270+
after,
3271+
before: base,
3272+
op: 'u',
3273+
table: 'post_highlight',
3274+
}),
3275+
);
3276+
3277+
expect(triggerTypedEvent).not.toHaveBeenCalled();
3278+
});
3279+
});
3280+
32123281
describe('squad public request', () => {
32133282
type ObjectType = SquadPublicRequest;
32143283
const base: ChangeObject<ObjectType> = {

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
"@connectrpc/connect-fastify": "^1.6.1",
3939
"@connectrpc/connect-node": "^1.6.1",
4040
"@dailydotdev/graphql-redis-subscriptions": "^2.4.3",
41-
"@dailydotdev/schema": "0.3.3",
41+
"@dailydotdev/schema": "0.3.6",
4242
"@dailydotdev/ts-ioredis-pool": "^1.0.2",
4343
"@fastify/cookie": "^11.0.2",
4444
"@fastify/cors": "^11.2.0",

pnpm-lock.yaml

Lines changed: 27 additions & 17 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/common/typedPubsub.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import {
3636
MatchedCandidate,
3737
type OpportunityMessage,
3838
type OpportunityPreviewResult,
39+
PostHighlightedMessage,
3940
RecruiterAcceptedCandidateMatchMessage,
4041
type TransferResponse,
4142
type UserBriefingRequest,
@@ -189,6 +190,7 @@ export type PubSubSchema = {
189190
};
190191
'skadi.v2.campaign-updated': CampaignUpdateEventArgs;
191192
'api.v1.post-metrics-updated': z.infer<typeof postMetricsUpdatedTopic>;
193+
'api.v1.post-highlighted': PostHighlightedMessage;
192194
'api.v1.reputation-event': {
193195
op: ChangeMessage<unknown>['payload']['op'];
194196
payload: ChangeObject<ReputationEvent>;

src/workers/cdc/primary.ts

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
import { OpportunityState, OpportunityType } from '@dailydotdev/schema';
1+
import {
2+
OpportunityState,
3+
OpportunityType,
4+
PostHighlightedMessage,
5+
} from '@dailydotdev/schema';
26
import {
37
Alerts,
48
Banner,
@@ -44,6 +48,7 @@ import {
4448
UserStreak,
4549
UserTopReader,
4650
Feedback,
51+
PostHighlight,
4752
} from '../../entity';
4853
import { BookmarkList } from '../../entity/BookmarkList';
4954
import { HotTake } from '../../entity/user/HotTake';
@@ -2444,6 +2449,33 @@ const onFeedbackChange = async (
24442449
}
24452450
};
24462451

2452+
const onPostHighlightChange = async (
2453+
con: DataSource,
2454+
logger: FastifyBaseLogger,
2455+
data: ChangeMessage<PostHighlight>,
2456+
) => {
2457+
if (data.payload.op !== 'c' || !data.payload.after) {
2458+
return;
2459+
}
2460+
2461+
const { id, channel, postId, headline, significance, reason, highlightedAt } =
2462+
data.payload.after;
2463+
2464+
await triggerTypedEvent(
2465+
logger,
2466+
'api.v1.post-highlighted',
2467+
new PostHighlightedMessage({
2468+
highlightId: id,
2469+
channel,
2470+
postId,
2471+
headline,
2472+
significance,
2473+
reason: reason ?? undefined,
2474+
highlightedAt,
2475+
}),
2476+
);
2477+
};
2478+
24472479
const onHotTakeChange = async (
24482480
con: DataSource,
24492481
logger: FastifyBaseLogger,
@@ -2713,6 +2745,9 @@ const worker: Worker = {
27132745
case getTableName(con, Feedback):
27142746
await onFeedbackChange(con, logger, data);
27152747
break;
2748+
case getTableName(con, PostHighlight):
2749+
await onPostHighlightChange(con, logger, data);
2750+
break;
27162751
case getTableName(con, HotTake):
27172752
await onHotTakeChange(con, logger, data);
27182753
break;

0 commit comments

Comments
 (0)