fix: fetch all channel highlights (including retired) to prevent duplicate key error#3731
Closed
fix: fetch all channel highlights (including retired) to prevent duplicate key error#3731
Conversation
…icate key error When replaceHighlightsForChannel only fetched active highlights (retiredAt IS NULL), re-admitting a previously retired post would attempt an INSERT instead of an UPDATE, violating the UQ_post_highlight_channel_post unique constraint. Root cause: The existingByPostId map was built from only active records, so retired posts had no known ID. TypeORM's save() with id=undefined performs INSERT. Fix: Fetch ALL existing highlights for the channel (active + retired) so the map always contains the correct row ID. This turns the INSERT into an UPDATE when a retired post is re-selected, and clears its retiredAt back to null. Also narrows the retirement filter to only retire currently-active highlights that are no longer in the incoming set (previously retired posts should stay retired unless re-admitted). Adds dedicated tests for replaceHighlightsForChannel covering: - Basic insert - Retiring removed highlights - Re-admitting a retired post (the regression case) - Cross-channel isolation - Empty items handling - Updating headline/significance on active posts
|
🍹 The Update (preview) for dailydotdev/api/prod (at 1573ed4) was successful. ✨ Neo ExplanationThis is a standard application rollout deploying a new build across all 7 services, 38 cron jobs, and triggering fresh database and ClickHouse migration jobs to run against the updated schema.Root Cause AnalysisA new version of the API application has been built and is being deployed to production. Every workload in the cluster is being updated to run the new container image, and the versioned migration jobs from the previous release are being replaced with new ones for this release. Dependency ChainThe new container image version cascades uniformly across all workloads:
Risk AnalysisNo stateful resources (databases, storage buckets, persistent volumes) are being replaced or deleted. The migration jobs are transient by design and follow the normal create/delete lifecycle per release. Deployments use rolling updates by default in Kubernetes, so there is no expected downtime. Resource Changes Name Type Operation
~ vpc-native-update-current-streak-cron kubernetes:batch/v1:CronJob update
~ vpc-native-update-trending-cron kubernetes:batch/v1:CronJob update
~ vpc-native-generic-referral-reminder-cron kubernetes:batch/v1:CronJob update
~ vpc-native-update-tags-str-cron kubernetes:batch/v1:CronJob update
~ vpc-native-ws-deployment kubernetes:apps/v1:Deployment update
~ vpc-native-daily-digest-cron kubernetes:batch/v1:CronJob update
~ vpc-native-channel-digests-cron kubernetes:batch/v1:CronJob update
~ vpc-native-clean-zombie-user-companies-cron kubernetes:batch/v1:CronJob update
~ vpc-native-update-highlighted-views-cron kubernetes:batch/v1:CronJob update
- vpc-native-api-clickhouse-migration-4847c30e kubernetes:batch/v1:Job delete
~ vpc-native-update-source-public-threshold-cron kubernetes:batch/v1:CronJob update
~ vpc-native-personalized-digest-cron kubernetes:batch/v1:CronJob update
~ vpc-native-update-views-cron kubernetes:batch/v1:CronJob update
~ vpc-native-user-profile-analytics-clickhouse-cron kubernetes:batch/v1:CronJob update
~ vpc-native-rotate-daily-quests-cron kubernetes:batch/v1:CronJob update
~ vpc-native-clean-expired-better-auth-sessions-cron kubernetes:batch/v1:CronJob update
+ vpc-native-api-clickhouse-migration-53a7329e kubernetes:batch/v1:Job create
~ vpc-native-clean-channel-highlights-cron kubernetes:batch/v1:CronJob update
+ vpc-native-api-db-migration-53a7329e kubernetes:batch/v1:Job create
~ vpc-native-calculate-top-readers-cron kubernetes:batch/v1:CronJob update
~ vpc-native-check-analytics-report-cron kubernetes:batch/v1:CronJob update
~ vpc-native-clean-zombie-images-cron kubernetes:batch/v1:CronJob update
~ vpc-native-update-tag-recommendations-cron kubernetes:batch/v1:CronJob update
~ vpc-native-user-posts-analytics-refresh-cron kubernetes:batch/v1:CronJob update
~ vpc-native-user-profile-analytics-history-clickhouse-cron kubernetes:batch/v1:CronJob update
~ vpc-native-user-profile-updated-sync-cron kubernetes:batch/v1:CronJob update
~ vpc-native-clean-stale-user-transactions-cron kubernetes:batch/v1:CronJob update
~ vpc-native-private-deployment kubernetes:apps/v1:Deployment update
~ vpc-native-channel-highlights-cron kubernetes:batch/v1:CronJob update
~ vpc-native-post-analytics-clickhouse-cron kubernetes:batch/v1:CronJob update
~ vpc-native-generate-search-invites-cron kubernetes:batch/v1:CronJob update
~ vpc-native-hourly-notification-cron kubernetes:batch/v1:CronJob update
~ vpc-native-worker-job-deployment kubernetes:apps/v1:Deployment update
~ vpc-native-update-achievement-rarity-cron kubernetes:batch/v1:CronJob update
~ vpc-native-personalized-digest-deployment kubernetes:apps/v1:Deployment update
~ vpc-native-rotate-weekly-quests-cron kubernetes:batch/v1:CronJob update
~ vpc-native-deployment kubernetes:apps/v1:Deployment update
~ vpc-native-bg-deployment kubernetes:apps/v1:Deployment update
~ vpc-native-clean-gifted-plus-cron kubernetes:batch/v1:CronJob update
~ vpc-native-post-analytics-history-day-clickhouse-cron kubernetes:batch/v1:CronJob update
~ vpc-native-validate-active-users-cron kubernetes:batch/v1:CronJob update
... and 10 other changes |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
replaceHighlightsForChannelinapi-bgis throwing ~434 errors/6h on theopensourcechannel:Both api-bg pods (
td8jqandtx8jf) are affected. Every scheduled run ofapi.generate-channel-highlightis failing with retries piling up.Root Cause
replaceHighlightsForChannelonly fetched active highlights (retiredAt IS NULL) to build its ID lookup map. When a previously retired post was re-selected by the evaluator, its existing row ID was unknown, so TypeORM'ssave()attempted anINSERTinstead of anUPDATE— hitting the unique constraint on(channel, postId).Fix
Fetch all existing highlights for the channel (active + retired) so the
existingByPostIdmap always contains the correct row ID. This turns the conflicting INSERT into an UPDATE that clearsretiredAtback tonull.Also narrows the retirement filter to only retire currently-active highlights not in the incoming set.
Tests
Added
__tests__/common/channelHighlightPublish.tscovering: