private async waitForDeploymentCompletion()

in src/tasks/BeanstalkDeployApplication/TaskOperations.ts [154:242]


    private async waitForDeploymentCompletion(
        applicationName: string,
        environmentName: string,
        startingEventDate: Date,
        eventPollDelay: number
    ): Promise<void> {
        // upper limit to the random amount we add to the initial event poll start delay
        // and any extensions during event polling when throttling exhausts the sdk's
        // auto-retry ability
        const randomJitterUpperLimit = 5

        const requestEnvironment: ElasticBeanstalk.DescribeEnvironmentsMessage = {
            ApplicationName: applicationName,
            EnvironmentNames: [environmentName]
        }

        const requestEvents: ElasticBeanstalk.DescribeEventsMessage = {
            ApplicationName: applicationName,
            EnvironmentName: environmentName,
            StartTime: startingEventDate
        }

        let lastPrintedEventDate = startingEventDate

        console.log(tl.loc('WaitingForDeployment'))
        console.log(tl.loc('ConfiguredEventPollDelay', eventPollDelay))

        console.log(tl.loc('EventsComing'))

        let success = true
        let environment: ElasticBeanstalk.EnvironmentDescription | undefined

        // delay the event poll by a random amount, up to 5 seconds, so that if multiple
        // deployments run in parallel they don't all start querying at the same time and
        // potentially trigger throttling from the outset
        const initialStartDelay = Math.floor(Math.random() * randomJitterUpperLimit) + 1
        await this.sleep(initialStartDelay * 1000)

        do {
            tl.debug(`...event poll sleep for ${eventPollDelay}s`)
            await this.sleep(eventPollDelay * 1000)

            // if any throttling exception escapes the sdk's default retry logic,
            // extend the user's selected poll delay by a random, sub-5 second, amount
            try {
                const responseEnvironments = await this.beanstalkClient
                    .describeEnvironments(requestEnvironment)
                    .promise()
                if (!responseEnvironments.Environments || responseEnvironments.Environments.length === 0) {
                    throw new Error(tl.loc('FailedToFindEnvironment'))
                }
                environment = responseEnvironments.Environments[0]

                requestEvents.StartTime = lastPrintedEventDate
                const responseEvent = await this.beanstalkClient.describeEvents(requestEvents).promise()

                if (responseEvent.Events && responseEvent.Events.length > 0) {
                    for (let i = responseEvent.Events.length - 1; i >= 0; i--) {
                        const event = responseEvent.Events[i]
                        if (!event.EventDate || event.EventDate <= lastPrintedEventDate) {
                            continue
                        }

                        console.log(`${event.EventDate}   ${event.Severity}   ${event.Message}`)

                        if (event.Message === 'Failed to deploy application.') {
                            success = false
                        }
                    }

                    if (responseEvent.Events[0].EventDate) {
                        lastPrintedEventDate = responseEvent.Events[0].EventDate
                    }
                }
            } catch (err) {
                // if we are still encountering throttles, increase the poll delay some more
                if (err.code === 'Throttling') {
                    eventPollDelay += Math.floor(Math.random() * randomJitterUpperLimit) + 1
                    console.log(tl.loc('EventPollWaitExtended', eventPollDelay))
                } else {
                    throw err
                }
            }
        } while (environment && (environment.Status === 'Launching' || environment.Status === 'Updating'))

        if (!success) {
            throw new Error(tl.loc('FailedToDeploy'))
        }
    }