Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,5 +33,8 @@ jobs:
- name: Build using Gradle
run: ./gradlew build

- name: Check formatting with ktfmt
run: ./gradlew ktfmtCheck

- name: Test using Gradle
run: ./gradlew test
8 changes: 8 additions & 0 deletions .idea/ktfmt.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 0 additions & 2 deletions .prettierrc.yaml
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
# Prettier configuration
plugins:
- prettier-plugin-java
- prettier-plugin-kotlin
overrides:
- files:
- "*.java"
- "*.kt"
options:
printWidth: 100
tabWidth: 2
Expand Down
9 changes: 5 additions & 4 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,13 @@ To install Prettier Java, you can use the following command:

```bash
npm install prettier-plugin-java --save-dev
npm install prettier-plugin-kotlin --save-dev
```

Subsequently, IntelliJ IDEA can be configurated to use Prettier for formatting Java and Kotlin files. For this, you can use the
[File Watchers](https://plugins.jetbrains.com/plugin/7177-file-watchers) plugin inside IntelliJ IDEA. After installing the plugin, you can add a new file watcher for Prettier or import the
provided `watchers.xml` file. File Watchers can be configured to run on save inside the _Tools → Actions on Save_ menu.
Subsequently, IntelliJ IDEA can be configured to use Prettier for formatting Java files. For this, you can use the [File Watchers](https://plugins.jetbrains.com/plugin/7177-file-watchers)
plugin inside IntelliJ IDEA. After installing the plugin, you can add a new file watcher for Prettier or import the provided `watchers.xml`
file. File Watchers can be configured to run on save inside the _Tools → Actions on Save_ menu.

For Kotlin formatting, we use [ktfmt](https://github.com/cortinico/ktfmt-gradle) and the Google style. Formatting is checked by the CI.

## Pull Requests

Expand Down
42 changes: 17 additions & 25 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,22 @@ plugins {

id("com.google.protobuf") version "0.9.4"
id("org.pkl-lang") version "0.29.0"
id("com.ncorti.ktfmt.gradle") version "0.24.0"

kotlin("jvm")
}

group = "ac.at.uibk.dps.cirrina"

version = rootProject.file("version.txt").readText().trim()

application {
mainClass = "at.ac.uibk.dps.cirrina.cirrina.CirrinaKt"
}
application { mainClass = "at.ac.uibk.dps.cirrina.cirrina.CirrinaKt" }

java {
toolchain {
languageVersion = JavaLanguageVersion.of(21)
}
}
ktfmt { googleStyle() }

jacoco {
toolVersion = "0.8.11"
}
java { toolchain { languageVersion = JavaLanguageVersion.of(21) } }

jacoco { toolVersion = "0.8.11" }

pkl {
project {
Expand All @@ -41,7 +37,7 @@ pkl {
sourceModules.addAll(
"src/main/resources/pkl/csm/Csml.pkl",
"src/main/resources/pkl/csm/HttpServiceImplementationDescription.pkl",
"src/main/resources/pkl/csm/ServiceImplementationDescription.pkl"
"src/main/resources/pkl/csm/ServiceImplementationDescription.pkl",
)
generateGetters.set(true)
generateJavadoc.set(true)
Expand Down Expand Up @@ -75,13 +71,13 @@ dependencies {

implementation("io.nats:jnats:2.17.3")

implementation(platform("io.opentelemetry:opentelemetry-bom:1.38.0"));
implementation("io.opentelemetry:opentelemetry-api");
implementation("io.opentelemetry:opentelemetry-sdk");
implementation("io.opentelemetry:opentelemetry-exporter-logging");
implementation("io.opentelemetry:opentelemetry-exporter-otlp");
implementation("io.opentelemetry.semconv:opentelemetry-semconv:1.25.0-alpha");
implementation("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure");
implementation(platform("io.opentelemetry:opentelemetry-bom:1.38.0"))
implementation("io.opentelemetry:opentelemetry-api")
implementation("io.opentelemetry:opentelemetry-sdk")
implementation("io.opentelemetry:opentelemetry-exporter-logging")
implementation("io.opentelemetry:opentelemetry-exporter-otlp")
implementation("io.opentelemetry.semconv:opentelemetry-semconv:1.25.0-alpha")
implementation("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure")

implementation("jakarta.annotation:jakarta.annotation-api:3.0.0")

Expand Down Expand Up @@ -116,13 +112,9 @@ repositories {
maven(url = "https://repository.cloudera.com/artifactory/cloudera-repos/")
}

tasks.compileJava {
dependsOn("pklMakePackages")
}
tasks.compileJava { dependsOn("pklMakePackages") }

tasks.distZip {
archiveFileName.set("${project.name}.zip")
}
tasks.distZip { archiveFileName.set("${project.name}.zip") }

tasks.test {
useJUnitPlatform()
Expand Down
9 changes: 3 additions & 6 deletions settings.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
pluginManagement {
plugins {
kotlin("jvm") version "2.1.20"
}
}
pluginManagement { plugins { kotlin("jvm") version "2.1.20" } }

rootProject.name = "cirrina"

include("core", "runtime")
include("core", "runtime")
59 changes: 34 additions & 25 deletions src/main/java/at/ac/uibk/dps/cirrina/cirrina/Cirrina.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import at.ac.uibk.dps.cirrina.execution.`object`.context.Context
import at.ac.uibk.dps.cirrina.execution.`object`.context.NatsContext
import at.ac.uibk.dps.cirrina.execution.`object`.event.EventHandler
import at.ac.uibk.dps.cirrina.execution.`object`.event.NatsEventHandler
import at.ac.uibk.dps.cirrina.cirrina.Runtime
import at.ac.uibk.dps.cirrina.execution.service.OptimalServiceImplementationSelector
import at.ac.uibk.dps.cirrina.execution.service.ServiceImplementationBuilder
import io.opentelemetry.api.OpenTelemetry
import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk
import org.apache.logging.log4j.Level
Expand Down Expand Up @@ -54,14 +55,15 @@ class Cirrina {
newPersistentContext().use { persistentContext ->
val openTelemetry = getOpenTelemetry()

val runtime = Runtime(
openTelemetry,
eventHandler,
persistentContext
)
val services = ServiceImplementationBuilder.from(listOf()).build()
val serviceImplementationSelector = OptimalServiceImplementationSelector(services)

val runtime =
Runtime(openTelemetry, serviceImplementationSelector, eventHandler, persistentContext)

runtime.run(
EnvironmentVariables.applicationPath.get(),
EnvironmentVariables.instantiate.get()
EnvironmentVariables.instantiate.get(),
)

logger.info("Done running")
Expand All @@ -75,31 +77,38 @@ class Cirrina {
}

// Construct a new event handler as configured.
private fun newEventHandler(): EventHandler = when (EnvironmentVariables.eventProvider.get()) {
EventProvider.NATS -> newNatsEventHandler()
else -> throw ConfigurationError.Unknown(
"Unknown event handler", EnvironmentVariables.eventProvider.get()
)
}
private fun newEventHandler(): EventHandler =
when (EnvironmentVariables.eventProvider.get()) {
EventProvider.NATS -> newNatsEventHandler()
else ->
throw ConfigurationError.Unknown(
"Unknown event handler",
EnvironmentVariables.eventProvider.get(),
)
}

// Construct a new NATS event handler as configured.
private fun newNatsEventHandler(): NatsEventHandler =
NatsEventHandler(EnvironmentVariables.natsEventUrl.get())

// Construct a new persistent context based as configured.
private fun newPersistentContext(): Context = when (EnvironmentVariables.persistentContextProvider.get()) {
PersistentContextProvider.NATS -> newNatsPersistentContext()
else -> throw ConfigurationError.Unknown(
"persistent context", EnvironmentVariables.persistentContextProvider.get()
)
}
private fun newPersistentContext(): Context =
when (EnvironmentVariables.persistentContextProvider.get()) {
PersistentContextProvider.NATS -> newNatsPersistentContext()
else ->
throw ConfigurationError.Unknown(
"persistent context",
EnvironmentVariables.persistentContextProvider.get(),
)
}

// Construct a new NATS persistent context as configured.
private fun newNatsPersistentContext(): NatsContext = NatsContext(
false,
EnvironmentVariables.natsPersistentContextUrl.get(),
EnvironmentVariables.natsPersistentContextBucket.get()
)
private fun newNatsPersistentContext(): NatsContext =
NatsContext(
false,
EnvironmentVariables.natsPersistentContextUrl.get(),
EnvironmentVariables.natsPersistentContextBucket.get(),
)

// Construct a new OpenTelemetry instance as configured.
private fun getOpenTelemetry(): OpenTelemetry =
Expand All @@ -108,4 +117,4 @@ class Cirrina {

fun main() {
Cirrina().run()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,23 @@ enum class PersistentContextProvider {

/** An environment variable, which can be converted from a string to the required type. */
data class EnvironmentVariable<T>(
val name: String, val required: Boolean = false, val default: T? = null, val mapper: (String) -> T = {
it as T
}
val name: String,
val required: Boolean = false,
val default: T? = null,
val mapper: (String) -> T = { it as T },
) {
/** Get the value of the environment variable. */
fun get(): T {
val value = System.getenv(name)
return when {
value != null -> mapper(value)
default != null -> default
required -> throw EnvironmentVariableError.Missing("Missing required environment variable: $name")
else -> throw EnvironmentVariableError.Missing("Environment variable '$name' is missing but not marked required")
required ->
throw EnvironmentVariableError.Missing("Missing required environment variable: $name")
else ->
throw EnvironmentVariableError.Missing(
"Environment variable '$name' is missing but not marked required"
)
}
}
}
Expand All @@ -34,10 +39,12 @@ object EnvironmentVariables {
val natsEventUrl = EnvironmentVariable("NATS_EVENT_URL", default = "nats://localhost:4222/")

/** The NATS persistent context server URL. */
val natsPersistentContextUrl = EnvironmentVariable("NATS_PERSISTENT_CONTEXT_URL", default = "nats://localhost:4222")
val natsPersistentContextUrl =
EnvironmentVariable("NATS_PERSISTENT_CONTEXT_URL", default = "nats://localhost:4222")

/** The NATS persistent context bucket. */
val natsPersistentContextBucket = EnvironmentVariable("NATS_PERSISTENT_CONTEXT_BUCKET", default = "persistent")
val natsPersistentContextBucket =
EnvironmentVariable("NATS_PERSISTENT_CONTEXT_BUCKET", default = "persistent")

/** The path to the CSML application. */
val applicationPath = EnvironmentVariable<String>("APPLICATION_PATH", required = true)
Expand All @@ -60,7 +67,9 @@ object EnvironmentVariables {
EventProvider.valueOf(value.uppercase())
} catch (_: IllegalArgumentException) {
throw EnvironmentVariableError.Invalid(
"EVENT_PROVIDER", value, EventProvider.entries.toString()
"EVENT_PROVIDER",
value,
EventProvider.entries.toString(),
)
}
},
Expand All @@ -76,7 +85,9 @@ object EnvironmentVariables {
PersistentContextProvider.valueOf(value.uppercase())
} catch (_: IllegalArgumentException) {
throw EnvironmentVariableError.Invalid(
"PERSISTENT_CONTEXT_PROVIDER", value, PersistentContextProvider.entries.toString()
"PERSISTENT_CONTEXT_PROVIDER",
value,
PersistentContextProvider.entries.toString(),
)
}
},
Expand All @@ -85,5 +96,3 @@ object EnvironmentVariables {
/** The port to use for the health server. */
val healthPort = EnvironmentVariable("HEALTH_PORT", default = 0xCAFE) { it.toInt() }
}


9 changes: 6 additions & 3 deletions src/main/java/at/ac/uibk/dps/cirrina/cirrina/Error.kt
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
package at.ac.uibk.dps.cirrina.cirrina

sealed class EnvironmentVariableError(message: String) : RuntimeException(message) {
class Missing(name: String) : EnvironmentVariableError("Missing required environment variable '$name'")
class Missing(name: String) :
EnvironmentVariableError("Missing required environment variable '$name'")

class Invalid(name: String, value: String, allowed: String) :
EnvironmentVariableError("Invalid value for environment variable '$name', the value is '$value', allowed values are '${allowed}'")
EnvironmentVariableError(
"Invalid value for environment variable '$name', the value is '$value', allowed values are '${allowed}'"
)
}

sealed class ConfigurationError(message: String) : RuntimeException(message) {
class Unknown(what: String, `is`: Any) : ConfigurationError("Unknown $what which is '$`is`'")
}
}
Loading