Skip to main content

Rust-first, Python-friendly SDK for SeaweedFS

Project description

weedforge

A lightweight Rust SDK with Python bindings for SeaweedFS.

Crates.io PyPI License: MIT

Features

  • Clean Architecture: Domain, Application, Infrastructure, Python layers
  • HA-aware: Multiple master support with automatic failover
  • Async + Sync: Both async and blocking Rust APIs
  • Type-safe: FileId as a first-class entity, not an opaque string
  • Python bindings: Native Python SDK via PyO3
  • Production-ready: Retry logic, error handling, tracing

Installation

Rust

[dependencies]
weedforge = "0.1"

Python

pip install weedforge

Quick Start

Rust (Async)

use weedforge::WeedClient;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Create client with HA support
    let client = WeedClient::builder()
        .master_urls(["http://master1:9333", "http://master2:9333"])
        .build()?;

    // Upload a file
    let file_id = client.write(b"Hello, SeaweedFS!".to_vec(), Some("hello.txt")).await?;
    println!("Uploaded: {}", file_id);

    // Download the file
    let data = client.read(&file_id).await?;
    println!("Downloaded: {} bytes", data.len());

    // Get public URL
    let url = client.public_url(&file_id).await?;
    println!("Public URL: {}", url);

    // Delete the file
    client.delete(&file_id).await?;

    Ok(())
}

Rust (Blocking)

use weedforge::BlockingWeedClient;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = BlockingWeedClient::builder()
        .master_url("http://localhost:9333")
        .build()?;

    let file_id = client.write(b"Hello!".to_vec(), Some("hello.txt"))?;
    let data = client.read(&file_id)?;

    Ok(())
}

Python

from weedforge import WeedClient, FileId

# Create client
client = WeedClient(
    master_urls=["http://localhost:9333"],
    strategy="round_robin",  # or "failover", "random"
    max_retries=3
)

# Upload bytes
file_id = client.write(b"Hello, SeaweedFS!", filename="hello.txt")
print(f"Uploaded: {file_id}")

# Download
data = client.read(file_id)
print(f"Downloaded: {len(data)} bytes")

# Get public URL
url = client.public_url(file_id)
print(f"Public URL: {url}")

# With image resize
url = client.public_url_resized(file_id, width=200, height=200)

# Delete
client.delete(file_id)

# Parse file ID from string
fid = FileId.parse("3,01637037d6")
print(f"Volume: {fid.volume_id}, Key: {fid.file_key}")

Architecture

weedforge follows Clean Architecture principles:

┌─────────────────────────────────────────┐
│             Python Bindings             │  ← Thin wrappers (PyO3)
├─────────────────────────────────────────┤
│            Application Layer            │  ← Use cases (WriteFile, ReadFile)
├─────────────────────────────────────────┤
│              Domain Layer               │  ← Entities (FileId), Ports (traits)
├─────────────────────────────────────────┤
│           Infrastructure Layer          │  ← HTTP clients, HA logic
└─────────────────────────────────────────┘

Dependencies flow downward only:

  • Python → Application → Domain → Infrastructure
  • Domain layer has no external dependencies
  • Application layer is fully testable with mocks

Configuration

Master Selection Strategies

Strategy Description
round_robin Cycle through masters (default)
failover Try masters in order, failover on error
random Random selection

Rust Builder Options

let client = WeedClient::builder()
    .master_urls(["http://master1:9333", "http://master2:9333"])
    .strategy(MasterSelectionStrategy::RoundRobin)
    .max_retries(3)
    .http_config(HttpClientConfig::default()
        .with_connect_timeout(Duration::from_secs(5))
        .with_request_timeout(Duration::from_secs(30)))
    .build()?;

SeaweedFS Protocol

weedforge implements the official SeaweedFS protocol:

Write Flow

  1. GET /dir/assign → Get file ID and volume URL
  2. POST {volume_url}/{fid} → Upload file (multipart)
  3. Return fid for storage

Read Flow

  1. GET /dir/lookup?volumeId=X → Get volume locations
  2. Select replica (random or deterministic)
  3. GET {volume_url}/{fid} → Download file

