Skip to content

v0.24.0

Pre-release
Pre-release

Choose a tag to compare

@alexander-yevsyukov alexander-yevsyukov released this 15 Oct 14:52
a3f217d

This is the first release of Spine Delivery published on GitHub. It covers the changes from #51 onward.

Spine Delivery, formerly codenamed Liquor, is a gRPC server that keeps the shard registry and the inbox of Spine applications. It is now open source, under the Apache License 2.0 (#66). The Terraform module SpineEventEngine/delivery/google deploys it to Google Compute Engine and replaces the spine-liquor module.

Important

This release breaks compatibility with the 0.9.x clients. See “Breaking changes” below.

The server image

europe-docker.pkg.dev/spine-event-engine/containers/delivery-server:v0.24.0

Set this name as the container input of the Terraform module. The image is public and built for linux/amd64 and linux/arm64 (#67). It replaces gcr.io/spine-dev/simple-message-delivery-server.

Every push to master publishes the image tagged latest, v<version>, and the commit SHA. Pin a version tag, so that a restart of the VM doesn't pull a different server.

The environment variables that earlier versions read keep their meaning. The only new variable that the server reads is SHARD_UPDATES_INTERVAL_MILLIS, described below.

Breaking changes

  • The 0.9.x clients can't reach this server. The gRPC package changed from spine.message.delivery to spine.delivery (#53). Every service now has a new full name, so an old client gets UNIMPLEMENTED. Also, LiquorPickUpOutcome is now DeliveryPickUpOutcome (#54). Upgrade the server and its clients together. The published client is built on Spine 2.x. An app on Spine 1.x needs a client generated from the current protos.
  • The Maven coordinates changed. The libraries moved from the io.spine.message-delivery group on GitHub Packages to the io.spine.delivery group, which is served without credentials from https://europe-maven.pkg.dev/spine-event-engine/releases (#62, #66). The artifacts are spine-delivery-client, spine-delivery-client-base, spine-delivery-model, and spine-delivery-server.
  • SimpleDeliveryClient is now DeliveryClient. Closing the client also closes the gRPC channel it created (#63).
  • Stored data isn't carried over. The Redis and Hazelcast modes store data under new keys and map names, and this version doesn't read the data that earlier versions wrote (#78).
  • The Redis mode requires Redis 6 or newer (#78).
  • Each unit of work that may run concurrently needs its own worker ID. The worker that holds a shard can now pick it up again, so two units of work that share a worker ID can process the same shard at the same time (#80).

What's new

Faster and more consistent storage

The inbox and the shard registry are now stored per shard, in all three storage modes (#78):

  • The cost of an operation is proportional to the size of the shard it touches, not of the whole inbox. In the in-memory mode, with 200,000 stored messages, reading a page of a shard takes 0.5 ms, down from 139 ms.
  • Picking up a shard is exclusive across all the servers that share a Redis database or a Hazelcast cluster. Before, it was exclusive only within a single server. The exception is a Hazelcast network split: while it lasts, each part of the cluster may pick up the same shard.

Safer shard sessions

  • Only the worker that holds a shard can release it (#79). A late release from a worker whose session went stale no longer frees a shard that another worker is processing.
  • The worker that holds a shard can pick it up again, which renews its session (#80). This way, a worker recovers when the reply to its pick-up is lost, when its release fails, or when it restarts with the same worker ID. Before, it had to wait until the session went stale, or forever if SHARD_PROCESSING_TIMEOUT was not set.
  • The server skips a pick-up or a release call that is cancelled before the server starts handling it (#80).

Admin updates

  • A shard update now carries the full state of the shard: its status, the time of its last pick-up, and the number of its messages (#51, #78). The counts are exact and the same on every node, and a shard without messages shows 0. Before, each node counted on its own, and the counts drifted apart.
  • The updates are throttled per shard. The new optional SHARD_UPDATES_INTERVAL_MILLIS variable sets the interval in milliseconds. It is 25 by default, and 0 turns the throttling off. The value must be a whole number, 0 or greater; any other value stops the server at startup.
  • The Admin server and its web UI now run on Micronaut 4 (#55, #57). The admin block of the Terraform module turns them on, as before.

Hazelcast clustering

The servers in the Hazelcast mode now find each other by IP multicast, under the cluster name delivery (#68). Hazelcast's cloud auto-detection is off because it left cloud-hosted members standalone. Where the network doesn't carry multicast, enable cloud discovery as the server documentation describes. To keep two deployments on one network apart, set HZ_CLUSTERNAME.

Security

  • The image's Netty libraries are at 4.2.19.Final (#69, #84). They carry the fixes of the Netty security releases 4.2.17.Final through 4.2.19.Final, among them CVE-2026-59903 and several fixes for HTTP/1 request smuggling in netty-codec-http, which serves the Admin server's port.
  • The gRPC port runs on gRPC's own copy of Netty, which is packed inside the grpc-netty-shaded library and can't be upgraded separately. In gRPC 1.85.0, that copy is Netty 4.2.17.Final, and no gRPC release ships a newer one yet (#84).

Logging

The server no longer logs every request by default: requests are now logged at DEBUG, below the default INFO level (#78).

For developers who use the libraries

The libraries depend on gRPC 1.85.0 and Protobuf 4.36.2 (#84). An app that runs spine-delivery-server in its own process also sees these changes:

  • InboxStore and ShardSessionStore replace the storage classes of the server (#78).
  • DeliveryShardRegistry.releaseShard() takes the WorkerId of the releasing worker and returns a ReleaseOutcome (#79, #80).
  • DeliveryShardRegistry.pickUp() returns a DeliveryShardSession, which no longer extends ShardProcessingSession of core-jvm (#82).
  • The artifact now depends on grpc-netty-shaded at runtime (#83).