-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathMain.kt
97 lines (86 loc) · 3.32 KB
/
Main.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
/**
* Main entrypoint for SAVE Agent
*/
package com.saveourtool.save.agent
import com.saveourtool.save.agent.utils.*
import com.saveourtool.save.agent.utils.ktorLogger
import com.saveourtool.save.core.config.LogType
import com.saveourtool.save.core.logging.describe
import com.saveourtool.save.core.logging.logType
import com.saveourtool.save.utils.*
import io.ktor.client.HttpClient
import io.ktor.client.plugins.*
import io.ktor.client.plugins.contentnegotiation.*
import io.ktor.client.plugins.logging.*
import io.ktor.serialization.kotlinx.json.*
import okio.Path.Companion.toPath
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import kotlinx.serialization.PolymorphicSerializer
import kotlinx.serialization.json.Json
import kotlinx.serialization.modules.SerializersModule
import kotlinx.serialization.modules.polymorphic
import kotlinx.serialization.modules.subclass
internal val json = Json {
serializersModule = SerializersModule {
contextual(HeartbeatResponse::class, PolymorphicSerializer(HeartbeatResponse::class))
polymorphic(HeartbeatResponse::class) {
subclass(InitResponse::class)
subclass(NewJobResponse::class)
subclass(ContinueResponse::class)
subclass(WaitResponse::class)
subclass(TerminateResponse::class)
}
}
}
fun main() {
val propertiesFile = "agent.toml".toPath()
val config: AgentConfiguration = if (fs.exists(propertiesFile)) {
parseConfig(propertiesFile)
} else {
AgentConfiguration.initializeFromEnv()
}
.updateFromEnv()
logType.set(if (config.debug) LogType.ALL else LogType.WARN)
logDebugCustom("Instantiating save-agent version ${config.info.version} with config $config")
handleSigterm()
config.parentUserName?.let { protectAuthToken(it, it) }
val httpClient = configureHttpClient(config)
runBlocking {
// Launch in a new scope, because we cancel the scope on graceful termination,
// and `BlockingCoroutine` shouldn't be cancelled.
launch {
val saveAgent = SaveAgent(config, httpClient, coroutineScope = this)
val mainJob = saveAgent.start()
mainJob.join()
}
}
logInfoCustom("Agent is shutting down")
}
@Suppress("FLOAT_IN_ACCURATE_CALCULATIONS", "MagicNumber")
private fun configureHttpClient(agentConfiguration: AgentConfiguration) = HttpClient {
install(ContentNegotiation) {
json(json = json)
}
install(HttpTimeout) {
requestTimeoutMillis = agentConfiguration.requestTimeoutMillis
}
install(HttpRequestRetry) {
retryOnException(maxRetries = agentConfiguration.retry.attempts)
retryOnServerErrors(maxRetries = agentConfiguration.retry.attempts)
exponentialDelay(base = agentConfiguration.retry.initialRetryMillis / 1000.0)
modifyRequest {
if (retryCount > 1) {
val reason = response?.status ?: cause?.describe() ?: "Unknown reason"
logDebugCustom("Retrying request: attempt #$retryCount, reason: $reason")
}
}
}
install(Logging) {
logger = ktorLogger
level = if (agentConfiguration.debug) LogLevel.ALL else LogLevel.INFO
}
if (agentConfiguration.kubernetes) {
install(KubernetesServiceAccountAuthHeaderPlugin)
}
}