Skip to content

Commit a49792c

Browse files
committed
GCS: set content-type to XML and expire faster for maven-metadata.xml files
1 parent 6367d11 commit a49792c

File tree

1 file changed

+51
-9
lines changed
  • librarian-gradle-plugin/src/main/kotlin/com/gradleup/librarian/gradle/internal/task

1 file changed

+51
-9
lines changed

librarian-gradle-plugin/src/main/kotlin/com/gradleup/librarian/gradle/internal/task/publishToGcs.kt

Lines changed: 51 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,15 @@ import com.google.auth.oauth2.GoogleCredentials
44
import gratatouille.tasks.GInputFiles
55
import gratatouille.tasks.GLogger
66
import gratatouille.tasks.GTask
7+
import kotlinx.serialization.json.JsonObject
8+
import kotlinx.serialization.json.JsonPrimitive
79
import nmcp.transport.Content
810
import nmcp.transport.Transport
911
import nmcp.transport.publishFileByFile
10-
import nmcp.transport.toRequestBody
12+
import okhttp3.*
1113
import okhttp3.HttpUrl.Companion.toHttpUrl
12-
import okhttp3.OkHttpClient
13-
import okhttp3.Request
14+
import okhttp3.MediaType.Companion.toMediaType
15+
import okio.BufferedSink
1416
import okio.BufferedSource
1517
import java.time.Duration
1618
import kotlin.math.pow
@@ -77,6 +79,8 @@ internal class GcsTransport(
7779
}
7880

7981
/**
82+
* We use multipart upload to upload both the metadata and the contents at the same time.
83+
*
8084
* https://cloud.google.com/storage/docs/json_api/v1/objects/insert
8185
*/
8286
override fun put(path: String, body: Content) {
@@ -85,13 +89,51 @@ internal class GcsTransport(
8589

8690
val name = "${prefix}${path}"
8791
logger.info("Librarian: gcs-put $name")
92+
93+
val cacheControl = when {
94+
name.endsWith("maven-metadata.xml") -> "public, max-age=60" // This makes it easier to debug snapshots issues
95+
else -> "public, max-age=3600"
96+
}
97+
val multipartBody = MultipartBody.Builder()
98+
.setType("multipart/related".toMediaType())
99+
.addPart(object : RequestBody() {
100+
override fun contentType(): MediaType {
101+
return "application/json; charset=UTF-8".toMediaType()
102+
}
103+
104+
override fun writeTo(sink: BufferedSink) {
105+
JsonObject(
106+
mapOf(
107+
"name" to JsonPrimitive(name),
108+
"cacheControl" to JsonPrimitive(cacheControl)
109+
)
110+
).let {
111+
sink.writeUtf8(it.toString())
112+
}
113+
}
114+
})
115+
.addPart(object : RequestBody() {
116+
override fun contentType(): MediaType {
117+
return when {
118+
name.endsWith(".jar") -> "application/java-archive"
119+
name.endsWith(".pom") -> "application/xml"
120+
name.endsWith(".module") -> "application/xml"
121+
name.endsWith(".xml") -> "application/xml"
122+
else -> "application/octet-stream"
123+
}.toMediaType()
124+
}
125+
126+
override fun writeTo(sink: BufferedSink) {
127+
body.writeTo(sink)
128+
}
129+
})
130+
.build()
88131
val url = postBaseUrl
89132
.newBuilder()
90-
.addQueryParameter("name", name)
91-
.addQueryParameter("uploadType", "media")
133+
.addQueryParameter("uploadType", "multipart")
92134
.build()
93135
val request = Request.Builder()
94-
.post(body.toRequestBody())
136+
.post(multipartBody)
95137
.addHeader("Authorization", "Bearer $accessToken")
96138
.url(url)
97139
.build()
@@ -113,7 +155,7 @@ internal class GcsTransport(
113155
Thread.sleep(delay)
114156
retry++
115157
if (retry > 5) {
116-
error("Too many retries ($retry), giving up ('${response.code}'): ${response.body?.string()}")
158+
error("Too many retries ($retry), giving up ('${response.code}'): ${response.body.string()}")
117159
}
118160
}
119161

@@ -123,15 +165,15 @@ internal class GcsTransport(
123165
request.header(
124166
"content-length"
125167
)
126-
}) ('${response.code}'): ${response.body?.string()}"
168+
}) ('${response.code}'): ${response.body.string()}"
127169
)
128170
}
129171
}
130172
}
131173
continue
132174
}
133175

134-
return response.body!!.source()
176+
return response.body.source()
135177
}
136178
}
137179
}

0 commit comments

Comments
 (0)