Repository navigation
v0.24.0
Pre-releaseThis 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.xclients can't reach this server. The gRPC package changed fromspine.message.deliverytospine.delivery(#53). Every service now has a new full name, so an old client getsUNIMPLEMENTED. Also,LiquorPickUpOutcomeis nowDeliveryPickUpOutcome(#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-deliverygroup on GitHub Packages to theio.spine.deliverygroup, which is served without credentials fromhttps://europe-maven.pkg.dev/spine-event-engine/releases(#62, #66). The artifacts arespine-delivery-client,spine-delivery-client-base,spine-delivery-model, andspine-delivery-server. SimpleDeliveryClientis nowDeliveryClient. 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_TIMEOUTwas 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_MILLISvariable sets the interval in milliseconds. It is25by default, and0turns the throttling off. The value must be a whole number,0or greater; any other value stops the server at startup. - The Admin server and its web UI now run on Micronaut 4 (#55, #57). The
adminblock 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-shadedlibrary 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:
InboxStoreandShardSessionStorereplace the storage classes of the server (#78).DeliveryShardRegistry.releaseShard()takes theWorkerIdof the releasing worker and returns aReleaseOutcome(#79, #80).DeliveryShardRegistry.pickUp()returns aDeliveryShardSession, which no longer extendsShardProcessingSessionofcore-jvm(#82).- The artifact now depends on
grpc-netty-shadedat runtime (#83).