StateSet API

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

Features

  • Order Management:

    • Create, retrieve, update, and delete orders
    • Support for complex order workflows and statuses
  • Inventory Control:

    • Real-time inventory tracking across multiple locations
    • Automated reorder point notifications
  • Returns Processing:

    • Streamlined return authorization and processing
    • Integration with refund and exchange systems
  • Warranty Management:

    • Track and manage product warranties
    • Automated claim processing and resolution
  • Shipment Tracking:

    • Real-time tracking integration with major carriers
    • Custom shipment status notifications
  • Manufacturing & Production:

    • Supplier management and communication
    • Bill of Materials (BOM) tracking and version control
  • Work Order Handling:

    • Create and manage work orders for repairs or modifications
    • Track work order progress and resource allocation

Tech Stack

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

Core Technologies

  • Language: Rust (for performance and safety)
  • Web Framework: Axum (lightweight and fast asynchronous web framework)
  • Database: PostgreSQL with SQLx (for robust, async operations)

ORM and Query Building

  • SeaORM (async ORM for Rust, providing powerful database operations)

API Protocols and Services

  • REST: Handled natively by Axum
  • GraphQL: Async-GraphQL (high-performance GraphQL server library for Rust)
  • gRPC: Tonic (for efficient, type-safe gRPC support)

Caching and Messaging

  • Caching: Redis (for high-speed data caching)
  • Message Queue: RabbitMQ (for reliable async processing)

Observability

  • Metrics: Prometheus (for detailed system monitoring)
  • Tracing: OpenTelemetry with Jaeger (for distributed tracing)
  • Logging: slog (for structured, efficient logging)

Technological Advantages:

  • Rust’s Performance & Safety: Ensures memory safety without sacrificing performance, making the API highly reliable and efficient.
  • Asynchronous Operations: Leveraging Rust’s async capabilities for non-blocking, high-throughput processing. Comprehensive Observability: Detailed monitoring and tracing facilitate proactive maintenance and rapid issue resolution. Flexible API Protocols: Support for multiple API protocols allows seamless integration with diverse client applications and services.

Use Cases:

  • E-commerce Platforms: Managing orders, inventory, shipments, and customer interactions with high efficiency and reliability.
  • Manufacturing Systems: Handling production workflows, inventory control, supplier management, and quality assurance processes.
  • Enterprise Solutions: Providing a scalable and maintainable backend infrastructure for various business operations and services.

Architecture

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

Key Components

  • Services: Implement core business logic
  • Handlers: Process HTTP requests
  • Commands: Handle write operations
  • Queries: Manage read operations
  • Events: Enable asynchronous processing
  • Models: Represent domain entities
  • Middleware: Provide cross-cutting concerns (auth, rate limiting, etc.)

Performance

StateSet API is designed for high performance and scalability:

  • Handles 10,000+ requests per second on a single node
  • Scales horizontally for increased load
  • 99.99% uptime SLA

Acknowledgments

We’re grateful to the open-source community and especially:

Axum Web Service

Axum is a web framework for Rust that is designed to be simple, efficient, and powerful. It is built on top of the Tokio runtime and is designed to be asynchronous and non-blocking.


// StateSet API Web 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(),
        app_state.services.inventory_service.clone(),
        app_state.services.return_service.clone(),
        app_state.services.warranty_service.clone(),
        app_state.services.shipment_service.clone(),
        app_state.services.work_order_service.clone(),
        app_state.services.billofmaterials_service.clone(),
        app_state.services.manufacturing_service.clone(),
        app_state.services.suppliers_service.clone(),
        app_state.services.customers_service.clone()
    ));

    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
    #[cfg(feature = "grpc")]
    let grpc_server = grpc_server::start(config.clone(), app_state.services.clone()).await?;

    // Build our application with a route
    let app = Router::new()
        .route("/health", get(health::health_check))
        .nest("/orders", handlers::orders::routes())
        .nest("/inventory", handlers::inventory::routes())
        .nest("/return", handlers::returns::routes())
        .nest("/warranties", handlers::warranties::routes())
        .nest("/shipments", handlers::shipments::routes())
        .nest("/work_orders", handlers::work_orders::routes())
        .nest("/billofmaterials", handlers::billofmaterials::routes())
        .nest("/manufacturing", handlers::manufacturing::routes())
        .nest("/suppliers", handlers::suppliers::routes())
        .nest("/customers", handlers::customers::routes())
        .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));

    // Run our app with hyper
    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(())
}


Handlers

This routes our API requests to the correct modules and handlers.

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))
}

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))
}

Create Order Command


