StateSet API: A Robust Backend Framework

StateSet API is a modern, scalable, and reliable backend system designed for enterprise-grade web services. Built with Rust, it leverages cutting-edge web technologies and best practices to deliver a high-performance infrastructure solution. It is particularly well-suited for e-commerce and manufacturing businesses, adept at handling order management, inventory control, returns processing, warranty management, shipment tracking, and work order handling.

Core Features

StateSet API is built to handle complex business operations. Here’s a breakdown of its key features:

  • Order Management: Full CRUD operations for orders, support for complex workflows and statuses.
  • Inventory Control: Real-time tracking across multiple locations, automated reorder point notifications.
  • Returns Processing: Streamlined return authorization, processing, and integration with refund and exchange systems.
  • Warranty Management: Track and manage product warranties, handle automated claim processing.
  • Shipment Tracking: Real-time integration with major carriers, custom shipment status notifications.
  • Manufacturing & Production: Supplier management, BOM tracking, and version control.
  • Work Order Handling: Create and manage work orders, track progress, and manage resource allocation.

Tech Stack: The Foundation of Performance

Our carefully selected tech stack ensures high performance, scalability, and maintainability.

Core Technologies

  • Language: Rust (for performance, safety, and concurrency)
  • Web Framework: Axum (a lightweight, async, and fast web framework)
  • Database: PostgreSQL (for robust, reliable data storage) with SQLx (for async operations).

ORM and Query Building

  • SeaORM (a powerful async ORM for Rust).

API Protocols and Services

  • REST: Implemented natively with Axum.
  • GraphQL: Implemented using Async-GraphQL for a high-performance GraphQL API.
  • gRPC: Built with Tonic for efficient, type-safe gRPC support.

Caching and Messaging

  • Caching: Redis for high-speed data caching.
  • Message Queue: RabbitMQ for reliable asynchronous processing.

Observability

Technological Advantages:

  • Rust’s Performance & Safety: Guarantees memory safety and prevents common programming errors, leading to a highly reliable and performant API.
  • Asynchronous Operations: Utilizing Rust’s async capabilities for high-throughput and non-blocking processing.
  • Comprehensive Observability: Enables proactive maintenance and rapid issue resolution.
  • Flexible API Protocols: Supports various API protocols, ensuring integration with different client applications and services.

Use Cases:

  • E-commerce Platforms: Efficiently manage orders, inventory, shipments, and customer interactions.
  • Manufacturing Systems: Streamline production workflows, inventory control, supplier management, and quality assurance.
  • Enterprise Solutions: Provides a scalable backend infrastructure for a wide variety of business operations and services.

Architecture: Modular and Event-Driven

StateSet API adopts a modular, asynchronous, event-driven architecture designed for scalability and maintainability.

Key Components

  • Services: Implement the core business logic for specific functionalities.
  • Handlers: Process incoming HTTP requests, routing them to the appropriate logic.
  • Commands: Handle operations that modify data or state in the system (writes).
  • Queries: Handle read operations, retrieving data without modifying it.
  • Events: Enable asynchronous communication and processing through event triggers.
  • Models: Represent domain entities, providing a structured data layer.
  • Middleware: Handle cross-cutting concerns like authentication, rate limiting, and logging.

Performance and Reliability

StateSet API is engineered for high performance and reliability:

  • Handles 10,000+ requests per second on a single node (This is a claim. If you have concrete benchmarks include them here or state in which conditions you measured this).
  • Scales horizontally to accommodate increased load.
  • Designed for 99.99% uptime SLA (Include specifics if this is part of an actual SLA).

Code Examples

Here are some representative code snippets to demonstrate the implementation.

Axum Web Service Entrypoint

This code sets up the Axum web service, including routes, middleware, and integration with other services.

#[tokio::main]
async fn main() -> Result<(), AppError> {
    dotenv().ok();
    let config = Arc::new(config::load()?);
    let log = setup_logger(&config);

    info!(log, "Starting StateSet API";
        "environment" => &config.environment,
        "version" => env!("CARGO_PKG_VERSION")
    );

    let app_state = build_app_state(&config, &log).await?;

    let schema = Arc::new(graphql::create_schema(
        app_state.services.order_service.clone(),
        // ... other service clones
    ));

    setup_telemetry(&config)?;

    // Spawn event processing
    tokio::spawn(events::process_events(
       app_state.event_sender.subscribe(),
       app_state.services.clone(),
       log.clone(),
    ));

    // Start gRPC server (conditionally included)
    #[cfg(feature = "grpc")]
    let grpc_server = grpc_server::start(config.clone(), app_state.services.clone()).await?;

    let app = Router::new()
        .route("/health", get(health::health_check))
        .nest("/orders", handlers::orders::routes())
        // ... other route nests
        .route("/proto_endpoint", post(handle_proto_request))
        .layer(Extension(app_state))
        .layer(Extension(schema))
        .layer(TraceLayer::new_for_http())
        .layer(CompressionLayer::new())
        .layer(axum::middleware::from_fn(auth::auth_middleware))
        .layer(axum::middleware::from_fn(rate_limiter::rate_limit_middleware));

    let addr = format!("{}:{}", config.host, config.port);
    info!(log, "StateSet API server running"; "address" => &addr);
    axum::Server::bind(&addr.parse().unwrap())
        .serve(app.into_make_service())
        .await
        .unwrap();

    info!(log, "Shutting down");
    Ok(())
}

This shows the main entry point of the server including the config loading, setup of global services, the route definition, telemetry and the server startup

Handlers: API Request Routing

Here are some examples of how API requests are routed to the correct command.

