rusty-cat is an async Rust SDK for resumable file upload and download. It gives applications a compact public facade for building transfer tasks, running those tasks in a background scheduler, receiving progress callbacks, and plugging in protocol-specific implementations such as plain HTTP, Aliyun OSS, Aliyun OSS presigned URLs, Azure Blob Storage, and Azure Blob SAS URLs.
The crate is designed for applications that need reliable large-file transfer without forcing a specific storage backend or database layer. The SDK handles scheduling, chunk dispatch, retry, pause/resume/cancel commands, and progress fan-out. Your application remains responsible for business records, credential management, user permissions, and provider-specific setup.
The recommended public import is:
use rusty_cat::api::*;
Existing module paths still work, but rusty_cat::api::* is the stable, beginner-friendly entry point. Using the facade also makes future refactoring easier because most application code can import SDK types from a single module.
| Item | Value |
|---|---|
| Crate | rusty-cat |
| Version | 0.2.4 |
| Rust edition | 2021 |
| Runtime | Tokio-based async runtime hosted by an internal scheduler thread |
| HTTP stack | reqwest with rustls-tls |
| Platforms | Linux, macOS, and Windows targets supported by stable Rust, Tokio, and reqwest |
| License | MIT |
| Repository | https://github.com/0barman/rusty-cat |
The Crates.io, Docs.rs, and License badge Markdown is shown below. These badges are safe to paste into downstream README files or generated documentation pages:
[](https://crates.io/crates/rusty-cat)
[](https://docs.rs/rusty-cat)
[](LICENSE)
| Capability | Supported | Notes |
|---|---|---|
| HTTP resumable upload | Yes | Upload tasks are split into chunks and delegated to a BreakpointUpload implementation. The default style supports multipart/form-data chunk requests, and provider plugins can replace the request logic. |
| HTTP resumable download | Yes | Download tasks use HEAD during preparation and GET with Range headers for chunk transfer through StandardRangeDownload. |
| In-memory upload source | Yes | UploadPounceBuilder::from_bytes(file_name, bytes, chunk_size) uploads from an in-memory buffer instead of a file path; chunking and sizing behave the same as file-backed uploads. |
| Aliyun OSS direct upload/download | Yes | Enable aliyun-oss-direct; use AliOssDirectUpload and AliOssDirectDownload when the client process is trusted to hold AccessKey credentials. |
| Aliyun OSS presigned upload/download | Yes | Enable aliyun-oss-presigned; use short-lived presigned part and range URLs generated by your backend. |
| Azure Blob direct upload/download | Yes | Enable azure-blob-direct; use Shared Key-authenticated block upload and range download when the client process is trusted to hold the storage account key. |
| Azure Blob SAS upload/download | Yes | Enable azure-blob-sas; use short-lived SAS URLs generated by your backend. |
| Provider-neutral presigned primitives | Yes | Enable presigned to use PresignedMultipartUpload/PresignedRangeDownload and their plans against any S3/OSS-style backend your server can presign, without a provider-specific feature. |
| Presigned plan validation | Yes | PresignedMultipartUploadPlan::validate() rejects zero-size parts, duplicate offsets, and parts outside the declared object size before any byte is sent. |
| Presigned completion/abort callbacks | Yes | A plan can carry complete_request/abort_request plus an optional PresignedCompletionBodyBuilder, so your backend can verify and merge parts (or clean up) when a transfer ends. |
| Presigned URL refresh on expiry | Yes | PresignedUploadUrlRefresher/PresignedDownloadUrlRefresher with refresh_before_secs refresh part/range URLs before they expire during long transfers. |
| Upload concurrency setting | Yes | MeowConfig::builder().max_upload_concurrency(n) limits the number of upload groups running at the same time. |
| Download concurrency setting | Yes | MeowConfig::builder().max_download_concurrency(n) limits the number of download groups running at the same time. |
| Upload progress | Yes | Per-task progress callbacks passed to MeowClient::try_enqueue(...) receive FileTransferRecord snapshots. |
| Download progress | Yes | The same callback model is used for downloads, so upload and download UI code can share one progress-record handler. |
| Global progress listener | Yes | register_global_progress_listener(...) observes all tasks created by the client, which is useful for dashboards and persistence workers. |
| Global SDK debug logs | Yes | set_debug_log_listener(...) installs a process-global SDK log listener for diagnostics and integration tests. |
| Application-managed persistence | Yes | The SDK intentionally does not persist transfer state in an embedded database, so it can fit server, desktop, mobile, and CLI applications. |
| Custom database adaptation | Yes | Persist records from callbacks/listeners in your own database and rebuild tasks after restart. |
| Callback panic isolation | Yes | User callbacks are isolated from scheduler execution; callbacks should still be fast, non-blocking, and panic-free. |
| Chunk failure retry | Yes | with_max_chunk_retries(...) on upload and download builders controls additional retries after the first failed chunk transfer. |
| Upload prepare retry | Yes | UploadPounceBuilder::with_max_upload_prepare_retries(...) controls additional retries after the first failed upload preparation attempt. |
| Intra-file parallel parts | Opt-in | UploadPounceBuilder::with_max_parts_in_flight(n) uploads up to n chunks of one file concurrently. Default 1 (serial). Honored only for out-of-order-safe upload protocols — all four provider protocols (Aliyun OSS direct & presigned multipart, Azure Blob direct & SAS block blob); the built-in default HTTP upload stays serial. Progress, resume, pause, and cancel still observe a single contiguous prefix. See Concurrent chunked transfer. |
| Intra-file parallel download | Opt-in | DownloadPounceBuilder::with_max_parts_in_flight(n) fetches up to n range chunks of one file concurrently and writes them at absolute offsets. Default 1 (serial). Honored only for range-safe protocols (StandardRangeDownload) when the total size is known. Peak memory n * chunk_size. Interrupted concurrent downloads resume from a <file>.rcdl sidecar (re-fetching only missing parts); the sidecar is deleted on success. The download URL must be stable for the transfer's lifetime (no per-request re-signing on the range path). See Concurrent chunked transfer. |
| Transport-aware retry & backoff | Yes | Beyond the retry counts above, transient transport failures (connection reset, timeout, incomplete message) are retried with exponential backoff and jitter, while non-transient errors fail fast. |
| Disk-full & local-file-removed detection | Yes | Local I/O failures are classified into dedicated error codes DiskFull and LocalFileRemoved, so callers can react specifically instead of treating every I/O error the same. |
| Pause/resume/cancel | Yes | Use pause(...), resume(...), and cancel(...) with the returned TaskId. |
| Paused import / selective restore | Yes | try_enqueue_paused(...) imports a task in the paused state with no network/file I/O; resume only the user-selected subset on restart. |
| Resume after process restart / crash | Yes | Rebuild the task and re-enqueue after a restart: downloads resume from the on-disk partial file, default uploads from the server nextByte, and presigned uploads from re-injected parts. See Resuming after a restart. |
| Presigned multipart resume across restart | Yes | PresignedMultipartUpload::with_resumed_parts(...) re-injects parts persisted by a previous run; prepare resumes past the longest verified contiguous prefix and re-sends the rest. |
| Provider multipart session id surfacing | Yes | UploadResumeInfo::provider_upload_id and AliOssDirectUpload::current_upload_id() expose the provider UploadId (not a secret) so orphaned multipart sessions can be aborted out of band. |
| Upload abort on cancel | Yes | Canceling an upload runs the protocol's abort_upload (for example OSS AbortMultipartUpload) so uncommitted parts/blocks stop accruing storage cost. |
| Snapshot diagnostics | Yes | snapshot() returns queued and active scheduler state for monitoring and troubleshooting. |
| Custom HTTP client | Yes | Inject a preconfigured reqwest::Client with MeowConfigBuilder::http_client(...) for proxy, TLS, default headers, or observability integration. |
| Custom upload protocol | Yes | Implement BreakpointUpload to integrate business-specific upload APIs. |
| Custom download protocol | Yes | Implement BreakpointDownload to integrate custom range-download authentication or headers. |
| Custom upload request method/headers | Yes | with_method(...) and with_headers(...) on UploadPounceBuilder customize the default upload request line and headers. |
| Per-task download HTTP override | Yes | DownloadPounceBuilder::with_breakpoint_download_http(...) overrides the range Accept header for a single task without changing global config. |
| Layer | Main types | Responsibility |
|---|---|---|
| Public facade | rusty_cat::api::* |
One import point for client, config, task builders, callbacks, errors, status, logs, and optional providers. |
| Client | MeowClient |
Owns immutable config, lazily starts the executor, submits tasks, controls lifecycle, and manages listeners. |
| Config | MeowConfig, MeowConfigBuilder |
Defines concurrency, queue capacities, HTTP timeout/keepalive, range-download behavior, and optional custom HTTP client. |
| Task builders | UploadPounceBuilder, DownloadPounceBuilder |
Convert simple parameters into executable PounceTask values. |
| Scheduler | Internal executor | Runs background workers, queues tasks, dispatches chunks, retries failures, and emits events. |
| Protocol plugins | BreakpointUpload, BreakpointDownload |
Implement provider-specific signing, presigned URLs, chunk requests, and completion behavior. |
| Observability | FileTransferRecord, TransferSnapshot, Log |
Per-task progress, global progress events, queue snapshots, and debug logs. |
Add the crate:
[dependencies]
rusty-cat = "0.2.4"
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }
For OSS providers, enable only what you need. Keeping the feature list small reduces optional dependencies and makes it clearer which cloud integrations your application actually uses:
[dependencies]
rusty-cat = { version = "0.2.4", features = ["aliyun-oss-direct"] }
| Feature | Purpose |
|---|---|
aliyun-oss-direct |
Aliyun OSS direct upload/download with AccessKey credentials and OSS Signature Version 4 signing. |
aliyun-oss-presigned |
Aliyun OSS presigned multipart upload and range download helpers. |
azure-blob-direct |
Azure Blob upload/download with Shared Key authentication. |
azure-blob-sas |
Azure Blob SAS upload/download helpers. |
presigned |
Provider-neutral presigned multipart/range primitives. |
aliyun-oss |
Convenience umbrella that currently enables aliyun-oss-presigned only. It does not pull in aliyun-oss-direct. |
azure-blob |
Convenience umbrella that currently enables azure-blob-sas only. It does not pull in azure-blob-direct. |
oss-providers |
Both umbrellas together: aliyun-oss + azure-blob (Aliyun OSS presigned + Azure Blob SAS). It does not enable the direct/AccessKey/Shared Key features. |
all |
Enables all four provider features (aliyun-oss-direct, aliyun-oss-presigned, azure-blob-direct, azure-blob-sas). Use it for examples, not minimal production builds. |
The aliyun-oss, azure-blob, and oss-providers umbrellas intentionally select the presigned/SAS flows, because those are the recommended model for untrusted clients (your backend holds the credentials). When you need the direct AccessKey/Shared Key flows, enable aliyun-oss-direct and/or azure-blob-direct explicitly.
For a focused comparison of direct credentials versus presigned/SAS URLs, see Provider feature flags: direct vs presigned/SAS.
This example starts from MeowConfig, creates a MeowClient, registers listeners, builds a task, submits it, waits for the completion/failure signal, inspects a snapshot, and closes the client. It uses an HTTP range download task because that path works without cloud credentials; the same client lifecycle applies to upload tasks and OSS/Azure provider tasks.
```rust,no_run use std::sync::{mpsc, Arc, Mutex}; use std::time::Duration;
use rusty_cat::api::{ DownloadPounceBuilder, FileTransferRecord, Log, MeowClient, MeowConfig, TransferStatus, };
async fn main() -> Result<(), Box> { let config = MeowConfig::builder() .max_upload_concurrency(2) .max_download_concurrency(2) .http_timeout(Duration::from_secs(30)) .tcp_keepalive(Duration::from_secs(60)) .command_queue_capacity(256) .wo
$ claude mcp add rusty-cat \
-- python -m otcore.mcp_server <graph>