Halyx 1.1.0
Halyx 1.1.0 adds a ninth service, function invocation, and reads keys and passwords from a parameter store as they're used, so rotating one no longer means restarting. It also brings Kotlin coroutines to listeners and repositories. Code written for 1.0 keeps compiling and running unchanged.
Function invocation#
Issue #22. A FunctionInvoker calls an AWS Lambda function, an
Azure Function or a Cloud Run function by name, with each cloud's login: IAM on Lambda, an Entra ID token or a
function key on Azure, and a Google ID token on Cloud Run.
FunctionInvoker resize = halyx.provider("images").functionInvoker("resize-image");
FunctionResponse response = resize.invoke(FunctionRequest.builder("{\"key\":\"a.png\"}")
.header("X-Tenant", tenant)
.build());
The behaviour is the same on all three clouds:
- A function that throws raises
UnavailableException, and a missing oneNotFoundException. What the function reported is kept whole as aFunctionErrorcause: Lambda's error message, type and payload, or an HTTP function's status and body (#31). - An invocation runs the function, so it's retried only when the function is configured
idempotent. - Requests over a cloud's payload or header limit are refused before they're sent.
triggerstarts a Lambda function without waiting. There areasync()and reactive views, trace context carried into the function, andhalyx.functionsin Spring Boot.
A function conformance kit checks every provider: in memory, on Floci's Lambda, the Azure Functions host and Google's Functions Framework, and on real Lambda, Azure Functions and Cloud Run functions. See the functions guide.
Keys and passwords that rotate#
Issue #26. Logging in with IAM or Entra ID is still the best way, but some services take a key or a password. Halyx now reads them from a parameter store as they're used, so a rotation takes effect without a restart:
- Azure function keys, on every call.
- Cosmos DB account keys and Event Grid access keys, every
azure.key-refresh-interval(a minute by default). - Cache and Kafka passwords, each time a connection logs in, as SQL passwords already were.
In Spring Boot, these are secrets entries and auth.secret:
halyx:
providers:
azure:
type: azure
properties:
azure.cosmos.endpoint: https://acme.documents.azure.com:443/
secrets:
- property: azure.cosmos.key
store: app-secrets # one of halyx.parameter-stores, on any provider
name: orders-cosmos-key
A missing secret fails the start, naming the entry, and so does a halyx.* value whose ${...} placeholder didn't
resolve. Before, Spring left the placeholder as written, and it was sent as the key. The store can be on
another cloud: a function on Azure can keep its key in AWS
Secrets Manager. See Keys for other services.
Note
Service Bus and App Configuration connection strings are still read once, because their SDKs copy the key when the client is built. For keys that rotate there, log in with Entra ID.
Kotlin coroutines#
Issue #11. A @HalyxListener can be a suspend fun, for
subscriptions and stream consumers. Returning acknowledges the message and throwing retries it, as with any listener.
Repositories take suspend CRUD methods and derived queries, with Flow results read page by page.
@HalyxListener("billing")
suspend fun onOrder(placed: CloudEvent) {
invoices.put(BlobKey.of(placed.subject().orElseThrow()), render(placed)).awaitSingle()
}
Tested on Boot 3.5 (Kotlin 1.9) and Boot 4 (Kotlin 2.3). See Reactive applications.
Also in 1.1.0#
- API compatibility checks (#4): every build compares each published module with the last release, the provider SPI included, and fails on an incompatible change. 1.1.0 was checked against 1.0.0.
- Dependency scanning: OSV-Scanner checks every published module and the samples on each change, and weekly.
- Dependencies: tested on Spring Boot 4.1.2 and 3.5.16, and on the Google Cloud libraries 26.91.0, with the OpenTelemetry API held at 1.67.0 for a security fix.
Before the release, every real-cloud tier passed on AWS, Azure and Google Cloud, with Spring Boot 3.5 and 4, including the key rotation tests on Azure. The portable orders service passed on EKS, GKE and AKS. The results are in Cloud testing.
Upgrading#
Bump the BOM; nothing else changes.
implementation(platform("dev.halyx:halyx-bom:1.1.0"))
From 1.1.0, security fixes go to the 1.1 line.