ReductStore
repository·main·Indexed 18 days ago
https://github.com/reductstore/reductstoreA high-performance, time-indexed object storage system designed for robotics and industrial IoT workloads. It enables the storage of multimodal binary data—such as images, logs, and ROS bags—with efficient querying via timestamps and metadata labels. The system includes a Lifecycle Module for automated data maintenance (deletion and compression) and supports integration with Zenoh for routing and authentication.
What's inside ReductStore
- Reduct Macros is a specialized library containing macros used by the core ReductStore platform and its Client SDK. It provides the underlying macro-based logic required for the ecosystem's functionality.
Overview of the Lifecycle Module
mainThe Lifecycle Module implements background lifecycle policies for buckets to automate data maintenance. It supports two primary actions:
delete: Removes records older than a specifiedolder_thanduration.compress: Recompresses eligible blocks older than a specifiedolder_thanduration.
The module is organized into three layers:
- Repository: Manages lifecycle definitions, validates settings, and controls the lifecycle of workers.
- Task: A worker loop that runs a specific policy on a schedule and emits system events.
- Action: The execution layer that performs the actual work (deleting or compressing) against storage and reports progress.
For primary nodes, definitions are persisted in
.lifecycleswithin the data directory. For replica nodes, the module operates in a read-only mode where no workers are started.Overview of Reduct Base
mainReduct Base is a foundational library providing base structures and utilities. It is designed to support both the ReductStore platform and its associated Client SDK.How lifecycle tasks and progress work
mainLifecycle tasks use a progress model to avoid processing massive amounts of data in a single run, especially when dealing with large backlogs.
Progress Calculation
Tasks determine a processing window defined by a
startandstoptimestamp:- Start: Always the oldest matching record found in the bucket. Tasks scan from the oldest record to ensure that data that became eligible again (e.g., via label updates) is not missed.
- Stop: The minimum of the
effective_cutoff_stop(the point in time defined byolder_than) and a forward-moving window.
Controlling Workload with
processing_intervalYou can bound the amount of data processed in a single run using the
processing_intervalsetting:- If
processing_intervalis set: The task advances by this duration per run. - If
processing_intervalis NOT set: The task advances by24 * interval(whereintervalis the task's scheduled frequency).
Progress Persistence
When system events are enabled, the module uses the
last_processed_tsfield from the latest lifecycle stats event (found at$system/lifecycle/<instance>/<policy>) to resume work where it left off.Lifecycle Task Loop Semantics
mainThe
LifecycleTaskruns an inner loop with specific retry logic to handle sparse data:- If a run completes and returns
affected_records == 0butcaught_up == false, the worker does not wait for the full scheduled interval. Instead, it retries after 100 ms. - This allows the task to quickly advance through empty time windows until it reaches the current data cutoff.
- Once the task either finds records to process (
affected_records > 0) or reaches the cutoff (caught_up == true), it returns to its normal scheduled interval.
- If a run completes and returns
When to use ReductStore
mainReductStore is a high-performance, time-indexed object storage system designed for robotics and industrial IoT.
Use ReductStore if:
- You have a continuous stream of binary data (images, video, sensor payloads, logs, ROS bags).
- You need to query this data by both time range and metadata (labels).
- You need to manage data lifecycles (e.g., compression or deletion after a certain period).
- You want to replicate only specific subsets of data (filtered by labels) to the cloud to save bandwidth.
Do NOT use ReductStore if:
- You only have numerical data (use a Time-Series Database instead).
- You only have blob data without a need for historical/time-indexed access (use standard object storage).
- You need a message broker (ReductStore is for storage and streaming, not message queueing).
Install ReductStore via Docker
mainThe fastest way to run ReductStore is using Docker. You need to create a local data directory and ensure it has the correct permissions for the container user (UID 10001).
- Create a data directory:
mkdir -p ./data - Set permissions:
sudo chown -R 10001:10001 ./data - Run the container, mapping port 8383 and providing an
RS_API_TOKENvia environment variable.
mkdir -p ./data sudo chown -R 10001:10001 ./data docker run -p 8383:8383 -v ${PWD}/data:/data \ -e RS_API_TOKEN=my-secret-token reduct/store:latest- Create a data directory:
Run ReductStore integration tests locally
mainTo run the integration tests locally, you must first start a Zenoh router using Docker, then start ReductStore with the necessary Zenoh and feature flags, and finally execute the pytest suite.
1. Start Zenoh router
docker run --init -d --name zenoh-router -p 7447:7447/tcp eclipse/zenoh2. Start ReductStore
Run the following command to start the
reductstorepackage with thefs-backend,web-console, andzenoh-apifeatures enabled:RS_DATA_PATH=~/data-test RS_DISABLE_AUTH=true RS_ZENOH_ENABLED=1 RS_ZENOH_CONFIG="mode=client;connect/endpoints=[tcp/127.0.0.1:7447]" RS_ZENOH_SUB_KEYEXPRS="**" RS_ZENOH_QUERY_KEYEXPRS="**" RS_CORS_ALLOW_ORIGIN="https://first-allowed-origin.com, https://second-allowed-origin.com" cargo run -p reductstore --features "fs-backend web-console zenoh-api"3. Run tests
pytest integration_tests/zenohCleanup
docker rm -f zenoh-router rm -rf ~/data-test# 1) Start the Zenoh router: docker run --init -d --name zenoh-router -p 7447:7447/tcp eclipse/zenoh # 2) Start ReductStore: RS_DATA_PATH=~/data-test RS_DISABLE_AUTH=true RS_ZENOH_ENABLED=1 RS_ZENOH_CONFIG="mode=client;connect/endpoints=[tcp/127.0.0.1:7447]" RS_ZENOH_SUB_KEYEXPRS="**" RS_ZENOH_QUERY_KEYEXPRS="**" RS_CORS_ALLOW_ORIGIN="https://first-allowed-origin.com, https://second-allowed-origin.com" cargo run -p reductstore --features "fs-backend web-console zenoh-api" # 3) Run tests: pytest integration_tests/zenohInstall ReductStore via Linux Binary
mainYou can run ReductStore directly on Linux by downloading the binary from the latest release. You must specify the data path using the
RS_DATA_PATHenvironment variable and provide anRS_API_TOKEN.curl -LO https://github.com/reductstore/reductstore/releases/latest/download/reductstore.x86_64-unknown-linux-gnu.tar.gz tar -xzf reductstore.x86_64-unknown-linux-gnu.tar.gz mkdir -p ./data RS_DATA_PATH=./data RS_API_TOKEN=my-secret-token ./reductstoreUse specialized suffixes for Batch and Query operations
mainThe ReductStore HTTP API supports specialized operations by appending suffixes to the entry path. These suffixes allow you to perform batch operations or complex queries on an entry instead of standard single-entry CRUD operations.
Batch Operations
Append
/batchto the entry path to trigger batch processing for reading, writing, updating, or removing records.- Read Batch:
GET /{bucket_name}/{entry_name}/batch - Write Batch:
POST /{bucket_name}/{entry_name}/batch - Update Batch:
PATCH /{bucket_name}/{entry_name}/batch - Remove Batch:
DELETE /{bucket_name}/{entry_name}/batch
Query Operations
Append
/qto the entry path to perform queries or targeted removals using a JSON body.- Query/Remove via Query:
POST /{bucket_name}/{entry_name}/q- Uses a
QueryEntryJSON body to specify theQueryType(e.g.,QueryorRemove).
- Uses a
- Read Batch:
Use extension attachments from meta entries
mainReductStore can automatically attach metadata from system meta entries (e.g.,
entry/$meta) to your extension queries. If a meta entry exists for a matching pattern, its contents are parsed as JSON and injected into the extension's configuration under anattachmentskey.To use this, ensure your meta entries have a label
keythat matches the extension name or the desired attachment key. The system will collect up toMAX_META_ATTACHMENTS(100) records from the meta entry to build the attachment object.Configure the `processing_interval` for lifecycle tasks
mainThe
processing_intervalis an optional setting used to bound the maximum span of data time a single lifecycle run processes. This is useful for keeping individual runs computationally cheap on buckets with large backlogs.- Purpose: Limits the data window per run.
- Requirement: Must be a positive duration.
- Behavior: When set, it replaces the default
24 * intervalwindow and also bounds the full-range window used when system events are disabled.