From 803b8c9876aac639d6c2dd0affd4b4b5c96e8c24 Mon Sep 17 00:00:00 2001 From: hsiegeln <37154749+hsiegeln@users.noreply.github.com> Date: Sat, 4 Apr 2026 17:29:06 +0200 Subject: [PATCH] feat: add Phase 3 dependencies and configuration Add docker-java and ClickHouse JDBC dependencies, RuntimeConfig and ClickHouseConfig Spring components, AsyncConfig with deployment thread pool, and runtime/clickhouse config sections in application.yml. Co-Authored-By: Claude Sonnet 4.6 --- pom.xml | 20 ++++++ .../cameleer/saas/config/AsyncConfig.java | 31 +++++++++ .../cameleer/saas/log/ClickHouseConfig.java | 22 +++++++ .../cameleer/saas/runtime/RuntimeConfig.java | 63 +++++++++++++++++++ src/main/resources/application.yml | 14 +++++ 5 files changed, 150 insertions(+) create mode 100644 src/main/java/net/siegeln/cameleer/saas/config/AsyncConfig.java create mode 100644 src/main/java/net/siegeln/cameleer/saas/log/ClickHouseConfig.java create mode 100644 src/main/java/net/siegeln/cameleer/saas/runtime/RuntimeConfig.java diff --git a/pom.xml b/pom.xml index 636812f..fd114c1 100644 --- a/pom.xml +++ b/pom.xml @@ -80,6 +80,26 @@ spring-boot-starter-actuator + + + com.github.docker-java + docker-java-core + 3.4.1 + + + com.github.docker-java + docker-java-transport-httpclient5 + 3.4.1 + + + + + com.clickhouse + clickhouse-jdbc + 0.7.1 + all + + org.springframework.boot diff --git a/src/main/java/net/siegeln/cameleer/saas/config/AsyncConfig.java b/src/main/java/net/siegeln/cameleer/saas/config/AsyncConfig.java new file mode 100644 index 0000000..4d95aee --- /dev/null +++ b/src/main/java/net/siegeln/cameleer/saas/config/AsyncConfig.java @@ -0,0 +1,31 @@ +package net.siegeln.cameleer.saas.config; + +import net.siegeln.cameleer.saas.runtime.RuntimeConfig; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.EnableAsync; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; + +import java.util.concurrent.Executor; + +@Configuration +@EnableAsync +public class AsyncConfig { + + private final RuntimeConfig runtimeConfig; + + public AsyncConfig(RuntimeConfig runtimeConfig) { + this.runtimeConfig = runtimeConfig; + } + + @Bean(name = "deploymentExecutor") + public Executor deploymentExecutor() { + var executor = new ThreadPoolTaskExecutor(); + executor.setCorePoolSize(runtimeConfig.getDeploymentThreadPoolSize()); + executor.setMaxPoolSize(runtimeConfig.getDeploymentThreadPoolSize()); + executor.setQueueCapacity(25); + executor.setThreadNamePrefix("deploy-"); + executor.initialize(); + return executor; + } +} diff --git a/src/main/java/net/siegeln/cameleer/saas/log/ClickHouseConfig.java b/src/main/java/net/siegeln/cameleer/saas/log/ClickHouseConfig.java new file mode 100644 index 0000000..78cdaee --- /dev/null +++ b/src/main/java/net/siegeln/cameleer/saas/log/ClickHouseConfig.java @@ -0,0 +1,22 @@ +package net.siegeln.cameleer.saas.log; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import javax.sql.DataSource; +import com.clickhouse.jdbc.ClickHouseDataSource; +import java.util.Properties; + +@Configuration +public class ClickHouseConfig { + + @Value("${cameleer.clickhouse.url:jdbc:clickhouse://clickhouse:8123/cameleer}") + private String url; + + @Bean(name = "clickHouseDataSource") + public DataSource clickHouseDataSource() throws Exception { + var properties = new Properties(); + return new ClickHouseDataSource(url, properties); + } +} diff --git a/src/main/java/net/siegeln/cameleer/saas/runtime/RuntimeConfig.java b/src/main/java/net/siegeln/cameleer/saas/runtime/RuntimeConfig.java new file mode 100644 index 0000000..5dbfe0d --- /dev/null +++ b/src/main/java/net/siegeln/cameleer/saas/runtime/RuntimeConfig.java @@ -0,0 +1,63 @@ +package net.siegeln.cameleer.saas.runtime; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +@Component +public class RuntimeConfig { + + @Value("${cameleer.runtime.max-jar-size:209715200}") + private long maxJarSize; + + @Value("${cameleer.runtime.jar-storage-path:/data/jars}") + private String jarStoragePath; + + @Value("${cameleer.runtime.base-image:cameleer-runtime-base:latest}") + private String baseImage; + + @Value("${cameleer.runtime.docker-network:cameleer}") + private String dockerNetwork; + + @Value("${cameleer.runtime.agent-health-port:9464}") + private int agentHealthPort; + + @Value("${cameleer.runtime.health-check-timeout:60}") + private int healthCheckTimeout; + + @Value("${cameleer.runtime.deployment-thread-pool-size:4}") + private int deploymentThreadPoolSize; + + @Value("${cameleer.runtime.container-memory-limit:512m}") + private String containerMemoryLimit; + + @Value("${cameleer.runtime.container-cpu-shares:512}") + private int containerCpuShares; + + @Value("${cameleer.runtime.bootstrap-token:${CAMELEER_AUTH_TOKEN:}}") + private String bootstrapToken; + + @Value("${cameleer.runtime.cameleer3-server-endpoint:http://cameleer3-server:8081}") + private String cameleer3ServerEndpoint; + + public long getMaxJarSize() { return maxJarSize; } + public String getJarStoragePath() { return jarStoragePath; } + public String getBaseImage() { return baseImage; } + public String getDockerNetwork() { return dockerNetwork; } + public int getAgentHealthPort() { return agentHealthPort; } + public int getHealthCheckTimeout() { return healthCheckTimeout; } + public int getDeploymentThreadPoolSize() { return deploymentThreadPoolSize; } + public String getContainerMemoryLimit() { return containerMemoryLimit; } + public int getContainerCpuShares() { return containerCpuShares; } + public String getBootstrapToken() { return bootstrapToken; } + public String getCameleer3ServerEndpoint() { return cameleer3ServerEndpoint; } + + public long parseMemoryLimitBytes() { + var limit = containerMemoryLimit.trim().toLowerCase(); + if (limit.endsWith("g")) { + return Long.parseLong(limit.substring(0, limit.length() - 1)) * 1024 * 1024 * 1024; + } else if (limit.endsWith("m")) { + return Long.parseLong(limit.substring(0, limit.length() - 1)) * 1024 * 1024; + } + return Long.parseLong(limit); + } +} diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 8de3917..04b48fc 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -33,3 +33,17 @@ cameleer: logto-endpoint: ${LOGTO_ENDPOINT:} m2m-client-id: ${LOGTO_M2M_CLIENT_ID:} m2m-client-secret: ${LOGTO_M2M_CLIENT_SECRET:} + runtime: + max-jar-size: 209715200 + jar-storage-path: ${CAMELEER_JAR_STORAGE_PATH:/data/jars} + base-image: ${CAMELEER_RUNTIME_BASE_IMAGE:cameleer-runtime-base:latest} + docker-network: ${CAMELEER_DOCKER_NETWORK:cameleer} + agent-health-port: 9464 + health-check-timeout: 60 + deployment-thread-pool-size: 4 + container-memory-limit: ${CAMELEER_CONTAINER_MEMORY_LIMIT:512m} + container-cpu-shares: ${CAMELEER_CONTAINER_CPU_SHARES:512} + bootstrap-token: ${CAMELEER_AUTH_TOKEN:} + cameleer3-server-endpoint: ${CAMELEER3_SERVER_ENDPOINT:http://cameleer3-server:8081} + clickhouse: + url: ${CLICKHOUSE_URL:jdbc:clickhouse://clickhouse:8123/cameleer}