override fun publishFiles()

in google-storage-agent/src/main/kotlin/jetbrains/buildServer/artifacts/google/publish/GoogleSignedUrlFileUploader.kt [28:100]


    override fun publishFiles(
        build: AgentRunningBuild,
        pathPrefix: String,
        filesToPublish: Map<File, String>
    ) = runBlocking {
        filesToPublish.map { (file, path) ->
            FilePublishingContext(file, path, pathPrefix)
        }.map {
            var signedUrl = getSignedUrl(build, it.blobName, it.contentType)
            var locationUrl = getLocationUrl(signedUrl, it.contentType)

            async(Dispatchers.IO) {
                with(it) {
                    exceptionsWrapper {
                        var range = 0L
                        var response: HttpResponse

                        retry(
                            build.buildLogger,
                            ExponentialBackOff(),
                            {
                                logExceptions(build.buildLogger) {
                                    if (range < 0) {
                                        range = getCurrentRange(locationUrl, file)
                                    }
                                    val fileLength = file.length()
                                    val content = FileRangeContent(contentType, file).apply {
                                        this.range = range
                                    }
                                    val putRequest =
                                        requestFactory.buildPutRequest(GenericUrl(locationUrl), content).apply {
                                            if (range > 0) {
                                                this.headers.contentRange =
                                                    "bytes ${range + 1}-${fileLength - 1}/$fileLength"
                                            }
                                        }

                                    response = putRequest.execute()
                                    // reset range for non-success cases
                                    range = -1

                                    when {
                                        response.isSuccessStatusCode -> {
                                            ArtifactDataInstance.create(filePath, fileLength)
                                        }

                                        HttpBackOffUnsuccessfulResponseHandler.BackOffRequired.ON_SERVER_ERROR.isRequired(
                                            response
                                        ) -> {
                                            // will throw regular IllegalStateException
                                            // which will allow regular retry mechanism to handle it (see also handler below)
                                            error(getHttpError(response))
                                        }

                                        else -> {
                                            throw IOException("Invalid response code ${response.statusCode}. Response body:\n" + response.parseAsString())
                                        }
                                    }
                                }
                            },
                            { err ->
                                if (err !is IllegalStateException) {
                                    // let's try to recreate signed URL
                                    signedUrl = getSignedUrl(build, it.blobName, it.contentType)
                                    locationUrl = getLocationUrl(signedUrl, it.contentType)
                                }
                            }
                        )
                    }
                }
            }
        }.map { it.await() }
    }