-
-
Notifications
You must be signed in to change notification settings - Fork 6.1k
fix(instagram): persist publish state at the publish boundary to prevent duplicates and false failures #1681
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -594,15 +594,44 @@ export class InstagramProvider | |
| }; | ||
| } | ||
|
|
||
| // The post is already live when this is called — a failure fetching the | ||
| // permalink must not fail the publish (it used to mark a published post | ||
| // as ERROR, invite duplicate retries and email a false failure). | ||
| private async getPermalink( | ||
| type: string, | ||
| mediaId: string, | ||
| token: string, | ||
| fallback: string | ||
| ) { | ||
| try { | ||
| const { permalink } = await ( | ||
| await this.fetch( | ||
| `https://${type}/v20.0/${mediaId}?fields=permalink&access_token=${token}`, | ||
| undefined, | ||
| 'instagram-permalink' | ||
| ) | ||
| ).json(); | ||
| return permalink || fallback; | ||
| } catch (err) { | ||
| return fallback; | ||
| } | ||
| } | ||
|
|
||
| async post( | ||
| id: string, | ||
| token: string, | ||
| postDetails: PostDetails<InstagramDto>[], | ||
| integration: Integration, | ||
| progress?: (response: PostResponse) => Promise<unknown> | unknown, | ||
| type = 'graph.facebook.com' | ||
| ): Promise<PostResponse[]> { | ||
| const [accessToken, userToken] = token.split('___'); | ||
| const [firstPost] = postDetails; | ||
| // Used when the post is live but the permalink can't be fetched — the | ||
| // publish must still be reported as a success. | ||
| const fallbackUrl = `https://www.instagram.com/${ | ||
| integration.profile || '' | ||
| }`; | ||
| console.log('in progress', id); | ||
| const isStory = firstPost.settings.post_type === 'story'; | ||
| const isTrialReel = this.assetBoolean(firstPost.settings.is_trial_reel); | ||
|
|
@@ -676,7 +705,8 @@ export class InstagramProvider | |
| `https://${type}/v20.0/${id}/media?${mediaType}${isCarousel}${collaborators}${trialParams}${audioConfiguration}&access_token=${accessToken}${caption}`, | ||
| { | ||
| method: 'POST', | ||
| } | ||
| }, | ||
| 'instagram-create-media' | ||
| ) | ||
| ).json(); | ||
| console.log('in progress2', id); | ||
|
|
@@ -695,7 +725,7 @@ export class InstagramProvider | |
| userToken || accessToken | ||
| }&fields=status_code`, | ||
| undefined, | ||
| '', | ||
| 'instagram-media-status', | ||
| 0, | ||
| true | ||
| ) | ||
|
|
@@ -719,19 +749,25 @@ export class InstagramProvider | |
| `https://${type}/v20.0/${id}/media_publish?creation_id=${mediaCreationId}&access_token=${accessToken}&field=id`, | ||
| { | ||
| method: 'POST', | ||
| } | ||
| }, | ||
| 'instagram-media-publish' | ||
| ) | ||
| ).json(); | ||
| lastMediaId = mediaId; | ||
|
|
||
| const { permalink } = await ( | ||
| await this.fetch( | ||
| `https://${type}/v20.0/${mediaId}?fields=permalink&access_token=${ | ||
| userToken || accessToken | ||
| }` | ||
| ) | ||
| ).json(); | ||
| lastPermalink = permalink; | ||
| await progress?.({ | ||
| id: firstPost.id, | ||
| postId: mediaId, | ||
| releaseURL: fallbackUrl, | ||
| status: 'success', | ||
| }); | ||
|
|
||
| lastPermalink = await this.getPermalink( | ||
| type, | ||
| mediaId, | ||
| userToken || accessToken, | ||
| fallbackUrl | ||
| ); | ||
| } | ||
|
Comment on lines
+761
to
771
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Bug: A partial failure during a multi-story Instagram post causes duplicate stories to be published upon retry due to flawed deduplication logic. Suggested FixThe publishing logic should be updated to handle retries of multi-part posts. Instead of re-publishing all items, the loop should check which individual stories have already been published and skip them. This could be achieved by tracking the published state of each media item separately, rather than relying on a single Prompt for AI AgentAlso affects:
Did we get this right? 👍 / 👎 to inform future reviews. |
||
|
|
||
| return [ | ||
|
|
@@ -748,17 +784,24 @@ export class InstagramProvider | |
| `https://${type}/v20.0/${id}/media_publish?creation_id=${medias[0]}&access_token=${accessToken}&field=id`, | ||
| { | ||
| method: 'POST', | ||
| } | ||
| }, | ||
| 'instagram-media-publish' | ||
| ) | ||
| ).json(); | ||
|
|
||
| const { permalink } = await ( | ||
| await this.fetch( | ||
| `https://${type}/v20.0/${mediaId}?fields=permalink&access_token=${ | ||
| userToken || accessToken | ||
| }` | ||
| ) | ||
| ).json(); | ||
| await progress?.({ | ||
| id: firstPost.id, | ||
| postId: mediaId, | ||
| releaseURL: fallbackUrl, | ||
| status: 'success', | ||
| }); | ||
|
|
||
| const permalink = await this.getPermalink( | ||
| type, | ||
| mediaId, | ||
| userToken || accessToken, | ||
| fallbackUrl | ||
| ); | ||
|
|
||
| return [ | ||
| { | ||
|
|
@@ -778,7 +821,8 @@ export class InstagramProvider | |
| )}&access_token=${accessToken}`, | ||
| { | ||
| method: 'POST', | ||
| } | ||
| }, | ||
| 'instagram-create-carousel' | ||
| ) | ||
| ).json(); | ||
|
|
||
|
|
@@ -796,7 +840,7 @@ export class InstagramProvider | |
| userToken || accessToken | ||
| }`, | ||
| undefined, | ||
| '', | ||
| 'instagram-media-status', | ||
| 0, | ||
| true | ||
| ) | ||
|
|
@@ -810,17 +854,24 @@ export class InstagramProvider | |
| `https://${type}/v20.0/${id}/media_publish?creation_id=${containerId}&access_token=${accessToken}&field=id`, | ||
| { | ||
| method: 'POST', | ||
| } | ||
| }, | ||
| 'instagram-media-publish' | ||
| ) | ||
| ).json(); | ||
|
|
||
| const { permalink } = await ( | ||
| await this.fetch( | ||
| `https://${type}/v20.0/${mediaId}?fields=permalink&access_token=${ | ||
| userToken || accessToken | ||
| }` | ||
| ) | ||
| ).json(); | ||
| await progress?.({ | ||
| id: firstPost.id, | ||
| postId: mediaId, | ||
| releaseURL: fallbackUrl, | ||
| status: 'success', | ||
| }); | ||
|
|
||
| const permalink = await this.getPermalink( | ||
| type, | ||
| mediaId, | ||
| userToken || accessToken, | ||
| fallbackUrl | ||
| ); | ||
|
|
||
| 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.
Bug: The deduplication logic for LinkedIn posts is ineffective because the providers don't invoke the
progresscallback, which can lead to duplicate posts on retry.Severity: MEDIUM
Suggested Fix
Modify the LinkedIn providers (
linkedin.provider.tsandlinkedin.page.provider.ts) to invoke theprogresscallback with the remote post ID after a successful API call. This will persist the ID, allowing the deduplication guard inpostSocialto prevent duplicate posts during retries.Prompt for AI Agent