55use Pantheon \Terminus \Commands \TerminusCommand ;
66use Pantheon \Terminus \Site \SiteAwareInterface ;
77use Pantheon \Terminus \Site \SiteAwareTrait ;
8+ use Pantheon \Terminus \Exceptions \TerminusException ;
89
910/**
1011 * Class AwaitCommand.
@@ -40,13 +41,35 @@ public function workflowWait(
4041 ]
4142 ) {
4243 list ($ site , $ env ) = $ this ->getSiteEnv ($ site_env_id );
44+ if (!$ site instanceof \Pantheon \Terminus \Models \Site) {
45+ throw new TerminusException (
46+ 'Site {site} does not exist. ' ,
47+ ['site ' => $ site_env_id ]
48+ );
49+ }
50+ else {
51+ $ this ->log ()->notice ('Waiting for workflow on site {site} environment {env}. ' , [
52+ 'site ' => $ site ->getName (),
53+ 'env ' => $ site_env_id ,
54+ ]);
55+ }
56+ // print_r($site);
57+ if (!$ env ) {
58+ throw new TerminusException (
59+ 'Environment {env} does not exist for site {site}. ' ,
60+ ['env ' => $ site_env_id , 'site ' => $ site ->getName ()]
61+ );
62+ }
63+ else {
64+ $ this ->log ()->notice ('Waiting for workflow on environment {env}. ' , ['env ' => $ env ->getName ()]);
65+ }
4366 $ env_name = $ env ->getName ();
4467
4568 $ startTime = $ options ['start ' ];
4669 if (!$ startTime ) {
4770 $ startTime = time () - 60 ;
4871 }
49- if (!empty ($ options ['target_commit ' ])) {
72+ if (!empty ($ options ['commit ' ])) {
5073 $ this ->waitForCommit ($ startTime , $ site , $ env_name , $ options ['commit ' ], $ options ['max ' ]);
5174 return ;
5275 }
@@ -61,73 +84,96 @@ protected function waitForWorkflow(
6184 $ maxWaitInSeconds = 180 ,
6285 $ maxNotFoundAttempts = null
6386 ) {
87+ $ workflow = null ;
6488 if (empty ($ expectedWorkflowDescription )) {
6589 $ expectedWorkflowDescription = "Sync code on $ env_name " ;
6690 }
6791
68- $ startWaiting = time ();
69- $ firstWorkflowDescription = null ;
70- $ notFoundAttempts = 0 ;
92+ $ current_time = time ();
93+ if ($ maxWaitInSeconds > 0 ) {
94+ $ end_time = $ current_time + $ maxWaitInSeconds ;
95+ } else {
96+ $ end_time = 0 ;
97+ }
98+ $ not_found_attempts = 0 ;
7199 $ workflows = $ site ->getWorkflows ();
72100
73- while (true ) {
101+ do {
102+ $ current_time = time ();
103+ if ($ maxNotFoundAttempts && $ not_found_attempts === $ maxNotFoundAttempts ) {
104+ throw new TerminusException (
105+ "Attempted '{max}' times, giving up waiting for workflow to be found " ,
106+ ['max ' => $ maxNotFoundAttempts ]
107+ );
108+ }
109+
110+ // Check if the timeout has been reached and throw an exception if so.
111+ if ($ end_time > 0 && $ current_time >= $ end_time ) {
112+ throw new TerminusException (
113+ 'Workflow timed out after {timeout} seconds. ' ,
114+ ['timeout ' => $ maxWaitInSeconds ]
115+ );
116+ }
74117 $ site = $ this ->getSiteById ($ site ->id );
75- // Refresh env on each interation.
76- $ index = 0 ;
77118 $ workflows ->reset ();
119+ $ workflows ->setData ();
78120 $ workflow_items = $ workflows ->fetch (['paged ' => false ,])->all ();
79- $ found = false ;
80- foreach ($ workflow_items as $ workflow ) {
81- $ workflowCreationTime = $ workflow ->get ('created_at ' );
82-
83- $ workflowDescription = str_replace ('" ' , '' , $ workflow ->get ('description ' ));
84- if ($ index === 0 ) {
85- $ firstWorkflowDescription = $ workflowDescription ;
86- }
87- $ index ++;
88-
89- if ($ workflowCreationTime < $ startTime ) {
121+ foreach ($ workflow_items as $ current_workflow ) {
122+ $ workflow_created = $ current_workflow ->get ('created_at ' );
123+ if ($ workflow_created < $ startTime ) {
90124 // We already passed the start time.
91125 break ;
92126 }
93-
94- if (($ expectedWorkflowDescription === $ workflowDescription )) {
95- $ workflow ->fetch ();
127+ $ workflow_description = str_replace ( ' " ' , '' , $ current_workflow -> get ( ' description ' ));
128+ if (($ expectedWorkflowDescription === $ workflow_description )) {
129+ $ current_workflow ->fetch ();
96130 $ this ->log ()->notice (
97131 "Workflow '{current}' {status}. " ,
98- ['current ' => $ workflowDescription , 'status ' => $ workflow ->getStatus ()]
99- );
100- $ found = true ;
101- if ($ workflow ->isSuccessful ()) {
102- $ this ->log ()->notice ("Workflow succeeded " );
103- return ;
104- }
105- }
106- }
107- if (!$ found ) {
108- $ notFoundAttempts ++;
109- $ this ->log ()->notice (
110- "Current workflow is '{current}'; waiting for '{expected}' " ,
111- ['current ' => $ firstWorkflowDescription , 'expected ' => $ expectedWorkflowDescription ]
112- );
113- if ($ maxNotFoundAttempts && $ notFoundAttempts === $ maxNotFoundAttempts ) {
114- $ this ->log ()->warning (
115- "Attempted '{max}' times, giving up waiting for workflow to be found " ,
116- ['max ' => $ maxNotFoundAttempts ]
132+ ['current ' => $ workflow_description , 'status ' => $ current_workflow ->getStatus ()]
117133 );
134+ $ workflow = $ current_workflow ;
118135 break ;
119136 }
120137 }
121- // Wait a bit, then spin some more
138+ if ($ workflow ) {
139+ $ this ->log ()->debug ("Workflow found: {workflow} " , ['workflow ' => $ workflow_description ]);
140+ break ;
141+ }
142+
143+ $ not_found_attempts ++;
122144 sleep (5 );
123- if (time () - $ startWaiting >= $ maxWaitInSeconds ) {
124- $ this ->log ()->warning (
125- "Waited '{max}' seconds, giving up waiting for workflow to finish " ,
126- ['max ' => $ maxWaitInSeconds ]
145+ } while (empty ($ workflow ));
146+
147+ // If we get here, we have a workflow that is not finished.
148+ // We need to wait for it to finish.
149+ // At this point, we may have already spent some time waiting for the workflow to be found,
150+ // let's be forgiving and wait for the whole time again.
151+ $ retry_interval = $ this ->getConfig ()->get ('workflow_polling_delay_ms ' , 5000 );
152+ if ($ retry_interval < 1000 ) {
153+ // The API will not allow polling faster than once per second.
154+ $ retry_interval = 1000 ;
155+ }
156+ $ current_time = time ();
157+ if ($ maxWaitInSeconds > 0 ) {
158+ $ end_time = $ current_time + $ maxWaitInSeconds ;
159+ } else {
160+ $ end_time = 0 ;
161+ }
162+ do {
163+ if ($ end_time > 0 && $ current_time >= $ end_time ) {
164+ throw new TerminusException (
165+ 'Workflow timed out after {timeout} seconds. ' ,
166+ ['timeout ' => $ maxWaitInSeconds ]
127167 );
128- break ;
129168 }
169+ $ workflow ->fetch ();
170+ usleep ($ retry_interval * 1000 );
171+ $ current_time = time ();
172+ } while (!$ workflow ->isFinished ());
173+ if (!$ workflow ->isSuccessful ()) {
174+ throw new TerminusException ($ workflow ->getMessage ());
130175 }
176+ $ this ->log ()->notice ("Workflow succeeded " );
131177 }
132178
133179 /**
@@ -144,7 +190,7 @@ public function waitForCommit(
144190 $ wfl = null ;
145191 $ wflc = $ site ->getWorkflowLogs ();
146192 if (!$ wflc instanceof WorkflowLogsCollection) {
147- throw new TerminusException ('Workflow logs could not be retrieved for site: {site} ' , ['site ' => $ site_id ,]);
193+ throw new TerminusException ('Workflow logs could not be retrieved for site: {site} ' , ['site ' => $ site -> id ,]);
148194 }
149195
150196 // Remove workflows that are not for the environment $env_name.
@@ -155,21 +201,30 @@ public function waitForCommit(
155201 'target_commit ' => $ target_commit ,
156202 ]);
157203
204+ $ current_time = time ();
205+ if ($ maxWaitInSeconds > 0 ) {
206+ $ end_time = $ current_time + $ maxWaitInSeconds ;
207+ } else {
208+ $ end_time = 0 ;
209+ }
210+
158211 // If we didn't find a workflow, then we need to wait for one to be created
159212 if (!$ wfl instanceof WorkflowLog) {
160213 // sleep to give the workflow time to be created
161214 sleep ($ this ->getConfig ()->get ('refresh_workflow_delay ' , 30 ));
162215 $ wfl = $ wflc ->fetch ()->findLatestFromOptionsArray ([
163216 'target_commit ' => $ target_commit ,
164217 ]);
165- if ($ startTime ->diff (new \DateTime ())->s > $ options ['max ' ]) {
166- throw new TerminusException ('Exceeded maximum wait time of {max} seconds. ' , ['max ' => $ options ['max ' ]]);
218+ $ current_time = time ();
219+ if ($ end_time > 0 && $ current_time >= $ end_time ) {
220+ throw new TerminusException ('Exceeded maximum wait time of {max} seconds. ' , ['max ' => $ maxWaitInSeconds ]);
167221 }
168222 }
169223
170224 while (!$ wfl ->isFinished ()) {
171- if ($ startTime ->diff (new \DateTime ())->s > $ options ['max ' ]) {
172- throw new TerminusException ('Exceeded maximum wait time of {max} seconds. ' , ['max ' => $ options ['max ' ]]);
225+ $ current_time = time ();
226+ if ($ end_time > 0 && $ current_time >= $ end_time ) {
227+ throw new TerminusException ('Exceeded maximum wait time of {max} seconds. ' , ['max ' => $ maxWaitInSeconds ]);
173228 }
174229 $ this ->log ()->notice ('Waiting for workflow {id} to complete. ' , ['id ' => $ wfl ->id ,]);
175230 sleep ($ this ->getConfig ()->get ('refresh_workflow_delay ' , 30 ));
0 commit comments