MCPcopy Index your code
hub / github.com/bsideup/liiklus

github.com/bsideup/liiklus @0.10.0

Chat with this repo
repository ↗ · DeepWiki ↗ · release 0.10.0 ↗ · + Follow
576 symbols 1,884 edges 110 files 6 documented · 1%
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

Liiklus

Liiklus [li:klus] ("traffic" in Estonian) - RSocket/gRPC-based Gateway for the event-based systems from the ones who think that Kafka is too low-level.

Why

  • horizontally scalable RSocket/gRPC streaming gateway
  • supports as many client languages as RSocket+gRPC do (Java, Go, C++, Python, etc...)
  • reactive first
  • Per-partition backpressure-aware sources
  • at-least-once/at-most-once delivery guarantees
  • pluggable event storage (Kafka, Pulsar, Kinesis, etc...)
  • pluggable positions storage (DynamoDB, Cassandra, Redis, etc...)
  • WIP: cold event storage support (S3, Minio, SQL, key/value, etc...)

Who is using

  • https://vivy.com/ - 25+ microservices, an abstraction in front of Kafka for the Shared Log Infrastructure (Event Sourcing / CQRS)

Quick Start

The easiest (and recommended) way to run Liiklus is with Docker:

$ docker run \
    -e kafka_bootstrapServers=some.kafka.host:9092 \
    -e storage_positions_type=MEMORY \ # only for testing, DO NOT use in production
    -p 6565:6565 \
    bsideup/liiklus:$LATEST_VERSION

Where the latest version is:

Now use LiiklusService.proto to generate your client.

The clients must implement the following algorithm:
1. Subscribe to the assignments:
stub.subscribe(SubscribeRequest( topic="your-topic", group="your-consumer-group", [autoOffsetReset="earliest|latest"] )) 1. For every emitted reply of Subscribe, using the same channel, subscribe to the records:
stub.receive(ReceiveRequest( assignment=reply.getAssignment() )) 1. ACK records stub.ack(AckRequest( assignment=reply.getAssignment(), offset=record.getOffset() )) Note 1: If you ACK record before processing it you get at-most-once, after processing - at-least-once
Note 2: It's recommended to ACK every n-th record, or every n seconds to reduce the load on the positions storage

Java example:

Example code using Project Reactor and reactive-grpc:

var stub = ReactorLiiklusServiceGrpc.newReactorStub(channel);
stub
    .subscribe(
        SubscribeRequest.newBuilder()
            .setTopic("user-events")
            .setGroup("analytics")
            .setAutoOffsetReset(AutoOffsetReset.EARLIEST)
            .build()
    )
    .flatMap(reply -> stub
        .receive(ReceiveRequest.newBuilder().setAssignment(reply.getAssignment()).build())
        .window(1000) // ACK every 1000th records
        .concatMap(
            batch -> batch
                .map(ReceiveReply::getRecord)
                // TODO process instead of Mono.delay(), i.e. by indexing to ElasticSearch
                .concatMap(record -> Mono.delay(Duration.ofMillis(100)))
                .sample(Duration.ofSeconds(5)) // ACK every 5 seconds
                .onBackpressureLatest()
                .delayUntil(record -> stub.ack(
                    AckRequest.newBuilder()
                        .setAssignment(reply.getAssignment())
                        .setOffset(record.getOffset())
                        .build()
                )),
            1
        )
    )
    .blockLast()

Also check examples/java/ for a complete example

Configuration

The project is based on Spring Boot and uses it's configuration system
Please check application.yml for the available configuration keys.

License

See LICENSE.

Extension points exported contracts — how you extend this code

LiiklusClient (Interface)
(no doc) [6 implementers]
client/src/main/java/com/github/bsideup/liiklus/LiiklusClient.java
FiniteRecordsStorage (Interface)
(no doc) [10 implementers]
api/src/main/java/com/github/bsideup/liiklus/records/FiniteRecordsStorage.java
GRPCLiiklusTransportConfigurer (Interface)
(no doc) [5 implementers]
plugins/grpc-transport/src/main/java/com/github/bsideup/liiklus/transport/grpc/GRPCLiiklusTransportConfigurer.java
RSocketServerConfigurer (Interface)
(no doc) [3 implementers]
plugins/rsocket-transport/src/main/java/com/github/bsideup/liiklus/transport/rsocket/RSocketServerConfigurer.java
RecordStorageTests (Interface)
(no doc) [3 implementers]
tck/src/main/java/com/github/bsideup/liiklus/records/RecordStorageTests.java
RecordPostProcessor (Interface)
(no doc) [7 implementers]
api/src/main/java/com/github/bsideup/liiklus/records/RecordPostProcessor.java
PositionsStorageTests (Interface)
(no doc) [3 implementers]
tck/src/main/java/com/github/bsideup/liiklus/positions/PositionsStorageTests.java
RecordPreProcessor (Interface)
(no doc) [10 implementers]
api/src/main/java/com/github/bsideup/liiklus/records/RecordPreProcessor.java

Core symbols most depended-on inside this repo

of
called by 62
api/src/main/java/com/github/bsideup/liiklus/positions/GroupId.java
run
called by 60
tck/src/main/java/com/github/bsideup/liiklus/ApplicationRunner.java
withProperty
called by 36
tck/src/main/java/com/github/bsideup/liiklus/ApplicationRunner.java
getTopic
called by 35
tck/src/main/java/com/github/bsideup/liiklus/records/RecordStorageTestSupport.java
getKey
called by 33
api/src/main/java/com/github/bsideup/liiklus/records/LiiklusCloudEvent.java
getValue
called by 20
api/src/main/java/com/github/bsideup/liiklus/records/LiiklusCloudEvent.java
collect
called by 19
plugins/metrics/src/main/java/com/github/bsideup/liiklus/metrics/MetricsCollector.java
equals
called by 19
plugins/kafka-records-storage/src/main/java/com/github/bsideup/liiklus/kafka/KafkaRecordsStorage.java

Shape

Method 419
Class 125
Interface 27
Enum 5

Languages

Java100%

Modules by API surface

api/src/main/java/com/github/bsideup/liiklus/records/LiiklusCloudEvent.java18 symbols
app/src/test/java/com/github/bsideup/liiklus/config/GatewayConfigurationTest.java17 symbols
app/src/main/java/com/github/bsideup/liiklus/service/LiiklusService.java16 symbols
api/src/main/java/com/github/bsideup/liiklus/records/RecordsStorage.java15 symbols
plugins/pulsar-records-storage/src/main/java/com/github/bsideup/liiklus/pulsar/PulsarRecordsStorage.java14 symbols
plugins/kafka-records-storage/src/main/java/com/github/bsideup/liiklus/kafka/KafkaRecordsStorage.java14 symbols
plugins/inmemory-records-storage/src/main/java/com/github/bsideup/liiklus/records/inmemory/InMemoryRecordsStorage.java14 symbols
plugins/schema/src/test/java/com/github/bsideup/liiklus/schema/JsonSchemaPreProcessorTest.java12 symbols
plugins/grpc-transport-auth/src/test/java/com/github/bsideup/liiklus/transport/grpc/GRPCTLSTest.java11 symbols
plugins/grpc-transport-auth/src/main/java/com/github/bsideup/liiklus/transport/grpc/config/GRPCAuthConfiguration.java11 symbols
app/src/test/java/com/github/bsideup/liiklus/GroupVersionTest.java10 symbols
tck/src/main/java/com/github/bsideup/liiklus/records/tests/ConsumerGroupTest.java9 symbols

For agents

$ claude mcp add liiklus \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact