Await cached resource data to become available after save eviction
before asserting, and await null after deletion. Prevents Mockito
verifyNoMoreInteractions(resourceService) failure caused by racing
background cache-load invocations.
Backport of 99334ba7fe from master.
TbRestApiCallNodeTest ran concurrently with SsrfSafeAddressResolverGroupTest,
which toggles the static SsrfProtectionValidator.enabled flag in its
setUp/tearDown. When the flag leaked into the REST test's async HTTP calls,
'localhost' was rejected by SSRF and extra tellFailure invocations broke the
Mockito verify count.
TbHttpClientTest and SsrfSafeAddressResolverGroupTest already declare
@ResourceLock("SsrfProtectionValidator"); apply the same lock to
TbRestApiCallNodeTest so all three SSRF-sensitive tests serialize.
Fixes#15453
Prevents UnrecognizedPropertyException during rolling upgrades when a
newer node writes a cached entity with an added field and an older node
reads it back. The Redis-backed TbJsonRedisSerializer now uses
JacksonUtil.IGNORE_UNKNOWN_PROPERTIES_JSON_MAPPER instead of the strict
OBJECT_MAPPER used by JacksonUtil.fromBytes.
Relax version check to allow maintenance digit increases within the same
LTS family (e.g. 4.3.0 -> 4.3.1), not just patch digit increases.
Add LTS SQL schema patch execution from upgrade/lts/schema_update.sql,
running before views and widget updates so schema changes are in place
for dependent objects.
Replace the blocking semaphore guard with a non-blocking bounded FIFO queue
+ semaphore pattern:
- No semaphore/queue when maxParallelRequestsCount=0 (default): direct doHttpCall,
identical to the old behavior.
- When a concurrency limit is set, incoming messages are enqueued via non-blocking
offer(); a full queue triggers onFailure immediately.
- tryProcess() acquires one semaphore slot and dispatches the next valid queued task.
Stale tasks (batch deadline expired) are dropped and the slot reused in the same pass.
- doFinally hook releases the semaphore and calls tryProcess() exactly once after any
terminal signal (success, error, cancel), preventing double-release and permit leaks.
- publishOn(externalCallExecutor) moves callbacks off reactor-netty I/O threads.
System-level safety caps are wired through thingsboard.yml → ActorSystemContext →
TbContext → TbHttpClient, scoped to rule-engine services only via @TbRuleEngineComponent:
actors.rule.external.http_client.max_parallel_requests (ACTORS_RULE_EXTERNAL_HTTP_CLIENT_MAX_PARALLEL_REQUESTS)
actors.rule.external.http_client.max_pending_requests (ACTORS_RULE_EXTERNAL_HTTP_CLIENT_MAX_PENDING_REQUESTS)
actors.rule.external.http_client.pool_max_connections (ACTORS_RULE_EXTERNAL_HTTP_CLIENT_POOL_MAX_CONNECTIONS)
Backward compat: TB_RE_HTTP_CLIENT_POOL_MAX_CONNECTIONS still honored via yaml fallback.
Observability: five AtomicLong counters (dispatched, success, failure, droppedQueueFull,
droppedStale) with periodic WARN anomaly logging including semaphorePermits for leak detection.
No configuration changes or upgrade scripts required — docker image update is sufficient.
Rename RestApiCallNodeSettings to TbHttpClientSettings
The settings are about HTTP client transport concerns (connection pool,
concurrency, queue depth), not REST API Call node business logic.
The new name matches the consumer (TbHttpClient) and the YAML path
(actors.rule.external.http_client.*).
Removed overflow:hidden from DynamicFormSelectItemsComponent that was hiding the Value/Label table headers and "No options configured" message. Added overflow-visible to nested dynamic-form-properties to prevent clipping in expansion panels.