suspend fun createModernizationJob()

in plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/CodeModernizerSession.kt [152:310]


    suspend fun createModernizationJob(copyResult: MavenCopyCommandsResult?): CodeModernizerStartJobResult {
        if (this.isDisposed.get()) {
            return CodeModernizerStartJobResult.Cancelled
        }
        LOG.info { "Compressing local project" }
        val payload: File?
        var payloadSize = 0
        val startTime = Instant.now()
        var telemetryErrorMessage: String? = null
        var dependenciesCopied = false

        try {
            // Generate zip file
            if (!isValidCodeTransformConnection(sessionContext.project)) {
                // Creating zip can take some time, so quit early
                telemetryErrorMessage = "Credential expired before generating zip"
                return CodeModernizerStartJobResult.ZipUploadFailed(UploadFailureReason.CREDENTIALS_EXPIRED)
            }
            if (isDisposed.get()) {
                LOG.warn { "Disposed when about to create zip to upload" }
                telemetryErrorMessage = "Disposed when about to create zip"
                return CodeModernizerStartJobResult.Disposed
            }
            // for language upgrades, copyResult should always be Successful here, failure cases already handled
            val result = sessionContext.createZipWithModuleFiles(copyResult)

            if (result is ZipCreationResult.Missing1P) {
                telemetryErrorMessage = "Missing 1p dependencies"
                return CodeModernizerStartJobResult.CancelledMissingDependencies
            } else {
                dependenciesCopied = true
            }

            payload = result.payload
            payloadSize = payload.length().toInt()

            LOG.info { "Uploading zip file with size: $payloadSize bytes" }
            if (this.isDisposed.get()) {
                return CodeModernizerStartJobResult.Cancelled
            }

            if (payloadSize > MAX_ZIP_SIZE) {
                telemetryErrorMessage = "Project exceeds max upload size"
                return CodeModernizerStartJobResult.CancelledZipTooLarge
            }
        } catch (e: Exception) {
            val errorMessage = "Failed to create zip"
            LOG.error(e) { errorMessage }
            state.currentJobStatus = TransformationStatus.FAILED
            telemetryErrorMessage = errorMessage
            return when (e) {
                is CodeModernizerException -> CodeModernizerStartJobResult.ZipCreationFailed(e.message)
                else -> CodeModernizerStartJobResult.ZipCreationFailed(message("codemodernizer.notification.warn.zip_creation_failed.reasons.unknown"))
            }
        } finally {
            // Publish metric if uploadProject failed at the zipping step, since the process will return early.
            if (!telemetryErrorMessage.isNullOrEmpty()) {
                telemetry.uploadProject(payloadSize, startTime, dependenciesCopied, telemetryErrorMessage)
            }
        }

        var uploadId = ""
        try {
            // Create upload url and upload zip
            if (!isValidCodeTransformConnection(sessionContext.project)) {
                telemetryErrorMessage = "Credential expired before uploading project"
                return CodeModernizerStartJobResult.ZipUploadFailed(UploadFailureReason.CREDENTIALS_EXPIRED)
            }
            if (shouldStop.get() || this.isDisposed.get()) {
                LOG.warn { "Job was cancelled by user before upload was called" }
                telemetryErrorMessage = "Cancelled when about to upload project"
                return CodeModernizerStartJobResult.Cancelled
            }
            uploadId = payload?.let { uploadPayload(it) }.toString()
        } catch (e: AlreadyDisposedException) {
            LOG.warn { e.localizedMessage }
            telemetryErrorMessage = "Disposed when about to upload zip"
            return CodeModernizerStartJobResult.Disposed
        } catch (e: ConnectException) {
            state.putJobHistory(sessionContext, TransformationStatus.FAILED)
            state.currentJobStatus = TransformationStatus.FAILED
            telemetryErrorMessage = e.localizedMessage
            return CodeModernizerStartJobResult.ZipUploadFailed(UploadFailureReason.CONNECTION_REFUSED)
        } catch (e: SSLHandshakeException) {
            state.putJobHistory(sessionContext, TransformationStatus.FAILED)
            state.currentJobStatus = TransformationStatus.FAILED
            telemetryErrorMessage = e.localizedMessage
            return CodeModernizerStartJobResult.ZipUploadFailed(UploadFailureReason.SSL_HANDSHAKE_ERROR)
        } catch (e: HttpRequests.HttpStatusException) {
            state.putJobHistory(sessionContext, TransformationStatus.FAILED)
            state.currentJobStatus = TransformationStatus.FAILED
            telemetryErrorMessage = "Upload failed with statusCode: ${e.statusCode}"
            return if (e.statusCode == 403) {
                CodeModernizerStartJobResult.ZipUploadFailed(UploadFailureReason.PRESIGNED_URL_EXPIRED)
            } else {
                CodeModernizerStartJobResult.ZipUploadFailed(UploadFailureReason.HTTP_ERROR(e.statusCode))
            }
        } catch (e: IOException) {
            if (shouldStop.get()) {
                // Cancelling during S3 upload will cause IOException of "not enough data written",
                // so no need to show an IDE error for it
                LOG.warn { "Job was cancelled by user before start job was called" }
                telemetryErrorMessage = "Cancelled when about to upload project"
                return CodeModernizerStartJobResult.Cancelled
            } else {
                state.putJobHistory(sessionContext, TransformationStatus.FAILED)
                state.currentJobStatus = TransformationStatus.FAILED
                telemetryErrorMessage = e.localizedMessage
                return CodeModernizerStartJobResult.ZipUploadFailed(UploadFailureReason.OTHER(e.localizedMessage))
            }
        } catch (e: SsoOidcException) {
            state.putJobHistory(sessionContext, TransformationStatus.FAILED)
            state.currentJobStatus = TransformationStatus.FAILED
            telemetryErrorMessage = e.localizedMessage
            return CodeModernizerStartJobResult.ZipUploadFailed(UploadFailureReason.CREDENTIALS_EXPIRED)
        } catch (e: SdkClientException) {
            // Errors from code whisperer client will always be thrown as SdkClientException
            state.putJobHistory(sessionContext, TransformationStatus.FAILED)
            state.currentJobStatus = TransformationStatus.FAILED
            telemetryErrorMessage = e.localizedMessage
            return if (e.message.toString().contains(CONNECTION_REFUSED_ERROR)) {
                CodeModernizerStartJobResult.ZipUploadFailed(UploadFailureReason.CONNECTION_REFUSED)
            } else if (e.message.toString().contains(SSL_HANDSHAKE_ERROR)) {
                CodeModernizerStartJobResult.ZipUploadFailed(UploadFailureReason.SSL_HANDSHAKE_ERROR)
            } else {
                CodeModernizerStartJobResult.ZipUploadFailed(UploadFailureReason.OTHER(e.localizedMessage))
            }
        } catch (e: Exception) {
            state.putJobHistory(sessionContext, TransformationStatus.FAILED)
            state.currentJobStatus = TransformationStatus.FAILED
            telemetryErrorMessage = e.localizedMessage
            return CodeModernizerStartJobResult.ZipUploadFailed(UploadFailureReason.OTHER(e.localizedMessage))
        } finally {
            telemetry.uploadProject(payloadSize, startTime, true, telemetryErrorMessage)
            if (payload != null) {
                deleteUploadArtifact(payload)
            }
        }

        // Send upload completion message to chat (only if successful)
        CodeTransformMessageListener.instance.onUploadResult()

        return try {
            if (shouldStop.get() || this.isDisposed.get()) {
                LOG.warn { "Job was cancelled by user before start job was called" }
                return CodeModernizerStartJobResult.Cancelled
            }
            val startJobResponse = startJob(uploadId)
            state.putJobHistory(sessionContext, TransformationStatus.STARTED, startJobResponse.transformationJobId())
            state.currentJobStatus = TransformationStatus.STARTED
            telemetry.jobStart(startTime, JobId(startJobResponse.transformationJobId()))
            CodeModernizerStartJobResult.Started(JobId(startJobResponse.transformationJobId()))
        } catch (e: Exception) {
            state.putJobHistory(sessionContext, TransformationStatus.FAILED)
            state.currentJobStatus = TransformationStatus.FAILED
            telemetry.jobStart(startTime, null, e.localizedMessage)
            CodeModernizerStartJobResult.UnableToStartJob(e.message.toString())
        }
    }