Development

Prerequisites

  • Rust 1.75+
  • Python 3.9+ (for Python bindings)
  • maturin (for building Python wheels)

Build

# Rust
cargo build --release

# Python (development)
cd crates/weedforge-python
maturin develop

# Python (release wheel)
maturin build --release

Test

# Rust tests
cargo test

# Clippy
cargo clippy --all-targets --all-features

# Format check
cargo fmt --check

# Security audit
cargo deny check

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

weedforge-0.1.1.tar.gz (35.6 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

weedforge-0.1.1-cp39-abi3-win_amd64.whl (2.6 MB view details)

Uploaded CPython 3.9+Windows x86-64

weedforge-0.1.1-cp39-abi3-manylinux_2_24_x86_64.whl (2.9 MB view details)

Uploaded CPython 3.9+manylinux: glibc 2.24+ x86-64

weedforge-0.1.1-cp39-abi3-macosx_11_0_arm64.whl (2.6 MB view details)

Uploaded CPython 3.9+macOS 11.0+ ARM64

weedforge-0.1.1-cp39-abi3-macosx_10_12_x86_64.whl (2.8 MB view details)

Uploaded CPython 3.9+macOS 10.12+ x86-64

File details

Details for the file weedforge-0.1.1.tar.gz.

File metadata

  • Download URL: weedforge-0.1.1.tar.gz
  • Upload date:
  • Size: 35.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: maturin/1.11.2

File hashes

Hashes for weedforge-0.1.1.tar.gz
Algorithm Hash digest
SHA256 2bc71461a83a7d0678097e806131a6c641ee59f1109613bb8183bf3b5a12b1dc
MD5 bce5fc6232119c77fbfae7c0210b2a1a
BLAKE2b-256 a42b133d04877b283d90c07c8c46b9b39750513aba1a6d68aa43e151072dd87f

See more details on using hashes here.

File details

Details for the file weedforge-0.1.1-cp39-abi3-win_amd64.whl.

File metadata

  • Download URL: weedforge-0.1.1-cp39-abi3-win_amd64.whl
  • Upload date:
  • Size: 2.6 MB
  • Tags: CPython 3.9+, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: maturin/1.11.2

File hashes

Hashes for weedforge-0.1.1-cp39-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 4c782df2c7fa375c3658385005e883508995a3635dbde10b8ac0d458538e5c34
MD5 adaca7d9130350def4a2823da22e661e
BLAKE2b-256 c2949549a5dac3031789b9acca13f56f509f3f9aace3213c117e273e402cf065

See more details on using hashes here.

File details

Details for the file weedforge-0.1.1-cp39-abi3-manylinux_2_24_x86_64.whl.

File metadata

File hashes

Hashes for weedforge-0.1.1-cp39-abi3-manylinux_2_24_x86_64.whl
Algorithm Hash digest
SHA256 1403dc17be75538663751f5d9ab551d0c99cc1d01852663d77202343e575b3d9
MD5 d646845d7491a87462e6cf6e497b18c3
BLAKE2b-256 f99512335ddc0e3255ef896d4dd0c5d59695e313cc1c6d9a0b78c616d9230dc2

See more details on using hashes here.

File details

Details for the file weedforge-0.1.1-cp39-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for weedforge-0.1.1-cp39-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 99da21f38641f481a6050e8f94a613c41c99e2ca6c2b65165ac8878b4f533ba0
MD5 fa82da4fe5ed1876df8421d34c3ea764
BLAKE2b-256 529b239d3dd6e2fde3e4ab0e21f3f9dc0ac29909aa86b6a4da62b127c5dc9690

See more details on using hashes here.

File details

Details for the file weedforge-0.1.1-cp39-abi3-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for weedforge-0.1.1-cp39-abi3-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 d0e9510a86e4bf36531afb47b2f40198e6b271ace49d87dcfba831ba62f29b04
MD5 81312b0064ea4a7f90bab7a7b7a36998
BLAKE2b-256 48e7cc0f1746e654cdc46a37b4b6bd0490494f19f8ebce14add3837845ef705e

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page