Skip to content

feat(sync): prevent stale data on retry, improve logging and error handling#4562

Merged
miguelpeixe merged 12 commits into
trunkfrom
feat/sync-as-logging-error-handling
Mar 20, 2026
Merged

feat(sync): prevent stale data on retry, improve logging and error handling#4562
miguelpeixe merged 12 commits into
trunkfrom
feat/sync-as-logging-error-handling

Conversation

@miguelpeixe
Copy link
Copy Markdown
Member

@miguelpeixe miguelpeixe commented Mar 13, 2026

All Submissions:

Changes proposed in this Pull Request:

Prevent stale data on sync retries by storing the user ID instead of a contact data snapshot. When a retry executes, fresh contact data is fetched from the database, ensuring retries always push the latest reader state rather than potentially outdated information captured at the time of the original failure.

Improve ActionScheduler logging by writing per-integration success/failure messages to the AS log on both the initial sync and retries, making it easier to diagnose sync issues from the ActionScheduler admin UI.

Preserve AS action ID for queued syncs so that deferred syncs executed via run_queued_syncs() can still log against the correct ActionScheduler action.

Mark final retries as failed in ActionScheduler by throwing an exception when the last retry fails. In our custom UI, being explored in #4561, we'll be able to manually trigger a run for the failed action.

How to test the changes in this Pull Request:

  1. Register a new reader and verify sync completes successfully
  2. Check AS and confirm you get the successful sync logs in the data event handler action
  3. Change your ESP config to use invalid credentials
  4. Simulate a sync failure and confirm that AS logs show per-integration error messages.
  5. Manually run every pending retry until it exhausts and confirm:
    • The newspack_sync_retry_exhausted action fires with user_id (not a contact array).
    • The final retry throws an exception, causing ActionScheduler to mark the action as "failed".
    • No further retries are scheduled.
  6. Logged in as the reader, go through the email change flow
  7. Before the next retry, restore the ESP configuration
  8. Confirm the "Email_Change" sync works without regression on the next retry

Other information:

  • Have you added an explanation of what your changes do and why you'd like us to include them?
  • Have you written new tests for your changes, as applicable?
  • Have you successfully ran tests with your changes locally?

@miguelpeixe miguelpeixe changed the title feat(sync): enhance logging and improve error handling during retries feat(sync): prevent stale data on retry, improve logging and error handling Mar 13, 2026
@miguelpeixe miguelpeixe marked this pull request as ready for review March 13, 2026 20:50
@miguelpeixe miguelpeixe requested a review from a team as a code owner March 13, 2026 20:50
@miguelpeixe miguelpeixe self-assigned this Mar 13, 2026
@miguelpeixe miguelpeixe added the [Status] Needs Review The issue or pull request needs to be reviewed label Mar 13, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a 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 PR updates Reader Activation contact sync retry behavior to avoid stale data on retries by scheduling retries using a WordPress user_id, and expands ActionScheduler logging to improve observability of integration sync outcomes.

Changes:

  • Store user_id in ActionScheduler retry payloads and fetch fresh contact data at retry execution time.
  • Add per-integration success/failure log messages to ActionScheduler logs, and preserve the AS action ID through deferred/queued sync execution.
  • Update unit tests and WooCommerce mocks to reflect the new retry payload shape and customer email handling.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.

File Description
includes/reader-activation/sync/class-contact-sync.php Switch retry payloads to user_id, add AS logging, and adjust retry execution/error behavior.
tests/unit-tests/reader-activation-sync.php Update tests for user_id-based retries and last-retry exception behavior.
tests/mocks/wc-mocks.php Extend WC_Customer mock to support billing email getters/setters used by contact building.
Comments suppressed due to low confidence (1)