use std::sync::Arc;
use sea_orm::*;
use crate::{
    db::DbPool,
    errors::ServiceError,
    events::{Event, EventSender},
    models::{
        order_entity::{self, Entity as Order},
        order_item_entity::{self, Entity as OrderItem},
        OrderStatus,
    },
};
use serde::{Deserialize, Serialize};
use tracing::{error, info, instrument};
use uuid::Uuid;
use validator::Validate;
use prometheus::IntCounter;
use lazy_static::lazy_static;
use chrono::{DateTime, Utc};

lazy_static! {
    static ref ORDER_CREATIONS: IntCounter = 
        IntCounter::new("order_creations_total", "Total number of orders created")
            .expect("metric can be created");

    static ref ORDER_CREATION_FAILURES: IntCounter = 
        IntCounter::new("order_creation_failures_total", "Total number of failed order creations")
            .expect("metric can be created");
}

#[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> {
        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(),
        })
    }
}

impl CreateOrderCommand {
    async fn create_order(
        &self,
        db: &DatabaseConnection,
    ) -> Result<order_entity::Model, ServiceError> {
        db.transaction::<_, order_entity::Model, ServiceError>(|txn| {
            Box::pin(async move {
                let new_order = order_entity::ActiveModel {
                    customer_id: Set(self.customer_id),
                    status: Set(OrderStatus::Pending.to_string()),
                    created_at: Set(Utc::now().naive_utc()),
                    ..Default::default()
                };

                let saved_order = new_order.insert(txn).await.map_err(|e| {
                    let msg = format!("Failed to save order: {}", e);
                    error!("{}", msg);
                    ServiceError::DatabaseError(msg)
                })?;

                for item in &self.items {
                    let new_item = order_item_entity::ActiveModel {
                        order_id: Set(saved_order.id),
                        product_id: Set(item.product_id),
                        quantity: Set(item.quantity),
                        ..Default::default()
                    };
                    new_item.insert(txn).await.map_err(|e| {
                        let msg = format!("Failed to save order item: {}", e);
                        error!("{}", msg);
                        ServiceError::DatabaseError(msg)
                    })?;
                }

                Ok(saved_order)
            })
        }).await
    }

    async fn log_and_trigger_event(
        &self,
        event_sender: &EventSender,
        saved_order: &order_entity::Model,
    ) -> Result<(), ServiceError> {
        info!(
            order_id = %saved_order.id,
            customer_id = %self.customer_id,
            items_count = %self.items.len(),
            "Order created successfully"
        );

        event_sender
            .send(Event::OrderCreated(saved_order.id))
            .await
            .map_err(|e| {
                ORDER_CREATION_FAILURES.inc();
                let msg = format!("Failed to send event for created order: {}", e);
                error!("{}", msg);
                ServiceError::EventError(msg)
            })
    }
}


Return Commands

The handlers route to the commands and queries that are used to handle the requests.

Close Return Command


use std::sync::Arc;
use sea_orm::*;
use crate::{
    db::DbPool,
    errors::ServiceError,
    events::{Event, EventSender},
    models::{
        return_entity::{self, Entity as Return},
        return_entity::ReturnStatus,
    },
};
use serde::{Deserialize, Serialize};
use tracing::{error, info, instrument};
use uuid::Uuid;

#[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,
        })
    }
}

impl CloseReturnCommand {
    async fn close_return(
        &self,
        db: &DatabaseConnection,
    ) -> Result<return_entity::Model, ServiceError> {
        let return_request = Return::find_by_id(self.return_id)
            .one(db)
            .await
            .map_err(|e| {
                let msg = format!("Failed to find return request: {}", e);
                error!("{}", msg);
                ServiceError::DatabaseError(msg)
            })?
            .ok_or_else(|| {
                let msg = format!("Return request with ID {} not found", self.return_id);
                error!("{}", msg);
                ServiceError::NotFound(msg)
            })?;

        let mut return_request: return_entity::ActiveModel = return_request.into();
        return_request.status = Set(ReturnStatus::Closed.to_string());

        let updated_return = return_request.update(db).await.map_err(|e| {
            let msg = format!("Failed to close return request: {}", e);
            error!("{}", msg);
            ServiceError::DatabaseError(msg)
        })?;

        Ok(updated_return)
    }

    async fn log_and_trigger_event(
        &self,
        event_sender: &EventSender,
        completed_return: &return_entity::Model,
    ) -> Result<(), ServiceError> {
        info!("Return request closed for return ID: {}", self.return_id);
        event_sender
            .send(Event::ReturnClosed(self.return_id))
            .await
            .map_err(|e| {
                let msg = format!("Failed to send event for closed return: {}", e);
                error!("{}", msg);
                ServiceError::EventError(msg)
            })
    }
}

Queries

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)
    }
}

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)
    }
}