Skip to content

Commit 2c19daa

Browse files
committed
Adjust memory and cpu for quotes-backend
1 parent ef3bde8 commit 2c19daa

2 files changed

Lines changed: 38 additions & 57 deletions

File tree

quotes-backend/.nais/app.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ spec:
4646
limits:
4747
memory: "256Mi"
4848
requests:
49-
cpu: "10m"
49+
cpu: "100m"
5050
memory: "128Mi"
5151
accessPolicy:
5252
inbound:

quotes-backend/src/main/kotlin/io/nais/quotesbackend/Application.kt

Lines changed: 37 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -8,78 +8,62 @@ import io.ktor.server.netty.Netty
88
import io.ktor.server.plugins.BadRequestException
99
import io.ktor.server.plugins.contentnegotiation.*
1010
import io.ktor.server.plugins.openapi.*
11-
import io.ktor.server.plugins.statuspages.* // Added import for StatusPages
11+
import io.ktor.server.plugins.statuspages.*
1212
import io.ktor.server.plugins.swagger.*
1313
import io.ktor.server.request.*
1414
import io.ktor.server.response.*
1515
import io.ktor.server.routing.*
1616
import java.util.concurrent.ConcurrentHashMap
1717
import kotlin.random.Random
1818
import kotlinx.serialization.Serializable
19-
import kotlinx.serialization.SerializationException // Added import for SerializationException
19+
import kotlinx.serialization.SerializationException
2020
import kotlinx.serialization.json.Json
2121

22-
// Define globalErrorRate at the top level
23-
var globalErrorRate: Double = 0.1 // Default value, can be overridden in tests
22+
var globalErrorRate: Double = 0.1
2423

2524
@Serializable data class Quote(val id: String? = null, val text: String, val author: String)
2625

2726
fun main() {
28-
// You might want to set globalErrorRate from command-line args here if needed for
29-
// standalone runs
30-
// For example, by parsing args or environment variables.
31-
// This example focuses on test override, so we leave it as is for main.
3227
embeddedServer(Netty, port = 8080, module = Application::module).start(wait = true)
3328
}
3429

3530
fun Application.module() {
3631
log.info("Using global error rate: $globalErrorRate")
3732

38-
// Conditionally install StatusPages to prevent DuplicatePluginException
39-
if (pluginOrNull(StatusPages) == null) {
40-
install(StatusPages) {
41-
exception<BadRequestException> { call, cause ->
42-
call.application.log.warn("Bad request for ${call.request.path()}: ${cause.message}")
43-
call.respond(
44-
HttpStatusCode.BadRequest,
45-
mapOf(
46-
"error" to "BAD_REQUEST",
47-
"message" to (cause.message ?: "Invalid or missing request body.")
48-
)
49-
)
50-
}
51-
exception<SerializationException> { call, cause ->
52-
call.application.log.warn(
53-
"Request deserialization failed for ${call.request.path()}: ${cause.message}"
54-
)
55-
call.respond(
56-
HttpStatusCode.BadRequest,
57-
mapOf(
58-
"error" to "DESERIALIZATION_ERROR",
59-
"message" to (cause.message ?: "Invalid request format or missing fields.")
60-
)
61-
)
62-
}
33+
install(StatusPages) {
34+
exception<BadRequestException> { call, cause ->
35+
call.application.log.warn("Bad request for ${call.request.path()}: ${cause.message}")
36+
call.respond(
37+
HttpStatusCode.BadRequest,
38+
mapOf(
39+
"error" to "BAD_REQUEST",
40+
"message" to (cause.message ?: "Invalid or missing request body.")
41+
)
42+
)
6343
}
64-
} else {
65-
// Optional: Log or handle the case where StatusPages is already installed,
66-
// potentially by the test harness. We might need to ensure our specific
67-
// handlers are added/merged if the test harness installs a default one.
68-
log.debug("StatusPages plugin already installed. Skipping re-installation by module.")
69-
}
70-
71-
// Conditionally install ContentNegotiation to prevent DuplicatePluginException
72-
if (pluginOrNull(ContentNegotiation) == null) {
73-
install(ContentNegotiation) {
74-
json(
75-
Json {
76-
prettyPrint = true
77-
isLenient = true
78-
}
44+
exception<SerializationException> { call, cause ->
45+
call.application.log.warn(
46+
"Request deserialization failed for ${call.request.path()}: ${cause.message}"
47+
)
48+
call.respond(
49+
HttpStatusCode.BadRequest,
50+
mapOf(
51+
"error" to "DESERIALIZATION_ERROR",
52+
"message" to (cause.message ?: "Invalid request format or missing fields.")
53+
)
7954
)
8055
}
8156
}
8257

58+
install(ContentNegotiation) {
59+
json(
60+
Json {
61+
prettyPrint = true
62+
isLenient = true
63+
}
64+
)
65+
}
66+
8367
val quotes =
8468
ConcurrentHashMap<String, Quote>().apply {
8569
put(
@@ -127,7 +111,7 @@ fun Application.module() {
127111
routing {
128112
route("/api/quotes") {
129113
get {
130-
if (Random.nextDouble() < globalErrorRate) { // Use globalErrorRate
114+
if (Random.nextDouble() < globalErrorRate) {
131115
call.respond(
132116
HttpStatusCode.InternalServerError,
133117
"Simulated error for observability testing"
@@ -138,7 +122,7 @@ fun Application.module() {
138122
}
139123

140124
post {
141-
if (Random.nextDouble() < globalErrorRate) { // Use globalErrorRate
125+
if (Random.nextDouble() < globalErrorRate) {
142126
call.respond(
143127
HttpStatusCode.InternalServerError,
144128
"Simulated error for observability testing"
@@ -172,14 +156,13 @@ fun Application.module() {
172156
}
173157
quotes[newId] = newQuote
174158

175-
// Log the quote that will actually be sent in the response
176159
application.log.info("Responding with: $newQuote")
177160
call.respond(HttpStatusCode.Created, newQuote)
178161
}
179162
}
180163

181164
get("/api/quotes/{id}") {
182-
if (Random.nextDouble() < globalErrorRate) { // Use globalErrorRate
165+
if (Random.nextDouble() < globalErrorRate) {
183166
call.respond(
184167
HttpStatusCode.InternalServerError,
185168
"Simulated error for observability testing"
@@ -188,24 +171,22 @@ fun Application.module() {
188171
}
189172
val id =
190173
call.parameters["id"]
191-
?: return@get call.respond( // Changed to respond with JSON
174+
?: return@get call.respond(
192175
HttpStatusCode.BadRequest,
193176
mapOf("error" to "MISSING_ID", "message" to "Missing ID")
194177
)
195178
val quote =
196179
quotes[id]
197-
?: return@get call.respond( // Changed to respond with JSON
180+
?: return@get call.respond(
198181
HttpStatusCode.NotFound,
199182
mapOf("error" to "NOT_FOUND", "message" to "Quote not found")
200183
)
201184
call.respond(quote)
202185
}
203186

204-
// Add OpenAPI and Swagger support
205187
openAPI(path = "openapi")
206188
swaggerUI(path = "swagger")
207189

208-
// Liveness and Readiness endpoint
209190
route("/internal") {
210191
get("/health") { call.respond(HttpStatusCode.OK, "Application is healthy") }
211192
}

0 commit comments

Comments
 (0)