-
Notifications
You must be signed in to change notification settings - Fork 110
feat: add support for multiple squad posting and notification dedup #3154
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
🍹 The Update (preview) for dailydotdev/api/prod (at 139b1bf) was successful. Resource Changes Name Type Operation
~ vpc-native-update-highlighted-views-cron kubernetes:batch/v1:CronJob update
~ vpc-native-personalized-digest-deployment kubernetes:apps/v1:Deployment update
~ vpc-native-update-views-cron kubernetes:batch/v1:CronJob update
~ vpc-native-hourly-notification-cron kubernetes:batch/v1:CronJob update
~ vpc-native-clean-zombie-user-companies-cron kubernetes:batch/v1:CronJob update
~ vpc-native-generate-search-invites-cron kubernetes:batch/v1:CronJob update
+ vpc-native-api-db-migration-ea9dd875 kubernetes:batch/v1:Job create
~ vpc-native-bg-deployment kubernetes:apps/v1:Deployment update
~ vpc-native-sync-subscription-with-cio-cron kubernetes:batch/v1:CronJob update
~ vpc-native-daily-digest-cron kubernetes:batch/v1:CronJob update
~ vpc-native-personalized-digest-cron kubernetes:batch/v1:CronJob update
~ vpc-native-update-source-public-threshold-cron kubernetes:batch/v1:CronJob update
~ vpc-native-ws-deployment kubernetes:apps/v1:Deployment update
~ vpc-native-validate-active-users-cron kubernetes:batch/v1:CronJob update
~ vpc-native-private-deployment kubernetes:apps/v1:Deployment update
~ vpc-native-clean-zombie-users-cron kubernetes:batch/v1:CronJob update
- vpc-native-api-db-migration-34ee84f3 kubernetes:batch/v1:Job delete
~ vpc-native-calculate-top-readers-cron kubernetes:batch/v1:CronJob update
~ vpc-native-clean-zombie-images-cron kubernetes:batch/v1:CronJob update
~ vpc-native-clean-gifted-plus-cron kubernetes:batch/v1:CronJob update
~ vpc-native-update-source-tag-view-cron kubernetes:batch/v1:CronJob update
~ vpc-native-update-tag-recommendations-cron kubernetes:batch/v1:CronJob update
~ vpc-native-post-analytics-clickhouse-cron kubernetes:batch/v1:CronJob update
~ vpc-native-update-current-streak-cron kubernetes:batch/v1:CronJob update
~ vpc-native-update-tags-str-cron kubernetes:batch/v1:CronJob update
~ vpc-native-temporal-deployment kubernetes:apps/v1:Deployment update
~ vpc-native-generic-referral-reminder-cron kubernetes:batch/v1:CronJob update
~ vpc-native-clean-stale-user-transactions-cron kubernetes:batch/v1:CronJob update
~ vpc-native-check-analytics-report-cron kubernetes:batch/v1:CronJob update
~ vpc-native-update-trending-cron kubernetes:batch/v1:CronJob update
~ vpc-native-post-analytics-history-day-clickhouse-cron kubernetes:batch/v1:CronJob update
~ vpc-native-deployment kubernetes:apps/v1:Deployment update
- vpc-native-api-clickhouse-migration-34ee84f3 kubernetes:batch/v1:Job delete
+ vpc-native-api-clickhouse-migration-ea9dd875 kubernetes:batch/v1:Job create
|
… with validation and tests
| }); | ||
| }; | ||
|
|
||
| export const createFreeformPost = async ({ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Renamed, now createFreeformPost is a new function that also do some checks before insert
| export const createFreeformPost = async ( | ||
| ctx: AuthContext, | ||
| args: CreatePostArgs, | ||
| ) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the old createFreeformPost function plus the checks that the endpoint was doing before calling it
| })); | ||
| }, | ||
| editPost: async ( | ||
| source, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
was unused
| type PostPermissions = SourcePermissions.Post | SourcePermissions.PostRequest; | ||
|
|
||
| export const canPostToSquad = ( | ||
| ctx: Context, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was not used by the function
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This pull request adds support for multiple squad posting functionality and implements notification deduplication. The key changes enable users to create posts across multiple sources (squads) with a single operation while preventing duplicate notifications through a deduplication mechanism.
- Adds a new
createMultipleSourcePostsGraphQL mutation for cross-squad posting - Implements notification deduplication using dedupKey to prevent duplicate notifications
- Adds warning reasons for moderation items to flag multiple squad posts and duplicated content
Reviewed Changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
src/schema/posts.ts |
Adds new GraphQL mutation and resolver for multiple source posting with validation and permission checks |
src/common/post.ts |
Implements core logic for creating posts across multiple sources with deduplication and warning systems |
src/notifications/ |
Adds deduplication support to notifications system using dedupKey parameter |
src/entity/SourcePostModeration.ts |
Adds warning reasons enum and deduplication flags to moderation system |
src/migration/ |
Creates database index for deduplication key performance optimization |
__tests__/posts.ts |
Comprehensive test coverage for multiple source posting functionality |
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
src/common/post.ts
Outdated
| title: z.string().max(MAX_TITLE_LENGTH).optional(), | ||
| content: z.string().max(MAX_CONTENT_LENGTH).optional(), | ||
| image: z.custom<Promise<FileUpload>>(), | ||
| sourceIds: z.array(z.string()).min(1).max(MAX_MULTIPLE_POST_SOURCE_LIMIT), |
Copilot
AI
Sep 25, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The constant MAX_MULTIPLE_POST_SOURCE_LIMIT is defined but never used elsewhere. Consider adding a descriptive comment explaining why this specific limit exists and what happens when it's exceeded.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I half agree with the bot. I'm not sure if we need to define constants that aren't exported and only used one place in zod schemas ? 😅
Co-authored-by: Copilot <[email protected]>
Co-authored-by: Copilot <[email protected]>
capJavert
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Feels almost there, just please address final comments and I think we still miss tests for notification dedup part.
src/notifications/common.ts
Outdated
| return [uniqueKey, referenceId, referenceType, dedupKey] | ||
| .filter(Boolean) | ||
| .join(':'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
still missing post notification tests for dedup logic?
src/common/post.ts
Outdated
| return WarningReason.MultipleSquadPost; | ||
| } | ||
|
|
||
| return; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not needed at the end?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed
src/common/post.ts
Outdated
| return WarningReason.DuplicatedInSameSquad; | ||
| } | ||
|
|
||
| const isDuplicatedAcrossSquads = await hasDuplicatedPostBy(con, { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why do we call hasDuplicatedPostBy twice, once with sourceId once without? Would it not do the same thing if sourceId is not passed thus doing the query twice?
rebelchris
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Non blocking, but good to check that one by Ante.
Logic wise will approve from my side.
src/common/post.ts
Outdated
| return; | ||
| } | ||
|
|
||
| const isDuplicatedInSameSquad = await hasDuplicatedPostBy(con, { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I still think this could be 1 query 😅
| return await ctx.con.transaction(async (entityManager) => { | ||
| const output: Array<MultipleSourcesPostResult> = []; | ||
| for (const sourceId of sourceIds) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@capJavert the for loop works well with async right?
Or should be for await (?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
works ok yes
|
@claude please review this, but focus only on breaking changes. |
|
Claude finished @rebelchris's task —— View job Breaking Changes ReviewReviewing PR for breaking changes as requested by @rebelchris. Tasks:
✅ NO BREAKING CHANGES IDENTIFIEDAfter thorough analysis of this PR, I found no breaking changes: GraphQL API Changes:
Database Schema Changes:
Entity & Data Model Changes:
Core Logic Changes:
Summary: This PR is safe to merge from a breaking changes perspective. All changes are additive features that enhance functionality without affecting existing APIs or data structures. |
Jira ticket
MI-1043