@@ -534,32 +534,47 @@ public function upgrade_membership( $data ) {
534534 }
535535
536536 $ selected_membership_details ['payment_method ' ] = $ payment_method ;
537- $ membership_process = urm_get_membership_process ( $ user ->ID );
538537
539- $ is_upgrading = ! empty ( $ membership_process ['upgrade ' ] ) && isset ( $ membership_process ['upgrade ' ][ $ data ['current_membership_id ' ] ] );
538+ $ lock_name = 'urm_upgrade_lock_ ' . (int ) $ user ->ID ;
539+ $ lock = $ this ->subscription_repository ->acquire_lock ( $ lock_name );
540540
541- if ( $ is_upgrading ) {
541+ $ membership_process = urm_get_membership_process ( $ user ->ID );
542+ $ in_progress = $ membership_process ['upgrade ' ][ $ data ['current_membership_id ' ] ] ?? array ();
543+ // A stale guard means a previous attempt died or was abandoned before completing; let it be retried.
544+ $ is_upgrading = ! empty ( $ in_progress ) && ( time () - (int ) ( $ in_progress ['started_at ' ] ?? 0 ) ) < 15 * MINUTE_IN_SECONDS ;
545+
546+ if ( false === $ lock || $ is_upgrading ) {
547+ if ( true === $ lock ) {
548+ $ this ->subscription_repository ->release_lock ( $ lock_name );
549+ }
542550 $ response ['response ' ]['status ' ] = false ;
543551 $ response ['response ' ]['message ' ] = __ ( 'Membership upgrade process already initiated. ' , 'user-registration ' );
544552
545553 return $ response ;
546554 }
547555
548- $ membership_process = urm_get_membership_process ( $ subscription ['user_id ' ] );
549- $ is_upgrading = ! empty ( $ membership_process ['upgrade ' ] ) && isset ( $ membership_process ['upgrade ' ][ $ data ['current_membership_id ' ] ] );
556+ if ( 'free ' !== $ payment_method ) {
557+ $ membership_process ['upgrade ' ][ $ data ['current_membership_id ' ] ] = array (
558+ 'from ' => $ data ['current_membership_id ' ],
559+ 'to ' => $ data ['selected_membership_id ' ],
560+ 'subscription_id ' => $ data ['current_subscription_id ' ],
561+ 'started_at ' => time (),
562+ );
550563
551- if ( $ is_upgrading ) {
552- $ response ['response ' ]['status ' ] = false ;
553- $ response ['response ' ]['message ' ] = __ ( 'Membership upgrade process already initiated. ' , 'user-registration ' );
564+ update_user_meta ( $ user ->ID , 'urm_membership_process ' , $ membership_process );
565+ }
554566
555- return $ response ;
567+ if ( true === $ lock ) {
568+ $ this ->subscription_repository ->release_lock ( $ lock_name );
556569 }
557570
558571 $ current_membership_details ['ID ' ] = $ data ['current_membership_id ' ];
559572 $ selected_membership_details ['ID ' ] = $ data ['selected_membership_id ' ];
560573 $ upgrade_details = $ this ->calculate_membership_upgrade_cost ( $ current_membership_details , $ selected_membership_details , $ subscription );
561574
562575 if ( isset ( $ upgrade_details ['status ' ] ) && ! $ upgrade_details ['status ' ] ) {
576+ $ this ->release_upgrade_guard ( $ user ->ID , $ data ['current_membership_id ' ] );
577+
563578 return array (
564579 'response ' => $ upgrade_details ,
565580 );
@@ -622,6 +637,8 @@ public function upgrade_membership( $data ) {
622637 if ( ! $ cancel_subscription ['status ' ] ) {
623638 $ response ['status ' ] = false ;
624639
640+ $ this ->release_upgrade_guard ( $ user ->ID , $ data ['current_membership_id ' ] );
641+
625642 return $ response ;
626643 } else {
627644 $ this ->subscription_repository ->cancel_subscription_by_id ( $ current_subscription_id , false );
@@ -639,19 +656,6 @@ public function upgrade_membership( $data ) {
639656 $ ur_authorize_net_data = isset ( $ data ['ur_authorize_net ' ] ) ? $ data ['ur_authorize_net ' ] : array ();
640657 $ coupon = isset ( $ data ['coupon ' ] ) ? $ data ['coupon ' ] : '' ;
641658
642- if ( 'free ' !== $ payment_method ) {
643- $ membership_process = urm_get_membership_process ( $ user ->ID );
644- if ( ! isset ( $ membership_process ['upgrade ' ][ $ data ['current_membership_id ' ] ] ) ) {
645- $ membership_process ['upgrade ' ][ $ data ['current_membership_id ' ] ] = array (
646- 'from ' => $ data ['current_membership_id ' ],
647- 'to ' => $ data ['selected_membership_id ' ],
648- 'subscription_id ' => $ data ['current_subscription_id ' ],
649- );
650-
651- update_user_meta ( $ user ->ID , 'urm_membership_process ' , $ membership_process );
652- }
653- }
654-
655659 $ data = array (
656660 'membership ' => $ data ['selected_membership_id ' ],
657661 'subscription_id ' => $ subscription ['ID ' ],
@@ -682,12 +686,7 @@ public function upgrade_membership( $data ) {
682686 $ response ['status ' ] = true ;
683687
684688 } else {
685- $ membership_process = urm_get_membership_process ( $ user ->ID );
686- if ( ! empty ( $ membership_process ['upgrade ' ][ $ data ['current_membership_id ' ] ] ) ) {
687- unset( $ membership_process ['upgrade ' ][ $ data ['current_membership_id ' ] ] );
688- update_user_meta ( $ user ->ID , 'urm_membership_process ' , $ membership_process );
689- }
690-
689+ $ this ->release_upgrade_guard ( $ user ->ID , $ data ['current_membership_id ' ] );
691690 $ this ->orders_repository ->delete ( $ order ['ID ' ] );
692691 }
693692
@@ -703,6 +702,14 @@ public function upgrade_membership( $data ) {
703702 );
704703 }
705704
705+ private function release_upgrade_guard ( $ member_id , $ current_membership_id ) {
706+ $ membership_process = urm_get_membership_process ( $ member_id );
707+ if ( ! empty ( $ membership_process ['upgrade ' ][ $ current_membership_id ] ) ) {
708+ unset( $ membership_process ['upgrade ' ][ $ current_membership_id ] );
709+ update_user_meta ( $ member_id , 'urm_membership_process ' , $ membership_process );
710+ }
711+ }
712+
706713 /**
707714 * Calculate upgrade cost and details between memberships.
708715 *
0 commit comments