Skip to content

Commit 17b05ed

Browse files
authored
Add project config
1 parent 5125a75 commit 17b05ed

File tree

11 files changed

+296
-268
lines changed

11 files changed

+296
-268
lines changed

.github/scripts/test.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#!/usr/bin/bash
1+
#!/bin/bash
22

33
set -eu
44
set -o pipefail

.github/workflows/develop.yml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ jobs:
2525
java-version: 17
2626

2727
- name: Build
28-
run: ./gradlew build
28+
run: ./gradlew build installDist
2929

3030
- name: Start nginx
3131
uses: nyurik/[email protected]
@@ -54,10 +54,13 @@ jobs:
5454
}
5555
}
5656
57+
- name: Create test config
58+
run: echo "socket.address=$RUNNER_TEMP/kss.sock" >> kss.properties
59+
5760
- name: Run tests on nginx
5861
uses: BerniWittmann/[email protected]
5962
with:
60-
start: ./gradlew scripting-host:run --args="$RUNNER_TEMP/kss.sock"
63+
start: ./scripting-host/build/install/scripting-host/bin/scripting-host
6164
wait-on: sleep 5
6265
command: ./.github/scripts/test.sh "${{ steps.start_ngingx.outputs.html-dir }}"
6366

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,6 @@ bin/
3131

3232
### Mac OS ###
3333
.DS_Store
34+
35+
### Project ###
36+
/kss.properties

scripting-host/build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,5 +26,5 @@ kotlin {
2626
}
2727

