fix: retry WooCommerce SMS when every recipient send fails#92
Conversation
WC\Base::send() wrote the `_texty_{id}` idempotency flag before
dispatching and ignored the gateway result, so a transient gateway or
network error left the order flagged "sent" forever — the SMS was
silently lost and never retried.
Capture each gateway result and roll the flag back only when every
recipient failed, so a later status re-fire retries. A partial success
keeps the flag so already-notified recipients are not messaged again.
Switch the claim to update_meta_data so exactly one `_texty_{id}` row
exists per order/notification. The `texty_after_notification` hook still
fires in its original position to preserve the before/after pairing.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
📝 WalkthroughWalkthrough
ChangesWooCommerce SMS send claim
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@includes/Notifications/WC/Base.php`:
- Around line 142-145: The claim set in Base::sendNotification should be
released when no recipients remain after filtering, because the early return
path leaves the notification marked as sent even though nothing was delivered.
Update the no-recipient branch in Base::sendNotification so it clears the
_texty_{id} meta before returning, while keeping the existing claim/save
behavior for the normal send path.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 82784f18-cbf2-4aaa-be27-cf4c54fd09b1
📒 Files selected for processing (1)
includes/Notifications/WC/Base.php
| // Claim the send up-front so concurrent status changes stay at-most-once. | ||
| // update_meta_data (not add_meta_data) keeps exactly one row per order/notification. | ||
| $this->order->update_meta_data( $meta_key, 1 ); | ||
| $this->order->save_meta_data(); |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
Release the claim on the no-recipient path.
Line 144 persists _texty_{id}, but Line 169 returns when all recipients are filtered out. That leaves the notification marked sent even though nobody received an SMS, so later matching status changes will not retry.
Proposed fix
if ( ! $recipients ) {
+ $this->order->delete_meta_data( $meta_key );
+ $this->order->save_meta_data();
+
return false;
}Also applies to: 168-170
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@includes/Notifications/WC/Base.php` around lines 142 - 145, The claim set in
Base::sendNotification should be released when no recipients remain after
filtering, because the early return path leaves the notification marked as sent
even though nothing was delivered. Update the no-recipient branch in
Base::sendNotification so it clears the _texty_{id} meta before returning, while
keeping the existing claim/save behavior for the normal send path.
Closes getdokan/texty-pro#30
Problem
WC\Base::send()wrote the_texty_{id}idempotency flag before dispatching and ignored the gateway result. A transient gateway/network error left the order flagged "sent" forever, so the customer/admin SMS was silently lost and never retried. Two secondary defects compounded it: the flag was written withadd_meta_data(append, not replace), and a failed send produced no signal.Fix
$any_sentacross the recipient loop (! is_wp_error( $result ) && false !== $result).delete_meta_data( $meta_key )and returnfalse, so the next matching status change retries.update_meta_dataso exactly one_texty_{id}row exists per order/notification.texty_after_notificationstill fires in its original position (before the rollback), so thetexty_before_notification/texty_after_notificationpairing is unchanged.The
_texty_{id}meta key is unchanged (stable contract).Acceptance criteria
_texty_{id}left unset → next matching status change retries._texty_{id}meta row per order/notification (update_meta_data).Verification
php -lclean;composer phpcsclean (0 errors) on the changed file._texty_order_customer_processingis absent (was permanently1before). Restore the token, re-fire Processing → SMS now sends.Known limitations (out of scope, per the issue)
woocommerce_order_status_changedfirings could both claim and both send. Documented in the issue as an optionalwp_cache_add()follow-up.🤖 Generated with Claude Code
Summary by CodeRabbit