Create Order Handler

async fn create_order(
    State(order_service): State<Arc<OrderService>>,
    Json(command): Json<CreateOrderCommand>,
) -> Result<impl IntoResponse, ServiceError> {
    let result = command.execute(order_service).await?;
    Ok(Json(result))
}

This handler pulls the OrderService from the application state and calls the execute method on the CreateOrderCommand

Close Return Handler

async fn close_return(
    State(return_service): State<Arc<ReturnService>>,
    Path(return_id): Path<i32>,
) -> Result<impl IntoResponse, ServiceError> {
    let command = CloseReturnCommand { return_id };
    let closed_return = command.execute(return_service).await?;
    Ok(Json(closed_return))
}

This handler pulls the ReturnService from the application state and calls the execute method on the CloseReturnCommand

Commands: Business Logic Execution

The following shows the Create Order and Close Return commands which handle the business logic.

Create Order Command

#[derive(Debug, Serialize, Deserialize, Validate)]
pub struct CreateOrderCommand {
    pub customer_id: Uuid,
    #[validate(length(min = 1, message = "At least one item is required"))]
    pub items: Vec<OrderItem>,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct OrderItem {
    pub product_id: Uuid,
    #[validate(range(min = 1))]
    pub quantity: i32,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct CreateOrderResult {
    pub id: Uuid,
    pub customer_id: Uuid,
    pub status: String,
    pub created_at: DateTime<Utc>,
    pub items: Vec<OrderItem>,
}

#[async_trait::async_trait]
impl Command for CreateOrderCommand {
    type Result = CreateOrderResult;

    #[instrument(skip(self, db_pool, event_sender))]
    async fn execute(
        &self,
        db_pool: Arc<DbPool>,
        event_sender: Arc<EventSender>,
    ) -> Result<Self::Result, ServiceError> {
        // Validates the incoming command. Returns a validation error if invalid
        self.validate().map_err(|e| {
            ORDER_CREATION_FAILURES.inc();
            let msg = format!("Invalid input: {}", e);
            error!("{}", msg);
            ServiceError::ValidationError(msg)
        })?;
        let db = db_pool.as_ref();
        let saved_order = self.create_order(db).await?;
        self.log_and_trigger_event(&event_sender, &saved_order).await?;
        ORDER_CREATIONS.inc();
        Ok(CreateOrderResult {
            id: saved_order.id,
            customer_id: saved_order.customer_id,
            status: saved_order.status,
            created_at: saved_order.created_at.and_utc(),
            items: self.items.clone(),
        })
    }
}
// ... create order implementation

This shows the command definition, validation, and execution of the create order command.

Close Return Command

#[derive(Debug, Serialize, Deserialize)]
pub struct CloseReturnCommand {
    pub return_id: Uuid,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct CloseReturnResult {
    pub id: Uuid,
    pub object: String,
    pub completed: bool,
}

#[async_trait::async_trait]
impl Command for CloseReturnCommand {
    type Result = CloseReturnResult;

    #[instrument(skip(self, db_pool, event_sender))]
    async fn execute(
        &self,
        db_pool: Arc<DbPool>,
        event_sender: Arc<EventSender>,
    ) -> Result<Self::Result, ServiceError> {
        let db = db_pool.as_ref();
        let completed_return = self.close_return(db).await?;
        self.log_and_trigger_event(&event_sender, &completed_return)
            .await?;
        Ok(CloseReturnResult {
            id: completed_return.id,
            object: "return".to_string(),
            completed: true,
        })
    }
}

// ... close return implementation

This shows the command definition, and execution of the close return command.

Queries: Data Retrieval

These show the two return queries used by the application.

Get Returns By Order Query

#[derive(Debug, Serialize, Deserialize)]
pub struct GetReturnsByOrderQuery {
    pub order_id: i32,
}

#[async_trait]
impl Query for GetReturnsByOrderQuery {
    type Result = Vec<Return::Model>;

    async fn execute(&self, db_pool: Arc<DbPool>) -> Result<Self::Result, ServiceError> {
        let db = db_pool.get().map_err(|_| ServiceError::DatabaseError)?;
        Return::find()
            .filter(Return::Column::OrderId.eq(self.order_id))
            .all(&db)
            .await
            .map_err(|_| ServiceError::DatabaseError)
    }
}

This shows how we can find the returns based on the order ID using SeaORM

Get Returns By Date Range Query

#[derive(Debug, Serialize, Deserialize)]
pub struct GetReturnsByDateRangeQuery {
    pub start_date: DateTime<Utc>,
    pub end_date: DateTime<Utc>,
    pub limit: u64,
    pub offset: u64,
}

#[async_trait]
impl Query for GetReturnsByDateRangeQuery {
    type Result = Vec<Return::Model>;

    async fn execute(&self, db_pool: Arc<DbPool>) -> Result<Self::Result, ServiceError> {
        let db = db_pool.get().map_err(|_| ServiceError::DatabaseError)?;
        Return::find()
            .filter(Return::Column::CreatedAt.between(self.start_date, self.end_date))
            .order_by_desc(Return::Column::CreatedAt)
            .limit(self.limit)
            .offset(self.offset)
            .all(&db)
            .await
            .map_err(|_| ServiceError::DatabaseError)
    }
}

This shows how we can find the returns based on a date range using SeaORM.

Acknowledgments

We express our gratitude to the open-source community and the creators of the following libraries:

  • Axum for the powerful web framework.
  • SeaORM for providing a robust ORM.
  • Tonic for enabling gRPC support.
  • Async-GraphQL for efficient GraphQL handling.