SeaStreamer

repository·main·Indexed 18 days ago

https://github.com/seaql/sea-streamer

An async, generic, and highly concurrent stream processing toolkit for Rust (version 1.0.0-rc.1). It enables the creation of micro-service oriented stream processors supporting multiple backends including Redis, Kafka, local files, and stdio. The toolkit provides abstractions for producers, consumers, and processors, featuring patterns for resumable "at least once" processing, buffered high-frequency input handling, and fan-out processing for CPU-bound tasks.

Tokens
51.2K
Snippets
179
Records
231
Agent score
63%

What's inside sea-streamer

  1. Use the `sea-streamer-redis` backend

    main

    sea-streamer-redis is a high-level async implementation of the SeaStreamer abstract interface for Redis Streams. It abstracts away low-level Redis commands like XADD, XREAD, and XACK in favor of a type-safe API designed for high throughput (up to 100k messages per second).

    Key Features

    • RealTime mode: Includes AutoStreamReset behavior.
    • Resumable mode: Supports auto-ack and/or auto-commit.
    • LoadBalanced mode: Provides failover behavior.
    • Time-based operations: Seek or rewind to a specific point in time.
    • Stream Sharding: Basic support for splitting a stream into multiple sub-streams.
    • Concurrency Model: Uses a mutex-free implementation where read and write loops are separated from your processing loop, allowing them to run in parallel via Rust's async runtime.
  2. Use the sea-streamer-kafka backend

    main
    The sea-streamer-kafka crate provides a Kafka and Redpanda backend implementation for SeaStreamer. It wraps the underlying rdkafka (and librdkafka) APIs into an asynchronous interface. To ensure safety and prevent race conditions, many methods are marked as &mut and the API is designed to be used within an async runtime.
  3. Use `sea-streamer-runtime` for async runtime abstraction

    main
    The sea-streamer-runtime crate provides a set of functions designed to align type signatures between the smol and tokio async runtimes. This allows developers to build applications that are generic across both runtimes, facilitating easier portability and flexibility in the underlying async executor used by the application.
  4. Overview of `sea-streamer-file` backend

    main

    The sea-streamer-file backend provides a file-based implementation of SeaStreamer semantics. Unlike sea-streamer-stdio which only works in real-time with UTF-8 text, sea-streamer-file supports both real-time streaming and replay by allowing users to seek or rewind to specific timestamps or offsets within a .ss (sea-stream) file.

    Key characteristics:

    • Binary Support: Handles binary payloads, unlike the UTF-8 restricted Stdio backend.
    • Replayability: Supports traversing .ss files and seeking to specific points.
    • Multiple Streamers: Allows multiple independent Streamers to exist within a single process.
    • Efficient Seeking: Uses an array of Beacons placed at fixed intervals in the file. These Beacons act as an in-place index, summarizing streams to enable fast-forwarding and alignment with message boundaries.
    • Semantics: Follows SeaStreamer's multi-producer, multi-consumer semantics with round-robin load balancing.
  5. Implement buffered stream processing for high-frequency inputs

    main

    The buffered processor is an advanced pattern used when the input stream has a high frequency but the processor has high impedance (e.g., slow database inserts).

    Instead of processing messages one by one, it uses an internal queue to decouple the input loop from the processing loop. This allows the processor to handle messages in batches, maximizing throughput and minimizing the impact of sudden bursts. This pattern is ideal for tasks like batch database writes where individual inserts are inefficient.

    alias clock='cargo run --package sea-streamer-stdio --features=executables --bin clock'
    # Pipe a high-frequency clock into the buffered processor
    clock -- --stream clock --interval 100ms | \
    cargo run --bin buffered -- --input stdio:///clock --output stdio:///output
  6. Understand the role of `sea-streamer-types`

    main

    The sea-streamer-types crate serves as the foundational layer for the SeaStreamer ecosystem. It defines all the core traits and types required for the SeaStreamer API.

    Note: This crate is purely a definition layer; it does not provide any functional implementations. To actually use SeaStreamer features, you must use crates that implement these traits (such as sea-streamer-kafka, sea-streamer-redis, etc.).

  7. Implement blocking/fan-out processing for CPU-bound tasks

    main

    The blocking processor pattern is used when you need to perform blocking I/O or heavy CPU-bound computations.

    It utilizes a "fan out" pattern where tasks are randomly assigned to multiple worker threads. This allows the system to handle tasks that would otherwise block the main event loop, enabling the processor to catch up with high-speed input streams by parallelizing the workload across available threads.

    alias clock='cargo run --package sea-streamer-stdio --features=executables --bin clock'
    # Pipe a clock into the blocking processor
    clock -- --stream clock --interval 333ms | \
    cargo run --bin blocking -- --input stdio:///clock --output stdio:///output
  8. Understand Redis vs Kafka streaming behavior in SeaStreamer

    main

    When using the Redis backend, be aware of these fundamental differences compared to Kafka:

    1. Sequence Numbers: In Redis, sequence numbers are not contiguous, unlike in Kafka.
    2. Message Dispatching: In Redis, messages are dispatched to consumers in a first-ask-first-served manner among group members. This differs from Kafka's 1-to-1 consumer-to-shard mapping in a consumer group.
    3. Acknowledgements (ACK): In Redis, ACK must be performed per message. In Kafka, a single Ack (read-up-to) can cover a series of reads.
  9. Understand the SeaStreamer Architecture

    main

    SeaStreamer is built using a modular architecture of sub-crates that allow for backend-agnostic stream processing. The core components are:

    • sea-streamer-types: Defines the fundamental traits and types for the SeaStreamer API. It contains no implementations.
    • sea-streamer-socket: Provides a concrete-type API that allows you to select a backend (like Redis, Kafka, or File) at runtime without recompiling your stream processor.
    • sea-streamer-runtime: An abstraction layer that aligns type signatures between smol and tokio, enabling you to build applications generic to both async runtimes.
    • Backend Crates: Specific implementations for different streaming servers (e.g., sea-streamer-kafka, sea-streamer-redis, sea-streamer-file).

    All crates share the same major version (e.g., 0.1 of sea-streamer depends on 0.1 of sea-streamer-socket).

  10. Understand the `sea-streamer-socket` Backend-agnostic API

    main

    The sea-streamer-socket crate provides a concrete-type API that allows stream processors to work with different SeaStreamer backends (like Redis or Kafka) selected at runtime.

    Unlike the trait-based abstraction in sea-streamer-types, this API enables you to switch backends without recompiling your program. This is useful for scenarios such as generating data locally and streaming it to a production server, or sinking data from a server to a local environment for processing.

    Note: If your application is strictly tied to a single backend, you should depend directly on the specific backend crate (e.g., sea-streamer-redis or sea-streamer-kafka) instead of using the socket abstraction.

  11. Run tests for sea-streamer-iggy

    main

    To run the tests for the sea-streamer-iggy backend, you must first have an Iggy server running. You can spin up an Iggy server using Docker with the following configuration:

    1. Start the Iggy server: Run the docker run command provided below. This sets up the root credentials (iggy/iggy) and enables TCP on port 8090.
    2. Execute tests: Run the cargo test command with the required test and runtime-tokio features enabled.

    Note: The tests use --nocapture to allow you to see the output in your terminal.

    # 1. Start the Iggy server
    docker run -d -p 8090:8090 \
    --cap-add=SYS_NICE \
    --security-opt seccomp=unconfined \
    --ulimit memlock=-1:-1 \
    -e IGGY_ROOT_USERNAME=iggy \
    -e IGGY_ROOT_PASSWORD=iggy \
    -e IGGY_TCP_ENABLED=true \
    -e IGGY_TCP_ADDRESS=0.0.0.0:8090 \
    apache/iggy:latest
    
    # 2. Run the tests
    cargo test --package sea-streamer-iggy --features test,runtime-tokio -- --nocapture
  12. Install SeaStreamer

    main

    Add sea-streamer to your Cargo.toml. To use Kafka, Redis, and the Tokio runtime, enable the corresponding features:

    sea-streamer = { version = "0", features = ["kafka", "redis", "socket", "runtime-tokio"] }
    sea-streamer = { version = "0", features = ["kafka", "redis", "socket", "runtime-tokio"] }