A Go client for Infinispan using the Hot Rod binary protocol (version 4.1).
- Hot Rod 4.1 binary protocol over TCP
- SCRAM-SHA-256, PLAIN, OAUTHBEARER and EXTERNAL (certificate) authentication
- TLS and mutual TLS (mTLS)
- Topology-aware and hash-distribution-aware routing
- Multiplexed connections (concurrent operations over a single TCP connection)
- Type-safe cache with Protocol Buffers marshalling
- Cache entry event listeners (created, modified, removed, expired)
- Queries and continuous queries with Ickle query language
- Operation flags (force return value, skip cache load, skip indexing, etc.)
go get infinispan.org/go-client
package main
import (
"context"
"fmt"
"log"
"time"
"infinispan.org/go-client/hotrod"
)
func main() {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
client, err := hotrod.NewClient(ctx, "hotrod://admin:password@localhost:11222")
if err != nil {
log.Fatal(err)
}
defer client.Close()
cache := client.Cache("my-cache")
// Put
if err := cache.Put(ctx, []byte("greeting"), []byte("hello world")); err != nil {
log.Fatal(err)
}
// Get
val, found, err := cache.Get(ctx, []byte("greeting"))
if err != nil {
log.Fatal(err)
}
if found {
fmt.Println(string(val)) // hello world
}
// Remove
if err := cache.Remove(ctx, []byte("greeting")); err != nil {
log.Fatal(err)
}
}The client connects using a URI of the form:
hotrod://username:password@host:port
hotrods://username:password@host:port (TLS)
Query parameters for TLS configuration:
| Parameter | Description |
|---|---|
trust_store_file_name |
Path to CA certificate PEM file |
sni_host_name |
SNI hostname for TLS |
trust_ca |
Alias for trust_store_file_name |
client_cert |
Path to client certificate PEM (mTLS) |
client_key |
Path to client private key PEM (mTLS) |
sni_host |
Alias for sni_host_name |
Client-level options are passed to NewClient:
client, err := hotrod.NewClient(ctx, uri,
hotrod.WithClientIntelligence(hotrod.IntelligenceBasic),
hotrod.WithAuth("SCRAM-SHA-256", "admin", "password"),
hotrod.WithConnectTimeout(5*time.Second),
hotrod.WithTrustStore("/path/to/ca.pem"),
)Per-operation options:
// Put with expiration
cache.Put(ctx, key, value,
hotrod.WithLifespan(60*time.Second),
hotrod.WithMaxIdle(30*time.Second),
)
// Put and get the previous value
prev, err := cache.GetAndPut(ctx, key, value)
// Remove and get the previous value
prev, existed, err := cache.GetAndRemove(ctx, key)For type-safe operations using Protocol Buffers:
import (
"infinispan.org/go-client/hotrod"
pb "your/module/proto"
)
// Register the .proto schema with the server
client.Schemas().Register(ctx, "person.proto", personProtoContent)
// Create a typed cache
cache := hotrod.NewTypedCache[string, *pb.Person](
client, "people",
hotrod.ProtoStreamMarshaller(),
func() *pb.Person { return &pb.Person{} },
)
cache.Put(ctx, "john", &pb.Person{Name: "John", Age: 30})
person, found, err := cache.Get(ctx, "john")Listen for cache entry events:
listener, err := cache.AddListener(ctx,
hotrod.WithListenerInterests(hotrod.EventCreated, hotrod.EventRemoved),
)
defer cache.RemoveListener(ctx, listener)
for ev := range listener.Events {
fmt.Printf("event=%v key=%s\n", ev.Type, ev.Key)
}Execute Ickle queries against an indexed cache:
result, err := cache.Query(ctx, "FROM test.Person WHERE age > :minAge",
hotrod.WithQueryParam("minAge", int32(25)),
)
if err != nil {
log.Fatal(err)
}
for _, entry := range result.Entries {
p := &pb.Person{}
proto.Unmarshal(entry.Value, p)
fmt.Printf("%s (age %d)\n", p.Name, p.Age)
}Queries require an indexed cache with a registered protobuf schema.
Register a continuous query using the Ickle query language:
cq, err := cache.ContinuousQuery(ctx, "FROM test.Person WHERE age >= :minAge",
hotrod.WithCQParam("minAge", int32(18)),
)
defer cache.RemoveContinuousQuery(ctx, cq)
for ev := range cq.Events {
switch ev.Type {
case hotrod.CQJoining:
fmt.Printf("matched: %s\n", ev.Key)
case hotrod.CQLeaving:
fmt.Printf("no longer matches: %s\n", ev.Key)
}
}Continuous queries require an indexed cache with a registered protobuf schema.
go build ./...
Unit tests (no server required):
go test -short ./...
Integration tests (requires Docker for testcontainers):
go test -timeout 120s ./test/...
hotrod/ Source code (package hotrod)
test/ Integration and public-API tests
internal/ Internal packages (codec, connection pool, auth, hashing)
documentation/ User guide and protocol implementation guide
Apache License 2.0