2828
application {
29-
mainClass.set("net.edwardday.serverscript.scripthost.ScriptingHostKt")
29+
mainClass.set("net.edwardday.serverscript.scripthost.MainKt")
3030
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package net.edwardday.serverscript.scripthost
2+
3+
import java.io.File
4+
import java.io.IOException
5+
import java.io.InputStream
6+
import java.util.*
7+
8+
private const val CONFIG_FILE_NAME = "kss.properties"
9+
10+
suspend fun main() {
11+
// load default config
12+
val defaultConfig = try {
13+
Thread.currentThread()
14+
.getContextClassLoader()
15+
.getResourceAsStream(CONFIG_FILE_NAME)
16+
?.use<InputStream?, Properties> { stream ->
17+
Properties().apply {
18+
load(stream)
19+
}
20+
}
21+
?: error("Could not load default configuration")
22+
} catch (e: IOException) {
23+
error("Could not read default configuration because of ${e.localizedMessage}")
24+
}
25+
26+
// load config file from working directory
27+
val workingDirectoryConfig = Properties(defaultConfig)
28+
try {
29+
File(CONFIG_FILE_NAME).takeIf(File::exists)?.bufferedReader()?.use(workingDirectoryConfig::load)
30+
} catch (e: IOException) {
31+
// Ignore for now, maybe log?
32+
}
33+
34+
// load config from system properties
35+
val commandLineConfig = Properties(workingDirectoryConfig)
36+
workingDirectoryConfig.keys.forEach { key ->
37+
val keyAsString = key.toString()
38+
System.getProperty(keyAsString)?.also { value -> commandLineConfig[keyAsString] = value }
39+
}
40+
41+
val socket = commandLineConfig.getProperty("socket.address") ?: "unix:/var/run/kss/kss.sock"
42+
val maxConnections = commandLineConfig.getProperty("connections.max")?.toIntOrNull() ?: 4
43+
44+
readFromSocket(
45+
socket = socket,
46+
maxConnections = maxConnections,
47+
)
48+
}

scripting-host/src/main/kotlin/ScriptingHost.kt

Lines changed: 16 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -26,31 +26,15 @@ import java.nio.file.Files
2626
import java.nio.file.attribute.PosixFilePermission
2727
import kotlin.io.path.absolutePathString
2828
import kotlin.io.path.setPosixFilePermissions
29-
import kotlin.system.exitProcess
30-
31-
private const val DEFAULT_MAX_CONNECTIONS = 4
3229

3330
private val logger = KotlinLogging.logger {}
3431

35-
suspend fun main(vararg args: String) {
36-
if (args.size !in 1..2) {
37-
logger.error { "usage: <app> <fast cgi socket> [max connections=$DEFAULT_MAX_CONNECTIONS]" }
38-
exitProcess(status = 1)
39-
} else {
40-
val input = args[0]
41-
try {
42-
readFromSocket(input, args.getOrNull(1)?.toInt() ?: DEFAULT_MAX_CONNECTIONS)
43-
} finally {
44-
logger.info { "stop kss process" }
45-
}
46-
}
47-
}
48-
4932
suspend fun readFromSocket(socket: String, maxConnections: Int) {
5033
logger.info { "start kss process" }
5134
logger.debug { "reading from $socket with $maxConnections max connections" }
5235
val socketAddress = UnixDomainSocketAddress.of(socket)
5336
runInterruptible { Files.deleteIfExists(socketAddress.path) }
37+
val socketPath = socketAddress.path.absolutePathString()
5438

5539
val globalState = GlobalState(maxConnections)
5640
try {
@@ -64,7 +48,12 @@ suspend fun readFromSocket(socket: String, maxConnections: Int) {
6448
PosixFilePermission.GROUP_READ, PosixFilePermission.GROUP_WRITE,
6549
),
6650
)
67-
listenToConnections(maxConnections, serverChannel, socketAddress, globalState)
51+
listenToConnections(
52+
maxConnections = maxConnections,
53+
serverChannel = serverChannel,
54+
socketDescription = socketPath,
55+
globalState = globalState,
56+
)
6857
}
6958
} finally {
7059
runInterruptible {
@@ -76,17 +65,17 @@ suspend fun readFromSocket(socket: String, maxConnections: Int) {
7665
private suspend fun listenToConnections(
7766
maxConnections: Int,
7867
serverChannel: ServerSocketChannel,
79-
socketAddress: UnixDomainSocketAddress,
68+
socketDescription: String,
8069
globalState: GlobalState,
8170
) {
8271
coroutineScope {
8372
List(maxConnections) { index ->
8473
withLoggingContext("Connection Index" to index.toString()) {
8574
launch(MDCContext()) {
8675
handleRequests(
87-
serverChannel,
88-
socketAddress,
89-
globalState.connectionStates[index]
76+
serverChannel = serverChannel,
77+
socketDescription = socketDescription,
78+
connectionState = globalState.connectionStates[index]
9079
)
9180
}
9281
}
@@ -96,21 +85,23 @@ private suspend fun listenToConnections(
9685

9786
private suspend fun handleRequests(
9887
serverChannel: ServerSocketChannel,
99-
socketAddress: UnixDomainSocketAddress,
88+
socketDescription: String,
10089
connectionState: GlobalState.ConnectionState,
10190
): Nothing {
10291
while (true) {
92+
logger.debug { "listen for connection" }
10393
val socketChannel = try {
10494
runInterruptible(Dispatchers.IO, block = serverChannel::accept)
10595
} catch (e: Exception) {
106-
throw IllegalStateException("cannot accept socket of ${socketAddress.path.absolutePathString()}", e)
96+
throw IllegalStateException("cannot accept socket of $socketDescription", e)
10797
}
10898
logger.debug { "open connection" }
10999
val source = socketChannel.source().buffer()
110100
val sink = socketChannel.sink().buffer()
111101
while (true) {
112102
try {
113-
val message = runInterruptible { FCGIRequestMessage.read(source) }
103+
logger.trace { "read message" }
104+
val message = runInterruptible(Dispatchers.IO) { FCGIRequestMessage.read(source) }
114105
val result = connectionState.handleMessage(message)
115106
val close = result.fold(false) { close, responseMessage ->
116107
when (responseMessage) {
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
connections.max=4
2+
socket.address=/var/run/kss/kss.sock
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package net.edwardday.serverscript.scripthost
2+
3+
import kotlinx.coroutines.test.runTest
4+
import kotlin.test.Test
5+
import kotlin.test.assertEquals
6+
7+
class ServerScriptingHostCacheTest {
8+
9+
@Test
10+
fun testCacheWithUds() = runTest {
11+
val (url, response) = readResource("cache_data")
12+
13+
val urls = List(5) { url }
14+
val actualResponses = executeWithUds {
15+
executeScripts(it, urls)
16+
}
17+
18+
repeat(5) { index ->
19+
val counter = index + 1
20+
val expected = response.map { it.replace("{counter}", "$counter") }
21+
22+
val actual = actualResponses[index]
23+
24+
assertEquals(expected, actual)
25+
}
26+
}
27+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package net.edwardday.serverscript.scripthost
2+
3+
import kotlinx.coroutines.test.runTest
4+
import org.junit.runner.RunWith
5+
import org.junit.runners.Parameterized
6+
import kotlin.test.Test
7+
import kotlin.test.assertEquals
8+
9+
@RunWith(Parameterized::class)
10+
class ServerScriptingHostScriptsTest(private val testCaseName: String) {
11+
12+
@Test
13+
fun testScript() = runTest {
14+
val (url, expected) = readResource(testCaseName)
15+
16+
val actual = executeWithUds { executeScript(it, url) }
17+
18+
assertEquals(expected, actual)
19+
}
20+
21+
22+
companion object {
23+
24+
@JvmStatic
25+
@Parameterized.Parameters(name = "script:{0}")
26+
fun data() = listOf(
27+
"simple_script", "custom_headers", "known_status", "unknown_status",
28+
"big_output", "dependency", "multiple_output",
29+
)
30+
}
31+
}

0 commit comments

Comments
 (0)