includes/reader-activation/sync/class-contact-sync.php:261

  • The newspack_sync_retry_exhausted payload was changed from including contact to user_id only. Downstream consumers (e.g. Alert_Manager::handle_sync_retry_exhausted() and record_failure()) still expect payload['contact']['email'], which will trigger PHP warnings and result in missing/incorrect alert context. Consider keeping backward compatibility by including contact (or at least contact_email) in the payload, or updating all listeners/tests to the new schema in the same PR.
			do_action(
				'newspack_sync_retry_exhausted',
				[
					'integration_id' => $integration_id,
					'user_id'        => $user_id,
					'context'        => $context,
					'retry_count'    => self::MAX_RETRIES,
					'reason'         => $error_message,
				]

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

Comment thread includes/reader-activation/sync/class-contact-sync.php
Comment thread tests/unit-tests/reader-activation-sync.php Outdated
Comment thread includes/reader-activation/sync/class-contact-sync.php Outdated
Comment thread includes/reader-activation/sync/class-contact-sync.php Outdated
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 5 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

Comment thread tests/unit-tests/reader-activation-sync.php Outdated
Comment thread includes/reader-activation/sync/class-contact-sync.php
Comment thread includes/reader-activation/sync/class-contact-sync.php Outdated
Comment thread includes/reader-activation/sync/class-contact-sync.php Outdated
Comment thread includes/reader-activation/sync/class-contact-sync.php
Copy link
Copy Markdown
Contributor

@chickenn00dle chickenn00dle left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good @miguelpeixe!

Left a few nonblocking comments, but this is good to go as far as I'm concerned.

Comment thread includes/reader-activation/sync/class-contact-sync.php Outdated
Comment thread includes/reader-activation/sync/class-contact-sync.php
Comment thread includes/reader-activation/sync/class-contact-sync.php Outdated
@github-actions github-actions Bot added [Status] Approved The pull request has been reviewed and is ready to merge and removed [Status] Needs Review The issue or pull request needs to be reviewed labels Mar 19, 2026
Copy link
Copy Markdown
Contributor

@chickenn00dle chickenn00dle left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for addressing the feedback @miguelpeixe!

This looks good 👍

@miguelpeixe miguelpeixe merged commit 5467f34 into trunk Mar 20, 2026
9 checks passed
@miguelpeixe miguelpeixe deleted the feat/sync-as-logging-error-handling branch March 20, 2026 15:53
@github-actions
Copy link
Copy Markdown

Hey @miguelpeixe, good job getting this PR merged! 🎉

Now, the needs-changelog label has been added to it.

Please check if this PR needs to be included in the "Upcoming Changes" and "Release Notes" doc. If it doesn't, simply remove the label.

If it does, please add an entry to our shared document, with screenshots and testing instructions if applicable, then remove the label.

Thank you! ❤️

matticbot pushed a commit that referenced this pull request Apr 2, 2026
# [6.37.0-alpha.1](v6.36.1...v6.37.0-alpha.1) (2026-04-02)

### Bug Fixes

* **card-settings-group:** change default actionType from chevron to none ([#4610](#4610)) ([00505ed](00505ed))
* **post-date:** preserve classic theme markup and fix archive titles ([#4602](#4602)) ([c5fb825](c5fb825))
* remove removal of block visibility ([#4595](#4595)) ([9396379](9396379))

### Features

* **access-control:** filter available lists by content restrictions ([#4589](#4589)) ([959127f](959127f)), closes [#4581](#4581) [#4583](#4583) [#4590](#4590)
* **access-control:** premium newsletters UI ([#4577](#4577)) ([6f8c891](6f8c891)), closes [#4581](#4581) [#4583](#4583) [#4590](#4590)
* **author-profile-social:** add support for colors, block spacing, brand style ([#4509](#4509)) ([21cf4c9](21cf4c9))
* campaigns wizard light UI refresh ([#4588](#4588)) ([6078c4b](6078c4b))
* **color-picker:** simplify component to use basecontrol ([#4581](#4581)) ([ff677ea](ff677ea))
* **components:** add CardFeature component ([#4583](#4583)) ([5aabb18](5aabb18))
* **content-gate:** institution management ui ([#4582](#4582)) ([ae88750](ae88750))
* **content-gate:** institutional access redirect and loading UX ([#4593](#4593)) ([548d236](548d236))
* **content-gate:** institutions ([#4574](#4574)) ([49b0c05](49b0c05))
* **content-gate:** personalized institutional access verification page ([#4596](#4596)) ([0eed591](0eed591))
* **image-upload:** simplify component to use basecontrol; remove info prop ([#4580](#4580)) ([d51eb54](d51eb54))
* **integrations:** add ActionScheduler group handling ([#4559](#4559)) ([411732a](411732a))
* **integrations:** promoted fields for content gate and campaign segmentation ([#4601](#4601)) ([f943df2](f943df2))
* **newspack-ui:** add stack layout and color utility classes ([#4600](#4600)) ([1934067](1934067))
* **post-date:** centralize date features from theme into plugin ([#4579](#4579)) ([19f15eb](19f15eb))
* **sync:** prevent stale data on retry, improve logging and error handling ([#4562](#4562)) ([5467f34](5467f34))
* **tags:** add private tags feature ([#4507](#4507)) ([06d7711](06d7711))
* **yoast:** add primary category utility and settings toggle ([#4563](#4563)) ([4b396c3](4b396c3))
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 2, 2026

🎉 This PR is included in version 6.37.0-alpha.1 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

matticbot pushed a commit that referenced this pull request Apr 13, 2026
# [6.37.0](v6.36.3...v6.37.0) (2026-04-13)

### Bug Fixes

* **card-settings-group:** change default actionType from chevron to none ([#4610](#4610)) ([00505ed](00505ed))
* **post-date:** preserve classic theme markup and fix archive titles ([#4602](#4602)) ([c5fb825](c5fb825))
* remove removal of block visibility ([#4595](#4595)) ([9396379](9396379))

### Features

* **access-control:** filter available lists by content restrictions ([#4589](#4589)) ([959127f](959127f)), closes [#4581](#4581) [#4583](#4583) [#4590](#4590)
* **access-control:** premium newsletters UI ([#4577](#4577)) ([6f8c891](6f8c891)), closes [#4581](#4581) [#4583](#4583) [#4590](#4590)
* **author-profile-social:** add support for colors, block spacing, brand style ([#4509](#4509)) ([21cf4c9](21cf4c9))
* campaigns wizard light UI refresh ([#4588](#4588)) ([6078c4b](6078c4b))
* **color-picker:** simplify component to use basecontrol ([#4581](#4581)) ([ff677ea](ff677ea))
* **components:** add CardFeature component ([#4583](#4583)) ([5aabb18](5aabb18))
* **content-gate:** institution management ui ([#4582](#4582)) ([ae88750](ae88750))
* **content-gate:** institutional access redirect and loading UX ([#4593](#4593)) ([548d236](548d236))
* **content-gate:** institutions ([#4574](#4574)) ([49b0c05](49b0c05))
* **content-gate:** personalized institutional access verification page ([#4596](#4596)) ([0eed591](0eed591))
* **image-upload:** simplify component to use basecontrol; remove info prop ([#4580](#4580)) ([d51eb54](d51eb54))
* **integrations:** add ActionScheduler group handling ([#4559](#4559)) ([411732a](411732a))
* **integrations:** promoted fields for content gate and campaign segmentation ([#4601](#4601)) ([f943df2](f943df2))
* **newspack-ui:** add stack layout and color utility classes ([#4600](#4600)) ([1934067](1934067))
* **post-date:** centralize date features from theme into plugin ([#4579](#4579)) ([19f15eb](19f15eb))
* **sync:** prevent stale data on retry, improve logging and error handling ([#4562](#4562)) ([5467f34](5467f34))
* **tags:** add private tags feature ([#4507](#4507)) ([06d7711](06d7711))
* **yoast:** add primary category utility and settings toggle ([#4563](#4563)) ([4b396c3](4b396c3))
@github-actions
Copy link
Copy Markdown

🎉 This PR is included in version 6.37.0 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

[Status] Approved The pull request has been reviewed and is ready to merge

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants