Skip to content

Halyx 1.1.0

Latest

Choose a tag to compare

@kamranzafar kamranzafar released this 01 Nov 23:51
· 51 commits to main since this release

A minor release, compatible with 1.0. Upgrade by changing the halyx-bom version to 1.1.0; japicmp checks every published module against 1.0.0, so existing code keeps compiling and running. 1.1.x now gets the security fixes (see SECURITY.md).

Features

  • Kotlin coroutines (#11):

    • @HalyxListener methods may be suspend funs, for subscriptions and stream consumers. Returning acks or
      commits, and throwing retries, as with any listener. Needs kotlinx-coroutines-reactor.
    • Reactive repositories take suspend CRUD methods and derived queries, and Flow results: a Flow query reads
      every match, page by page, and a suspend query may return a Window. Entities are @JvmRecord data classes.
    • Tested on Boot 3.5 (Kotlin 1.9) and Boot 4 (Kotlin 2.3), in memory and on Kafka, SQS and DynamoDB emulators,
      with awaitSingle and asFlow over the reactive services.
  • Function invocation (#22):

    • FunctionInvoker invokes AWS Lambda functions, Azure Functions and Cloud Run functions by name, with a payload,
      configured and per-request headers, and a timeout, through CloudContext.functionInvoker. Each cloud's login is
      handled: IAM on Lambda, an Entra ID token or a function key on Azure, a Google ID token on Cloud Run.
    • A function that throws raises UnavailableException on every cloud, a missing one NotFoundException, and
      other statuses map as for every other service. Requests over a cloud's payload or header limit are refused
      before they're sent.
    • Invocations run the function, so they're retried only for functions configured idempotent; the SDKs retry
      others only after throttling or a failure to connect.
    • trigger starts a Lambda function without waiting for it (FunctionCapability.TRIGGER). async() views, and
      ReactiveFunctionInvoker in halyx-reactor.
    • TracingFunctionInvoker carries the trace context into the function, as headers or in Lambda's ClientContext.
    • Spring Boot: halyx.functions.<key> registers a FunctionInvoker bean, with a reactive view.
    • A function conformance kit, run on the memory provider (InMemoryFunctions), Floci's Lambda, the Azure
      Functions host and Google's Functions Framework, with tier 1 real-cloud runs on all three clouds.
    • AzureErrors.fromStatus and GcpErrors.fromStatus map an HTTP status as the SDK translations do.
    • The AI skills know functions: halyx-ai-create plans, writes and tests function calls, halyx-ai-migrate maps
      LambdaClient and HTTP calls to Azure Functions and Cloud Run functions, and halyx-ai-review checks them
      (rule C11).
  • Rotated keys (#26):

    • FunctionConfig.Builder.property(String, Supplier<String>): a property asked for each time it's used. The
      Azure function key is asked for on every call, so a rotated key takes effect without a restart.
    • Spring Boot: halyx.functions.<key>.secrets reads settings such as azure.functions.key from one of the
      halyx.parameter-stores, through its read cache. A missing secret fails the start.
    • Spring Boot: a halyx.* property whose ${...} placeholder didn't resolve fails the start, naming the property.
      Spring leaves such a value as written, so a missing secret was sent as the key and failed every call.
    • Cosmos DB account keys and Event Grid access keys given as suppliers (ProviderConfig.property(String, Supplier),
      and the same on EventBusConfig and SubscriptionConfig) are asked for every azure.key-refresh-interval (one
      minute by default), and Cosmos DB and Event Grid use a rotated key from the next request. Spring Boot:
      secrets on providers, event buses and subscriptions.
    • Service Bus and App Configuration connection strings stay read once: their SDKs copy the key when the client is
      built. The docs recommend Entra ID login for keys that rotate.
    • Cache and Kafka passwords given as suppliers (CacheAuth.password(Supplier),
      StreamAuth.password(mechanism, username, Supplier)) are asked for each time a connection logs in: Redis on
      new connections and reconnects, Kafka also when the broker has open connections log in again. Spring Boot:
      auth.secret on caches, the cache manager and stream clusters, as on databases, including for Spring for
      Apache Kafka.
    • Docs: keeping keys for other services in a parameter store, including a store on another cloud.
    • Spring Boot: a blank properties value no longer counts as set next to a secrets entry for the same setting,
      as a blank value is unset everywhere else.
    • Real-cloud tests on Azure (tier 1): a function key, a Cosmos DB key and an Event Grid key rotated in Key Vault
      while the clients stay open, and the function key through Spring Boot secrets.
  • Function error text (#31): a failed invocation's exception
    has a FunctionError cause with what the function reported, whole: Lambda's errorMessage, errorType and
    payload, or an HTTP function's status and body. FunctionError.of(e) finds it. The exception messages are
    unchanged and still cut long bodies. On the memory provider, a handler's exception is now the FunctionError's
    cause rather than the UnavailableException's.

Build

  • API compatibility checks (#4): mvn verify compares each
    published module with 1.0.0 from Maven Central using japicmp, and fails on a binary- or source-incompatible change
    to the public API, the provider SPI included. CI runs it on every push.
  • Dependency scanning: a workflow scans SBOMs of every published module and the samples with OSV-Scanner on
    every push and pull request, and weekly. osv-scanner.toml lists the findings Halyx can't fix itself, with their
    reasons, in place of the Snyk policy file.

Dependencies

  • OpenTelemetry API 1.67.0, held above the 1.62.0 the Google Cloud libraries bring, for a security fix found
    with OSV-Scanner. The portable orders samples take the same override, and the Boot 3.5 one also log4j 2.25.5.
  • Tested on Spring Boot 4.1.2 and Google Cloud libraries 26.91.0 (Parameter Manager 0.44.0).
  • Spring Boot 3.5 applications: Boot 3.5.16, the newest 3.5 release, manages Spring Framework 6.2.19, for which
    OSV lists advisories fixed only in Spring Framework 7. Halyx doesn't bring Spring Framework; the version is the
    application's Boot's.