From b4a2d55caee4dceb1244e0bc272454e6fe7a11c3 Mon Sep 17 00:00:00 2001 From: Samin Rahman Date: Fri, 23 Jan 2026 16:05:12 +1100 Subject: [PATCH 01/11] Added ComputePoolService and moved the identity map endpoints onto the worker pool --- src/main/java/com/uid2/operator/Main.java | 9 +- .../operator/service/ComputePoolService.java | 120 ++++++++++++++++++ .../operator/vertx/UIDOperatorVerticle.java | 29 ++++- .../operator/ExtendedUIDOperatorVerticle.java | 6 +- .../operator/UIDOperatorVerticleTest.java | 7 +- 5 files changed, 162 insertions(+), 9 deletions(-) create mode 100644 src/main/java/com/uid2/operator/service/ComputePoolService.java diff --git a/src/main/java/com/uid2/operator/Main.java b/src/main/java/com/uid2/operator/Main.java index b4e79f5c2..43441370f 100644 --- a/src/main/java/com/uid2/operator/Main.java +++ b/src/main/java/com/uid2/operator/Main.java @@ -341,8 +341,11 @@ private void run() throws Exception { this.createVertxInstancesMetric(); this.createVertxEventLoopsMetric(); + // Create shared compute pool for CPU-intensive operations + final ComputePoolService computePoolService = new ComputePoolService(vertx); + Supplier operatorVerticleSupplier = () -> { - UIDOperatorVerticle verticle = new UIDOperatorVerticle(configStore, config, this.clientSideTokenGenerate, siteProvider, clientKeyProvider, clientSideKeypairProvider, getKeyManager(), saltProvider, optOutStore, Clock.systemUTC(), _statsCollectorQueue, new SecureLinkValidatorService(this.serviceLinkProvider, this.serviceProvider), this.shutdownHandler::handleSaltRetrievalResponse, this.uidInstanceIdProvider); + UIDOperatorVerticle verticle = new UIDOperatorVerticle(configStore, config, this.clientSideTokenGenerate, siteProvider, clientKeyProvider, clientSideKeypairProvider, getKeyManager(), saltProvider, optOutStore, Clock.systemUTC(), _statsCollectorQueue, new SecureLinkValidatorService(this.serviceLinkProvider, this.serviceProvider), this.shutdownHandler::handleSaltRetrievalResponse, this.uidInstanceIdProvider, computePoolService); return verticle; }; @@ -371,6 +374,7 @@ private void run() throws Exception { }) .onFailure(t -> { LOGGER.error("Failed to bootstrap operator: " + t.getMessage(), new Exception(t)); + computePoolService.close(); vertx.close(); System.exit(1); }); @@ -499,7 +503,8 @@ private static Vertx createVertx() { VertxOptions vertxOptions = new VertxOptions() .setMetricsOptions(metricOptions) - .setBlockedThreadCheckInterval(threadBlockedCheckInterval); + .setBlockedThreadCheckInterval(threadBlockedCheckInterval) + .setWorkerPoolSize(8); return Vertx.vertx(vertxOptions); } diff --git a/src/main/java/com/uid2/operator/service/ComputePoolService.java b/src/main/java/com/uid2/operator/service/ComputePoolService.java new file mode 100644 index 000000000..e0a5c1550 --- /dev/null +++ b/src/main/java/com/uid2/operator/service/ComputePoolService.java @@ -0,0 +1,120 @@ +package com.uid2.operator.service; + +import io.micrometer.core.instrument.Gauge; +import io.micrometer.core.instrument.Metrics; +import io.micrometer.core.instrument.Timer; +import io.vertx.core.Future; +import io.vertx.core.Vertx; +import io.vertx.core.WorkerExecutor; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.time.Duration; +import java.util.concurrent.Callable; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicLong; + +public class ComputePoolService { + private static final Logger LOGGER = LoggerFactory.getLogger(ComputePoolService.class); + + private static final String POOL_NAME = "compute"; + private static final String METRIC_PREFIX = "uid2_compute_pool_"; + + private final WorkerExecutor workerExecutor; + + // Queue length: incremented on queue, decremented on completion + // since Vert.x worker executor doesn't expose queue length + private final AtomicLong queueLength = new AtomicLong(0); + + // Prometheus histogram for queue wait time (time between queued and dispatched) + private final Timer queueWaitTimer; + + // Prometheus gauge for queue length + private final Gauge queueLengthGauge; + + /** + * Creates a ComputePoolService with default pool size (available processors - 2, minimum 1). + * + * @param vertx the Vert.x instance + */ + public ComputePoolService(Vertx vertx) { + this(vertx, Math.max(1, Runtime.getRuntime().availableProcessors() - 2)); + } + + /** + * Creates a ComputePoolService with a specified pool size. + * + * @param vertx the Vert.x instance + * @param poolSize the number of worker threads in the pool + */ + public ComputePoolService(Vertx vertx, int poolSize) { + this.workerExecutor = vertx.createSharedWorkerExecutor(POOL_NAME, poolSize); + + // Histogram buckets are logarithmically distributed between 0.1ms and 500ms + this.queueWaitTimer = Timer.builder(METRIC_PREFIX + "queue_wait_seconds") + .description("Time tasks spend waiting in queue before being dispatched to a worker") + .publishPercentileHistogram() + .minimumExpectedValue(Duration.ofNanos(100_000)) // 0.1ms + .maximumExpectedValue(Duration.ofMillis(500)) // 500ms + .register(Metrics.globalRegistry); + + this.queueLengthGauge = Gauge.builder(METRIC_PREFIX + "queue_length", queueLength::get) + .description("Number of tasks queued but not yet completed") + .register(Metrics.globalRegistry); + + LOGGER.info("ComputePoolService initialized with pool size: {}", poolSize); + } + + /** + * Queues a blocking task for execution on the compute worker pool. + *

+ * Thread-safety: This method can be safely called from multiple threads concurrently. + * + * @param the result type + * @param callable the blocking task to execute + * @return a Future that completes with the task result + */ + public Future executeBlocking(Callable callable) { + final long queuedAt = System.nanoTime(); + queueLength.incrementAndGet(); + + return workerExecutor.executeBlocking(() -> { + try { + final long dispatchedAt = System.nanoTime(); + queueWaitTimer.record(dispatchedAt - queuedAt, TimeUnit.NANOSECONDS); + + return callable.call(); + } finally { + queueLength.decrementAndGet(); + } + }); + } + + /** + * Queues a blocking task that doesn't return a value. + * + * @param runnable the blocking task to execute + * @return a Future that completes when the task finishes + */ + public Future executeBlocking(Runnable runnable) { + return executeBlocking(() -> { + runnable.run(); + return null; + }); + } + + + /** + * Returns the current queue length (tasks queued but not yet completed). + */ + public long getQueueLength() { + return queueLength.get(); + } + + public void close() { + if (workerExecutor != null) { + workerExecutor.close(); + LOGGER.info("ComputePoolService closed"); + } + } +} diff --git a/src/main/java/com/uid2/operator/vertx/UIDOperatorVerticle.java b/src/main/java/com/uid2/operator/vertx/UIDOperatorVerticle.java index 7b36e8eea..c44ae5090 100644 --- a/src/main/java/com/uid2/operator/vertx/UIDOperatorVerticle.java +++ b/src/main/java/com/uid2/operator/vertx/UIDOperatorVerticle.java @@ -133,6 +133,7 @@ public class UIDOperatorVerticle extends AbstractVerticle { public static final long OPT_OUT_CHECK_CUTOFF_DATE = Instant.parse("2023-09-01T00:00:00.00Z").getEpochSecond(); private final Handler saltRetrievalResponseHandler; private final int allowClockSkewSeconds; + private final ComputePoolService computePoolService; protected Map> siteIdToInvalidOriginsAndAppNames = new HashMap<>(); protected boolean keySharingEndpointProvideAppNames; protected Instant lastInvalidOriginProcessTime = Instant.now(); @@ -164,7 +165,8 @@ public UIDOperatorVerticle(IConfigStore configStore, IStatsCollectorQueue statsCollectorQueue, SecureLinkValidatorService secureLinkValidatorService, Handler saltRetrievalResponseHandler, - UidInstanceIdProvider uidInstanceIdProvider) { + UidInstanceIdProvider uidInstanceIdProvider, + ComputePoolService computePoolService) { this.keyManager = keyManager; this.secureLinkValidatorService = secureLinkValidatorService; try { @@ -198,6 +200,7 @@ public UIDOperatorVerticle(IConfigStore configStore, this.identityV3Enabled = config.getBoolean(IdentityV3Prop, false); this.disableOptoutToken = config.getBoolean(DisableOptoutTokenProp, false); this.uidInstanceIdProvider = uidInstanceIdProvider; + this.computePoolService = computePoolService; } @Override @@ -283,9 +286,9 @@ private void setUpEncryptedRoutes(Router mainRouter, BodyHandler bodyHandler) { mainRouter.post(V2_TOKEN_VALIDATE.toString()).handler(bodyHandler).handler(auth.handleV1( rc -> encryptedPayloadHandler.handle(rc, this::handleTokenValidateV2), Role.GENERATOR)); mainRouter.post(V2_IDENTITY_BUCKETS.toString()).handler(bodyHandler).handler(auth.handleV1( - rc -> encryptedPayloadHandler.handle(rc, this::handleBucketsV2), Role.MAPPER)); + rc -> encryptedPayloadHandler.handleAsync(rc, this::handleBucketsV2Async), Role.MAPPER)); mainRouter.post(V2_IDENTITY_MAP.toString()).handler(bodyHandler).handler(auth.handleV1( - rc -> encryptedPayloadHandler.handle(rc, this::handleIdentityMapV2), Role.MAPPER)); + rc -> encryptedPayloadHandler.handleAsync(rc, this::handleIdentityMapV2Async), Role.MAPPER)); mainRouter.post(V2_KEY_LATEST.toString()).handler(bodyHandler).handler(auth.handleV1( rc -> encryptedPayloadHandler.handle(rc, this::handleKeysRequestV2), Role.ID_READER)); mainRouter.post(V2_KEY_SHARING.toString()).handler(bodyHandler).handler(auth.handleV1( @@ -304,7 +307,7 @@ private void setUpEncryptedRoutes(Router mainRouter, BodyHandler bodyHandler) { mainRouter.post(V2_TOKEN_CLIENTGENERATE.toString()).handler(bodyHandler).handler(this::handleClientSideTokenGenerate); mainRouter.post(V3_IDENTITY_MAP.toString()).handler(bodyHandler).handler(auth.handleV1( - rc -> encryptedPayloadHandler.handle(rc, this::handleIdentityMapV3), Role.MAPPER)); + rc -> encryptedPayloadHandler.handleAsync(rc, this::handleIdentityMapV3Async), Role.MAPPER)); } private void handleClientSideTokenGenerate(RoutingContext rc) { @@ -1037,6 +1040,12 @@ private Future handleLogoutAsyncV2(RoutingContext rc) { } } + private Future handleBucketsV2Async(RoutingContext rc) { + return computePoolService.executeBlocking(() -> { + handleBucketsV2(rc); + }); + } + private void handleBucketsV2(RoutingContext rc) { final JsonObject req = (JsonObject) rc.data().get("request"); final String qp = req.getString("since_timestamp"); @@ -1222,6 +1231,12 @@ private boolean validateServiceLink(RoutingContext rc) { return false; } + private Future handleIdentityMapV2Async(RoutingContext rc) { + return computePoolService.executeBlocking(() -> { + handleIdentityMapV2(rc); + }); + } + private void handleIdentityMapV2(RoutingContext rc) { try { final Integer siteId = RoutingContextUtil.getSiteId(rc); @@ -1285,6 +1300,12 @@ private InputUtil.InputVal[] getIdentityMapV2Input(RoutingContext rc) { getInputList.get(); } + private Future handleIdentityMapV3Async(RoutingContext rc) { + return computePoolService.executeBlocking(() -> { + handleIdentityMapV3(rc); + }); + } + private void handleIdentityMapV3(RoutingContext rc) { try { JsonObject jsonInput = (JsonObject) rc.data().get("request"); diff --git a/src/test/java/com/uid2/operator/ExtendedUIDOperatorVerticle.java b/src/test/java/com/uid2/operator/ExtendedUIDOperatorVerticle.java index 43e06dc6b..1efd21672 100644 --- a/src/test/java/com/uid2/operator/ExtendedUIDOperatorVerticle.java +++ b/src/test/java/com/uid2/operator/ExtendedUIDOperatorVerticle.java @@ -2,6 +2,7 @@ import com.uid2.operator.model.KeyManager; import com.uid2.operator.monitoring.IStatsCollectorQueue; +import com.uid2.operator.service.ComputePoolService; import com.uid2.operator.service.IUIDOperatorService; import com.uid2.operator.service.SecureLinkValidatorService; import com.uid2.operator.store.IConfigStore; @@ -33,8 +34,9 @@ public ExtendedUIDOperatorVerticle(IConfigStore configStore, IStatsCollectorQueue statsCollectorQueue, SecureLinkValidatorService secureLinkValidationService, Handler saltRetrievalResponseHandler, - UidInstanceIdProvider uidInstanceIdProvider) { - super(configStore, config, clientSideTokenGenerate, siteProvider, clientKeyProvider, clientSideKeypairProvider, keyManager, saltProvider, optOutStore, clock, statsCollectorQueue, secureLinkValidationService, saltRetrievalResponseHandler, uidInstanceIdProvider); + UidInstanceIdProvider uidInstanceIdProvider, + ComputePoolService computePoolService) { + super(configStore, config, clientSideTokenGenerate, siteProvider, clientKeyProvider, clientSideKeypairProvider, keyManager, saltProvider, optOutStore, clock, statsCollectorQueue, secureLinkValidationService, saltRetrievalResponseHandler, uidInstanceIdProvider, computePoolService); } public IUIDOperatorService getIdService() { diff --git a/src/test/java/com/uid2/operator/UIDOperatorVerticleTest.java b/src/test/java/com/uid2/operator/UIDOperatorVerticleTest.java index 835d76d91..aeb3015b7 100644 --- a/src/test/java/com/uid2/operator/UIDOperatorVerticleTest.java +++ b/src/test/java/com/uid2/operator/UIDOperatorVerticleTest.java @@ -142,6 +142,7 @@ public class UIDOperatorVerticleTest { private ExtendedUIDOperatorVerticle uidOperatorVerticle; private RuntimeConfig runtimeConfig; private EncryptedTokenEncoder encoder; + private ComputePoolService computePoolService; @BeforeEach void deployVerticle(Vertx vertx, VertxTestContext testContext, TestInfo testInfo) { @@ -165,7 +166,8 @@ void deployVerticle(Vertx vertx, VertxTestContext testContext, TestInfo testInfo this.uidInstanceIdProvider = new UidInstanceIdProvider("test-instance", "id"); - this.uidOperatorVerticle = new ExtendedUIDOperatorVerticle(configStore, config, config.getBoolean("client_side_token_generate"), siteProvider, clientKeyProvider, clientSideKeypairProvider, new KeyManager(keysetKeyStore, keysetProvider), saltProvider, optOutStore, clock, statsCollectorQueue, secureLinkValidatorService, shutdownHandler::handleSaltRetrievalResponse, uidInstanceIdProvider); + this.computePoolService = new ComputePoolService(vertx); + this.uidOperatorVerticle = new ExtendedUIDOperatorVerticle(configStore, config, config.getBoolean("client_side_token_generate"), siteProvider, clientKeyProvider, clientSideKeypairProvider, new KeyManager(keysetKeyStore, keysetProvider), saltProvider, optOutStore, clock, statsCollectorQueue, secureLinkValidatorService, shutdownHandler::handleSaltRetrievalResponse, uidInstanceIdProvider, this.computePoolService); vertx.deployVerticle(uidOperatorVerticle, testContext.succeeding(id -> testContext.completeNow())); this.registry = new SimpleMeterRegistry(); @@ -177,6 +179,9 @@ void deployVerticle(Vertx vertx, VertxTestContext testContext, TestInfo testInfo @AfterEach void teardown() { Metrics.globalRegistry.remove(registry); + if (computePoolService != null) { + computePoolService.close(); + } } private RuntimeConfig setupRuntimeConfig(JsonObject config) { From 827e3ee05e368e2cc5d560fb27566ec286a1766b Mon Sep 17 00:00:00 2001 From: Release Workflow Date: Fri, 23 Jan 2026 05:13:14 +0000 Subject: [PATCH 02/11] [CI Pipeline] Released Snapshot version: 5.63.31-alpha-290-SNAPSHOT --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 45d68d711..60d65f0ac 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.uid2 uid2-operator - 5.63.30 + 5.63.31-alpha-290-SNAPSHOT UTF-8 From 57f1059cbf0bcee929c4d922e8c1f47c8ee28797 Mon Sep 17 00:00:00 2001 From: Samin Rahman Date: Tue, 27 Jan 2026 14:08:01 +1100 Subject: [PATCH 03/11] Added percentiles and pool name to default micrometer metrics --- src/main/java/com/uid2/operator/Main.java | 9 +++- .../operator/service/ComputePoolService.java | 47 ++++++++++++------- 2 files changed, 38 insertions(+), 18 deletions(-) diff --git a/src/main/java/com/uid2/operator/Main.java b/src/main/java/com/uid2/operator/Main.java index 43441370f..506307321 100644 --- a/src/main/java/com/uid2/operator/Main.java +++ b/src/main/java/com/uid2/operator/Main.java @@ -492,7 +492,7 @@ private static Vertx createVertx() { MicrometerMetricsOptions metricOptions = new MicrometerMetricsOptions() .setPrometheusOptions(prometheusOptions) - .setLabels(EnumSet.of(Label.HTTP_METHOD, Label.HTTP_CODE, Label.HTTP_PATH)) + .setLabels(EnumSet.of(Label.HTTP_METHOD, Label.HTTP_CODE, Label.HTTP_PATH, Label.POOL_NAME)) .setJvmMetricsEnabled(true) .setEnabled(true); setupMetrics(metricOptions); @@ -529,6 +529,7 @@ private static void setupMetrics(MicrometerMetricsOptions metricOptions) { Objects.equals(id.getTag(Label.HTTP_CODE.toString()), "404"))) .meterFilter(new MeterFilter() { private final String httpServerResponseTime = MetricsDomain.HTTP_SERVER.getPrefix() + MetricsNaming.v4Names().getHttpResponseTime(); + private final String poolQueueTime = MetricsDomain.HTTP_SERVER.getPrefix() + MetricsNaming.v4Names().getPoolQueueTime(); @Override public DistributionStatisticConfig configure(Meter.Id id, DistributionStatisticConfig config) { @@ -538,6 +539,12 @@ public DistributionStatisticConfig configure(Meter.Id id, DistributionStatisticC .build() .merge(config); } + if (id.getName().equals(poolQueueTime)) { + return DistributionStatisticConfig.builder() + .percentiles(0.50, 0.90, 0.95, 0.99) + .build() + .merge(config); + } return config; } }) diff --git a/src/main/java/com/uid2/operator/service/ComputePoolService.java b/src/main/java/com/uid2/operator/service/ComputePoolService.java index e0a5c1550..a28efc1b0 100644 --- a/src/main/java/com/uid2/operator/service/ComputePoolService.java +++ b/src/main/java/com/uid2/operator/service/ComputePoolService.java @@ -12,6 +12,7 @@ import java.time.Duration; import java.util.concurrent.Callable; import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicLong; public class ComputePoolService { @@ -22,15 +23,15 @@ public class ComputePoolService { private final WorkerExecutor workerExecutor; - // Queue length: incremented on queue, decremented on completion - // since Vert.x worker executor doesn't expose queue length - private final AtomicLong queueLength = new AtomicLong(0); + // Queue pending: incremented on queue, decremented on dispatch + // Tracks tasks waiting in queue but not yet started + private final AtomicLong queuePending = new AtomicLong(0); // Prometheus histogram for queue wait time (time between queued and dispatched) private final Timer queueWaitTimer; - // Prometheus gauge for queue length - private final Gauge queueLengthGauge; + // Prometheus gauge for queue pending + private final Gauge queuePendingGauge; /** * Creates a ComputePoolService with default pool size (available processors - 2, minimum 1). @@ -58,8 +59,8 @@ public ComputePoolService(Vertx vertx, int poolSize) { .maximumExpectedValue(Duration.ofMillis(500)) // 500ms .register(Metrics.globalRegistry); - this.queueLengthGauge = Gauge.builder(METRIC_PREFIX + "queue_length", queueLength::get) - .description("Number of tasks queued but not yet completed") + this.queuePendingGauge = Gauge.builder(METRIC_PREFIX + "queue_pending", queuePending::get) + .description("Number of tasks waiting in queue but not yet dispatched to a worker") .register(Metrics.globalRegistry); LOGGER.info("ComputePoolService initialized with pool size: {}", poolSize); @@ -76,18 +77,30 @@ public ComputePoolService(Vertx vertx, int poolSize) { */ public Future executeBlocking(Callable callable) { final long queuedAt = System.nanoTime(); - queueLength.incrementAndGet(); + final AtomicBoolean dispatched = new AtomicBoolean(false); + + queuePending.incrementAndGet(); + + try { + return workerExecutor.executeBlocking(() -> { + dispatched.set(true); + queuePending.decrementAndGet(); - return workerExecutor.executeBlocking(() -> { - try { final long dispatchedAt = System.nanoTime(); queueWaitTimer.record(dispatchedAt - queuedAt, TimeUnit.NANOSECONDS); return callable.call(); - } finally { - queueLength.decrementAndGet(); - } - }); + }).onComplete(ar -> { + // If task was never dispatched, clean up + if (!dispatched.get()) { + queuePending.decrementAndGet(); + } + }); + } catch (Exception e) { + // executeBlocking threw before returning a Future + queuePending.decrementAndGet(); + return Future.failedFuture(e); + } } /** @@ -105,10 +118,10 @@ public Future executeBlocking(Runnable runnable) { /** - * Returns the current queue length (tasks queued but not yet completed). + * Returns the number of tasks waiting in queue but not yet dispatched to a worker. */ - public long getQueueLength() { - return queueLength.get(); + public long getQueuePending() { + return queuePending.get(); } public void close() { From b222e72b183c54c1bad231567ec7c0e20f06dac5 Mon Sep 17 00:00:00 2001 From: Release Workflow Date: Tue, 27 Jan 2026 03:16:14 +0000 Subject: [PATCH 04/11] [CI Pipeline] Released Snapshot version: 5.63.32-alpha-291-SNAPSHOT --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 60d65f0ac..718e25ac2 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.uid2 uid2-operator - 5.63.31-alpha-290-SNAPSHOT + 5.63.32-alpha-291-SNAPSHOT UTF-8 From 9c775478586a0f071ed0f622f941dfb787b8c26d Mon Sep 17 00:00:00 2001 From: Samin Rahman Date: Tue, 27 Jan 2026 14:31:09 +1100 Subject: [PATCH 05/11] Added libpng CVEs to trivyignore for testing --- .trivyignore | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.trivyignore b/.trivyignore index 55309276c..1aa30ac1d 100644 --- a/.trivyignore +++ b/.trivyignore @@ -21,4 +21,8 @@ CVE-2025-65018 exp:2026-06-05 CVE-2025-66293 exp:2026-06-15 # UID2-6481 -CVE-2025-68973 exp:2026-06-15 \ No newline at end of file +CVE-2025-68973 exp:2026-06-15 + +# Libpng for testing +CVE-2026-22695 +CVE-2026-22801 \ No newline at end of file From 3cdf3d3b5ef971192fe924047ad02ac0ad1713da Mon Sep 17 00:00:00 2001 From: Release Workflow Date: Tue, 27 Jan 2026 03:34:11 +0000 Subject: [PATCH 06/11] [CI Pipeline] Released Snapshot version: 5.63.33-alpha-292-SNAPSHOT --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 718e25ac2..fe911fc02 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.uid2 uid2-operator - 5.63.32-alpha-291-SNAPSHOT + 5.63.33-alpha-292-SNAPSHOT UTF-8 From ec11efc42535a3a35d98083d2a798190c9edf6c2 Mon Sep 17 00:00:00 2001 From: Samin Rahman Date: Tue, 27 Jan 2026 15:19:19 +1100 Subject: [PATCH 07/11] Removed ComputePoolService, added feature flags and fixed pool time metric name --- conf/default-config.json | 4 +- src/main/java/com/uid2/operator/Const.java | 3 + src/main/java/com/uid2/operator/Main.java | 14 +- .../operator/service/ComputePoolService.java | 133 ------------------ .../operator/vertx/UIDOperatorVerticle.java | 40 ++++-- .../operator/ExtendedUIDOperatorVerticle.java | 6 +- .../operator/UIDOperatorVerticleTest.java | 11 +- 7 files changed, 52 insertions(+), 159 deletions(-) delete mode 100644 src/main/java/com/uid2/operator/service/ComputePoolService.java diff --git a/conf/default-config.json b/conf/default-config.json index c5de0d87b..3b3c1c78e 100644 --- a/conf/default-config.json +++ b/conf/default-config.json @@ -40,5 +40,7 @@ "sharing_token_expiry_seconds": 2592000, "operator_type": "public", "enable_remote_config": true, - "uid_instance_id_prefix": "local-operator" + "uid_instance_id_prefix": "local-operator", + "enable_async_batch_request": true, + "compute_pool_thread_count": 12 } diff --git a/src/main/java/com/uid2/operator/Const.java b/src/main/java/com/uid2/operator/Const.java index 14f878371..406c52df2 100644 --- a/src/main/java/com/uid2/operator/Const.java +++ b/src/main/java/com/uid2/operator/Const.java @@ -39,5 +39,8 @@ public class Config extends com.uid2.shared.Const.Config { public static final String RuntimeConfigMetadataPathProp = "runtime_config_metadata_path"; public static final String IdentityEnvironmentProp = "identity_environment"; + + public static final String ComputePoolThreadCountProp = "compute_pool_thread_count"; + public static final String EnableAsyncBatchRequestProp = "enable_async_batch_request"; } } diff --git a/src/main/java/com/uid2/operator/Main.java b/src/main/java/com/uid2/operator/Main.java index 506307321..ca62ea4c6 100644 --- a/src/main/java/com/uid2/operator/Main.java +++ b/src/main/java/com/uid2/operator/Main.java @@ -342,10 +342,12 @@ private void run() throws Exception { this.createVertxEventLoopsMetric(); // Create shared compute pool for CPU-intensive operations - final ComputePoolService computePoolService = new ComputePoolService(vertx); + final int computePoolSize = config.getInteger(Const.Config.ComputePoolThreadCountProp, Math.max(1, Runtime.getRuntime().availableProcessors() - 2)); + final WorkerExecutor computeWorkerPool = vertx.createSharedWorkerExecutor("compute", computePoolSize); + LOGGER.info("Created compute worker pool with size: {}", computePoolSize); Supplier operatorVerticleSupplier = () -> { - UIDOperatorVerticle verticle = new UIDOperatorVerticle(configStore, config, this.clientSideTokenGenerate, siteProvider, clientKeyProvider, clientSideKeypairProvider, getKeyManager(), saltProvider, optOutStore, Clock.systemUTC(), _statsCollectorQueue, new SecureLinkValidatorService(this.serviceLinkProvider, this.serviceProvider), this.shutdownHandler::handleSaltRetrievalResponse, this.uidInstanceIdProvider, computePoolService); + UIDOperatorVerticle verticle = new UIDOperatorVerticle(configStore, config, this.clientSideTokenGenerate, siteProvider, clientKeyProvider, clientSideKeypairProvider, getKeyManager(), saltProvider, optOutStore, Clock.systemUTC(), _statsCollectorQueue, new SecureLinkValidatorService(this.serviceLinkProvider, this.serviceProvider), this.shutdownHandler::handleSaltRetrievalResponse, this.uidInstanceIdProvider, computeWorkerPool); return verticle; }; @@ -374,7 +376,9 @@ private void run() throws Exception { }) .onFailure(t -> { LOGGER.error("Failed to bootstrap operator: " + t.getMessage(), new Exception(t)); - computePoolService.close(); + if (computeWorkerPool != null) { + computeWorkerPool.close(); + } vertx.close(); System.exit(1); }); @@ -504,7 +508,7 @@ private static Vertx createVertx() { VertxOptions vertxOptions = new VertxOptions() .setMetricsOptions(metricOptions) .setBlockedThreadCheckInterval(threadBlockedCheckInterval) - .setWorkerPoolSize(8); + .setWorkerPoolSize(12); return Vertx.vertx(vertxOptions); } @@ -529,7 +533,7 @@ private static void setupMetrics(MicrometerMetricsOptions metricOptions) { Objects.equals(id.getTag(Label.HTTP_CODE.toString()), "404"))) .meterFilter(new MeterFilter() { private final String httpServerResponseTime = MetricsDomain.HTTP_SERVER.getPrefix() + MetricsNaming.v4Names().getHttpResponseTime(); - private final String poolQueueTime = MetricsDomain.HTTP_SERVER.getPrefix() + MetricsNaming.v4Names().getPoolQueueTime(); + private final String poolQueueTime = MetricsDomain.NAMED_POOLS.getPrefix() + MetricsNaming.v4Names().getPoolQueueTime(); @Override public DistributionStatisticConfig configure(Meter.Id id, DistributionStatisticConfig config) { diff --git a/src/main/java/com/uid2/operator/service/ComputePoolService.java b/src/main/java/com/uid2/operator/service/ComputePoolService.java deleted file mode 100644 index a28efc1b0..000000000 --- a/src/main/java/com/uid2/operator/service/ComputePoolService.java +++ /dev/null @@ -1,133 +0,0 @@ -package com.uid2.operator.service; - -import io.micrometer.core.instrument.Gauge; -import io.micrometer.core.instrument.Metrics; -import io.micrometer.core.instrument.Timer; -import io.vertx.core.Future; -import io.vertx.core.Vertx; -import io.vertx.core.WorkerExecutor; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.time.Duration; -import java.util.concurrent.Callable; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicLong; - -public class ComputePoolService { - private static final Logger LOGGER = LoggerFactory.getLogger(ComputePoolService.class); - - private static final String POOL_NAME = "compute"; - private static final String METRIC_PREFIX = "uid2_compute_pool_"; - - private final WorkerExecutor workerExecutor; - - // Queue pending: incremented on queue, decremented on dispatch - // Tracks tasks waiting in queue but not yet started - private final AtomicLong queuePending = new AtomicLong(0); - - // Prometheus histogram for queue wait time (time between queued and dispatched) - private final Timer queueWaitTimer; - - // Prometheus gauge for queue pending - private final Gauge queuePendingGauge; - - /** - * Creates a ComputePoolService with default pool size (available processors - 2, minimum 1). - * - * @param vertx the Vert.x instance - */ - public ComputePoolService(Vertx vertx) { - this(vertx, Math.max(1, Runtime.getRuntime().availableProcessors() - 2)); - } - - /** - * Creates a ComputePoolService with a specified pool size. - * - * @param vertx the Vert.x instance - * @param poolSize the number of worker threads in the pool - */ - public ComputePoolService(Vertx vertx, int poolSize) { - this.workerExecutor = vertx.createSharedWorkerExecutor(POOL_NAME, poolSize); - - // Histogram buckets are logarithmically distributed between 0.1ms and 500ms - this.queueWaitTimer = Timer.builder(METRIC_PREFIX + "queue_wait_seconds") - .description("Time tasks spend waiting in queue before being dispatched to a worker") - .publishPercentileHistogram() - .minimumExpectedValue(Duration.ofNanos(100_000)) // 0.1ms - .maximumExpectedValue(Duration.ofMillis(500)) // 500ms - .register(Metrics.globalRegistry); - - this.queuePendingGauge = Gauge.builder(METRIC_PREFIX + "queue_pending", queuePending::get) - .description("Number of tasks waiting in queue but not yet dispatched to a worker") - .register(Metrics.globalRegistry); - - LOGGER.info("ComputePoolService initialized with pool size: {}", poolSize); - } - - /** - * Queues a blocking task for execution on the compute worker pool. - *

- * Thread-safety: This method can be safely called from multiple threads concurrently. - * - * @param the result type - * @param callable the blocking task to execute - * @return a Future that completes with the task result - */ - public Future executeBlocking(Callable callable) { - final long queuedAt = System.nanoTime(); - final AtomicBoolean dispatched = new AtomicBoolean(false); - - queuePending.incrementAndGet(); - - try { - return workerExecutor.executeBlocking(() -> { - dispatched.set(true); - queuePending.decrementAndGet(); - - final long dispatchedAt = System.nanoTime(); - queueWaitTimer.record(dispatchedAt - queuedAt, TimeUnit.NANOSECONDS); - - return callable.call(); - }).onComplete(ar -> { - // If task was never dispatched, clean up - if (!dispatched.get()) { - queuePending.decrementAndGet(); - } - }); - } catch (Exception e) { - // executeBlocking threw before returning a Future - queuePending.decrementAndGet(); - return Future.failedFuture(e); - } - } - - /** - * Queues a blocking task that doesn't return a value. - * - * @param runnable the blocking task to execute - * @return a Future that completes when the task finishes - */ - public Future executeBlocking(Runnable runnable) { - return executeBlocking(() -> { - runnable.run(); - return null; - }); - } - - - /** - * Returns the number of tasks waiting in queue but not yet dispatched to a worker. - */ - public long getQueuePending() { - return queuePending.get(); - } - - public void close() { - if (workerExecutor != null) { - workerExecutor.close(); - LOGGER.info("ComputePoolService closed"); - } - } -} diff --git a/src/main/java/com/uid2/operator/vertx/UIDOperatorVerticle.java b/src/main/java/com/uid2/operator/vertx/UIDOperatorVerticle.java index c44ae5090..c89d18591 100644 --- a/src/main/java/com/uid2/operator/vertx/UIDOperatorVerticle.java +++ b/src/main/java/com/uid2/operator/vertx/UIDOperatorVerticle.java @@ -43,6 +43,7 @@ import io.vertx.core.Future; import io.vertx.core.Handler; import io.vertx.core.Promise; +import io.vertx.core.WorkerExecutor; import io.vertx.core.buffer.Buffer; import io.vertx.core.http.HttpServerOptions; import io.vertx.core.http.HttpServerResponse; @@ -133,7 +134,7 @@ public class UIDOperatorVerticle extends AbstractVerticle { public static final long OPT_OUT_CHECK_CUTOFF_DATE = Instant.parse("2023-09-01T00:00:00.00Z").getEpochSecond(); private final Handler saltRetrievalResponseHandler; private final int allowClockSkewSeconds; - private final ComputePoolService computePoolService; + private final WorkerExecutor computeWorkerPool; protected Map> siteIdToInvalidOriginsAndAppNames = new HashMap<>(); protected boolean keySharingEndpointProvideAppNames; protected Instant lastInvalidOriginProcessTime = Instant.now(); @@ -141,6 +142,8 @@ public class UIDOperatorVerticle extends AbstractVerticle { private final int optOutStatusMaxRequestSize; private final boolean optOutStatusApiEnabled; + private final boolean isAsyncBatchRequestsEnabled; + //"Android" is from https://github.com/IABTechLab/uid2-android-sdk/blob/ff93ebf597f5de7d440a84f7015a334ba4138ede/sdk/src/main/java/com/uid2/UID2Client.kt#L46 //"ios"/"tvos" is from https://github.com/IABTechLab/uid2-ios-sdk/blob/91c290d29a7093cfc209eca493d1fee80c17e16a/Sources/UID2/UID2Client.swift#L36-L38 private static final List SUPPORTED_IN_APP = Arrays.asList("Android", "ios", "tvos"); @@ -166,7 +169,7 @@ public UIDOperatorVerticle(IConfigStore configStore, SecureLinkValidatorService secureLinkValidatorService, Handler saltRetrievalResponseHandler, UidInstanceIdProvider uidInstanceIdProvider, - ComputePoolService computePoolService) { + WorkerExecutor computeWorkerPool) { this.keyManager = keyManager; this.secureLinkValidatorService = secureLinkValidatorService; try { @@ -200,7 +203,8 @@ public UIDOperatorVerticle(IConfigStore configStore, this.identityV3Enabled = config.getBoolean(IdentityV3Prop, false); this.disableOptoutToken = config.getBoolean(DisableOptoutTokenProp, false); this.uidInstanceIdProvider = uidInstanceIdProvider; - this.computePoolService = computePoolService; + this.computeWorkerPool = computeWorkerPool; + this.isAsyncBatchRequestsEnabled = config.getBoolean(EnableAsyncBatchRequestProp, false); } @Override @@ -285,10 +289,6 @@ private void setUpEncryptedRoutes(Router mainRouter, BodyHandler bodyHandler) { rc -> encryptedPayloadHandler.handleTokenRefresh(rc, this::handleTokenRefreshV2))); mainRouter.post(V2_TOKEN_VALIDATE.toString()).handler(bodyHandler).handler(auth.handleV1( rc -> encryptedPayloadHandler.handle(rc, this::handleTokenValidateV2), Role.GENERATOR)); - mainRouter.post(V2_IDENTITY_BUCKETS.toString()).handler(bodyHandler).handler(auth.handleV1( - rc -> encryptedPayloadHandler.handleAsync(rc, this::handleBucketsV2Async), Role.MAPPER)); - mainRouter.post(V2_IDENTITY_MAP.toString()).handler(bodyHandler).handler(auth.handleV1( - rc -> encryptedPayloadHandler.handleAsync(rc, this::handleIdentityMapV2Async), Role.MAPPER)); mainRouter.post(V2_KEY_LATEST.toString()).handler(bodyHandler).handler(auth.handleV1( rc -> encryptedPayloadHandler.handle(rc, this::handleKeysRequestV2), Role.ID_READER)); mainRouter.post(V2_KEY_SHARING.toString()).handler(bodyHandler).handler(auth.handleV1( @@ -306,8 +306,21 @@ private void setUpEncryptedRoutes(Router mainRouter, BodyHandler bodyHandler) { if (this.clientSideTokenGenerate) mainRouter.post(V2_TOKEN_CLIENTGENERATE.toString()).handler(bodyHandler).handler(this::handleClientSideTokenGenerate); - mainRouter.post(V3_IDENTITY_MAP.toString()).handler(bodyHandler).handler(auth.handleV1( - rc -> encryptedPayloadHandler.handleAsync(rc, this::handleIdentityMapV3Async), Role.MAPPER)); + if (isAsyncBatchRequestsEnabled) { + mainRouter.post(V2_IDENTITY_BUCKETS.toString()).handler(bodyHandler).handler(auth.handleV1( + rc -> encryptedPayloadHandler.handleAsync(rc, this::handleBucketsV2Async), Role.MAPPER)); + mainRouter.post(V2_IDENTITY_MAP.toString()).handler(bodyHandler).handler(auth.handleV1( + rc -> encryptedPayloadHandler.handleAsync(rc, this::handleIdentityMapV2Async), Role.MAPPER)); + mainRouter.post(V3_IDENTITY_MAP.toString()).handler(bodyHandler).handler(auth.handleV1( + rc -> encryptedPayloadHandler.handleAsync(rc, this::handleIdentityMapV3Async), Role.MAPPER)); + } else { + mainRouter.post(V2_IDENTITY_BUCKETS.toString()).handler(bodyHandler).handler(auth.handleV1( + rc -> encryptedPayloadHandler.handle(rc, this::handleBucketsV2), Role.MAPPER)); + mainRouter.post(V2_IDENTITY_MAP.toString()).handler(bodyHandler).handler(auth.handleV1( + rc -> encryptedPayloadHandler.handle(rc, this::handleIdentityMapV2), Role.MAPPER)); + mainRouter.post(V3_IDENTITY_MAP.toString()).handler(bodyHandler).handler(auth.handleV1( + rc -> encryptedPayloadHandler.handle(rc, this::handleIdentityMapV3), Role.MAPPER)); + } } private void handleClientSideTokenGenerate(RoutingContext rc) { @@ -1041,8 +1054,9 @@ private Future handleLogoutAsyncV2(RoutingContext rc) { } private Future handleBucketsV2Async(RoutingContext rc) { - return computePoolService.executeBlocking(() -> { + return computeWorkerPool.executeBlocking(() -> { handleBucketsV2(rc); + return null; }); } @@ -1232,8 +1246,9 @@ private boolean validateServiceLink(RoutingContext rc) { } private Future handleIdentityMapV2Async(RoutingContext rc) { - return computePoolService.executeBlocking(() -> { + return computeWorkerPool.executeBlocking(() -> { handleIdentityMapV2(rc); + return null; }); } @@ -1301,8 +1316,9 @@ private InputUtil.InputVal[] getIdentityMapV2Input(RoutingContext rc) { } private Future handleIdentityMapV3Async(RoutingContext rc) { - return computePoolService.executeBlocking(() -> { + return computeWorkerPool.executeBlocking(() -> { handleIdentityMapV3(rc); + return null; }); } diff --git a/src/test/java/com/uid2/operator/ExtendedUIDOperatorVerticle.java b/src/test/java/com/uid2/operator/ExtendedUIDOperatorVerticle.java index 1efd21672..79868da94 100644 --- a/src/test/java/com/uid2/operator/ExtendedUIDOperatorVerticle.java +++ b/src/test/java/com/uid2/operator/ExtendedUIDOperatorVerticle.java @@ -2,7 +2,6 @@ import com.uid2.operator.model.KeyManager; import com.uid2.operator.monitoring.IStatsCollectorQueue; -import com.uid2.operator.service.ComputePoolService; import com.uid2.operator.service.IUIDOperatorService; import com.uid2.operator.service.SecureLinkValidatorService; import com.uid2.operator.store.IConfigStore; @@ -12,6 +11,7 @@ import com.uid2.shared.store.*; import com.uid2.shared.store.salt.ISaltProvider; import io.vertx.core.Handler; +import io.vertx.core.WorkerExecutor; import io.vertx.core.json.JsonObject; import java.time.Clock; @@ -35,8 +35,8 @@ public ExtendedUIDOperatorVerticle(IConfigStore configStore, SecureLinkValidatorService secureLinkValidationService, Handler saltRetrievalResponseHandler, UidInstanceIdProvider uidInstanceIdProvider, - ComputePoolService computePoolService) { - super(configStore, config, clientSideTokenGenerate, siteProvider, clientKeyProvider, clientSideKeypairProvider, keyManager, saltProvider, optOutStore, clock, statsCollectorQueue, secureLinkValidationService, saltRetrievalResponseHandler, uidInstanceIdProvider, computePoolService); + WorkerExecutor computeWorkerPool) { + super(configStore, config, clientSideTokenGenerate, siteProvider, clientKeyProvider, clientSideKeypairProvider, keyManager, saltProvider, optOutStore, clock, statsCollectorQueue, secureLinkValidationService, saltRetrievalResponseHandler, uidInstanceIdProvider, computeWorkerPool); } public IUIDOperatorService getIdService() { diff --git a/src/test/java/com/uid2/operator/UIDOperatorVerticleTest.java b/src/test/java/com/uid2/operator/UIDOperatorVerticleTest.java index aeb3015b7..e45bd9f46 100644 --- a/src/test/java/com/uid2/operator/UIDOperatorVerticleTest.java +++ b/src/test/java/com/uid2/operator/UIDOperatorVerticleTest.java @@ -38,6 +38,7 @@ import io.vertx.core.Future; import io.vertx.core.Handler; import io.vertx.core.Vertx; +import io.vertx.core.WorkerExecutor; import io.vertx.core.buffer.Buffer; import io.vertx.core.http.HttpHeaders; import io.vertx.core.json.JsonArray; @@ -142,7 +143,7 @@ public class UIDOperatorVerticleTest { private ExtendedUIDOperatorVerticle uidOperatorVerticle; private RuntimeConfig runtimeConfig; private EncryptedTokenEncoder encoder; - private ComputePoolService computePoolService; + private WorkerExecutor computeWorkerPool; @BeforeEach void deployVerticle(Vertx vertx, VertxTestContext testContext, TestInfo testInfo) { @@ -166,8 +167,8 @@ void deployVerticle(Vertx vertx, VertxTestContext testContext, TestInfo testInfo this.uidInstanceIdProvider = new UidInstanceIdProvider("test-instance", "id"); - this.computePoolService = new ComputePoolService(vertx); - this.uidOperatorVerticle = new ExtendedUIDOperatorVerticle(configStore, config, config.getBoolean("client_side_token_generate"), siteProvider, clientKeyProvider, clientSideKeypairProvider, new KeyManager(keysetKeyStore, keysetProvider), saltProvider, optOutStore, clock, statsCollectorQueue, secureLinkValidatorService, shutdownHandler::handleSaltRetrievalResponse, uidInstanceIdProvider, this.computePoolService); + this.computeWorkerPool = vertx.createSharedWorkerExecutor("compute", 4); + this.uidOperatorVerticle = new ExtendedUIDOperatorVerticle(configStore, config, config.getBoolean("client_side_token_generate"), siteProvider, clientKeyProvider, clientSideKeypairProvider, new KeyManager(keysetKeyStore, keysetProvider), saltProvider, optOutStore, clock, statsCollectorQueue, secureLinkValidatorService, shutdownHandler::handleSaltRetrievalResponse, uidInstanceIdProvider, this.computeWorkerPool); vertx.deployVerticle(uidOperatorVerticle, testContext.succeeding(id -> testContext.completeNow())); this.registry = new SimpleMeterRegistry(); @@ -179,8 +180,8 @@ void deployVerticle(Vertx vertx, VertxTestContext testContext, TestInfo testInfo @AfterEach void teardown() { Metrics.globalRegistry.remove(registry); - if (computePoolService != null) { - computePoolService.close(); + if (computeWorkerPool != null) { + computeWorkerPool.close(); } } From fa2ad7dac9fb35c122db89d2ca118ac539322496 Mon Sep 17 00:00:00 2001 From: Samin Rahman Date: Tue, 27 Jan 2026 15:22:51 +1100 Subject: [PATCH 08/11] Added log message for when feature is enabled --- src/main/java/com/uid2/operator/vertx/UIDOperatorVerticle.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/com/uid2/operator/vertx/UIDOperatorVerticle.java b/src/main/java/com/uid2/operator/vertx/UIDOperatorVerticle.java index c89d18591..075a6894a 100644 --- a/src/main/java/com/uid2/operator/vertx/UIDOperatorVerticle.java +++ b/src/main/java/com/uid2/operator/vertx/UIDOperatorVerticle.java @@ -307,6 +307,7 @@ private void setUpEncryptedRoutes(Router mainRouter, BodyHandler bodyHandler) { mainRouter.post(V2_TOKEN_CLIENTGENERATE.toString()).handler(bodyHandler).handler(this::handleClientSideTokenGenerate); if (isAsyncBatchRequestsEnabled) { + LOGGER.info("Async batch requests enabled"); mainRouter.post(V2_IDENTITY_BUCKETS.toString()).handler(bodyHandler).handler(auth.handleV1( rc -> encryptedPayloadHandler.handleAsync(rc, this::handleBucketsV2Async), Role.MAPPER)); mainRouter.post(V2_IDENTITY_MAP.toString()).handler(bodyHandler).handler(auth.handleV1( From 72924e44e8608f48bdd1b903bd6620bfcdfe4d71 Mon Sep 17 00:00:00 2001 From: Release Workflow Date: Tue, 27 Jan 2026 04:26:26 +0000 Subject: [PATCH 09/11] [CI Pipeline] Released Snapshot version: 5.63.34-alpha-293-SNAPSHOT --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index fe911fc02..abbcd88bd 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.uid2 uid2-operator - 5.63.33-alpha-292-SNAPSHOT + 5.63.34-alpha-293-SNAPSHOT UTF-8 From 7ef4e7e7f2efe98ae742509a8e69121d07ef3599 Mon Sep 17 00:00:00 2001 From: Samin Rahman Date: Wed, 28 Jan 2026 12:00:50 +1100 Subject: [PATCH 10/11] Changed GC to ZGC --- Dockerfile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 7f9f95f75..46cce2247 100644 --- a/Dockerfile +++ b/Dockerfile @@ -27,7 +27,8 @@ RUN adduser -D uid2-operator && mkdir -p /opt/uid2 && chmod 777 -R /opt/uid2 && USER uid2-operator CMD java \ - -XX:MaxRAMPercentage=95 -XX:-UseCompressedOops -XX:+PrintFlagsFinal -XX:-OmitStackTraceInFastThrow \ + -XX:+UseZGC -XX:+ZGenerational \ + -XX:MaxRAMPercentage=85 -XX:-UseCompressedOops -XX:+PrintFlagsFinal -XX:-OmitStackTraceInFastThrow \ -Djava.security.egd=file:/dev/./urandom \ -Dvertx.logger-delegate-factory-class-name=io.vertx.core.logging.SLF4JLogDelegateFactory \ -Dlogback.configurationFile=/app/conf/logback.xml \ From 6e771fbda062b00fe06dc5e148d791c623c23f7c Mon Sep 17 00:00:00 2001 From: Release Workflow Date: Wed, 28 Jan 2026 01:04:09 +0000 Subject: [PATCH 11/11] [CI Pipeline] Released Snapshot version: 5.63.35-alpha-294-SNAPSHOT --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index abbcd88bd..88ed2aa1a 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.uid2 uid2-operator - 5.63.34-alpha-293-SNAPSHOT + 5.63.35-alpha-294-SNAPSHOT UTF-8