DEV Community

Cover image for Concurrency Architecture in Lioran S3: Arc, Traits, Tokio and Backpressure
Swaraj Puppalwar
Swaraj Puppalwar

Posted on

Concurrency Architecture in Lioran S3: Arc, Traits, Tokio and Backpressure

Concurrency Architecture in Lioran S3

Rust does not automatically make concurrent infrastructure correct.

It gives you better tools for making ownership and synchronization explicit.

Lioran S3 uses a relatively clear set of primitives:

Arc
dyn Trait
Tokio async I/O
Semaphore
Mutex
Atomics
Enter fullscreen mode Exit fullscreen mode

I’m Swaraj Puppalwar, Founder & CTO of Lioran Group and Lioran Developer Solutions. This article looks at how those pieces fit together.

Shared server state

The server has a cloneable ServerState.

Major components are stored behind Arc:

pub metadata: Arc<dyn MetadataStore>,
pub object_engine: Arc<dyn ObjectEngine>,
pub config: Arc<ServerConfig>,
pub image_optimizer: Arc<ImageOptimizer>,
pub video_upload_manager: Arc<MultipartUploadManager>,
pub video_pipeline: Arc<VideoPipeline>,
pub video_worker_pool: Arc<VideoWorkerPool>,
pub metrics: Arc<ServerMetrics>,
Enter fullscreen mode Exit fullscreen mode

Cloning request state therefore does not clone the database or object engine.

It clones reference-counted handles.

Trait boundaries

The server depends on:

dyn MetadataStore
dyn ObjectEngine
Enter fullscreen mode Exit fullscreen mode

rather than hard-wiring every caller to one concrete implementation.

This separates:

HTTP/server orchestration
Enter fullscreen mode Exit fullscreen mode

from:

physical object implementation
metadata implementation
Enter fullscreen mode Exit fullscreen mode

That is useful for testing and future engine changes.

Async file I/O

Normal object paths use Tokio:

tokio::fs::File
AsyncRead
AsyncReadExt
AsyncWriteExt
Enter fullscreen mode Exit fullscreen mode

The request does not need to synchronously block a worker thread while waiting for every network read.

Backpressure

Async I/O does not mean “accept infinite work”.

Multipart explicitly adds a global semaphore:

global_limiter: Arc<Semaphore>
Enter fullscreen mode Exit fullscreen mode

Each active part upload must acquire a permit.

That converts unlimited demand into bounded active work plus waiting.

This is backpressure.

Why backpressure matters

Suppose each active part uses:

128 KiB explicit stream buffer
Enter fullscreen mode Exit fullscreen mode

and there are 64 active part streams.

The explicit copy buffers are roughly:

64 × 128 KiB = 8 MiB
Enter fullscreen mode Exit fullscreen mode

before accounting for HTTP buffers, Tokio, filesystem state, metadata, TLS, and other allocations.

Without a concurrency ceiling, memory and descriptor usage can grow with incoming demand.

Mutex where state converges

Multipart also owns:

session_update_lock: Arc<Mutex<()>>
Enter fullscreen mode Exit fullscreen mode

Parts may stream concurrently, but they eventually converge on shared upload-session state.

That is a different problem from bandwidth concurrency.

The engine can keep expensive data transfer parallel while serializing the small critical section that updates shared session metadata.

Atomic shutdown state

The server uses:

Arc<AtomicBool>
Enter fullscreen mode Exit fullscreen mode

for the graceful shutdown flag.

Checking whether shutdown has begun does not require a mutex around a boolean.

The implementation uses sequentially consistent ordering for this flag.

Avoid one global lock

The architecture document explicitly warns against global locks on hot paths.

That is important in storage systems because one innocent global mutex can turn:

64 concurrent requests
Enter fullscreen mode Exit fullscreen mode

into:

1 request doing work
63 requests admiring the mutex
Enter fullscreen mode Exit fullscreen mode

Shared metadata store

Arc<dyn MetadataStore> allows multiple request paths and subsystems to share the embedded metadata engine.

RocksDB itself is configured with background parallelism and an internal shared block cache.

The Rust abstraction does not wrap the entire metadata engine in one application-level global mutex.

Where concurrency is intentionally bounded

Examples include:

  • multipart global active-part count
  • maximum active upload sessions
  • RocksDB background jobs
  • media worker behavior
  • bounded stream buffers

This is a more useful performance model than simply spawning tasks until the host files a resignation letter.

The design principle

Concurrency should be:

parallel where work is independent
serialized where state must be coherent
bounded where resources are finite
Enter fullscreen mode Exit fullscreen mode

That is the shape Lioran S3 is moving toward in V1.

Not “async everywhere”.

Not “mutex everything”.

Not “spawn until benchmark graph goes vertical”.

Infrastructure needs controlled concurrency.

Top comments (0)