Application Framework
Table of Contents
- Introduction
- Project Structure
- Core Components
- Architecture Overview
- Detailed Component Analysis
- Dependency Analysis
- Performance Considerations
- Troubleshooting Guide
- Conclusion
- Appendix
Introduction
This document is a comprehensive guide for the Sparrow application framework, designed for two types of readers:
- Framework Users: Provides practical guides and best practices for application startup process, configuration system, dependency injection container, service lifecycle management, database connection management, etc.
- Framework Extenders: Provides in-depth implementation details for dependency injection container implementation mechanism, configuration loading and validation, extension point design and integration methods.
Project Structure
Sparrow adopts a layered and modular organization approach, with core entry points and infrastructure concentrated in the bootstrap package, configuration system concentrated in the config package, and business capabilities assembled and extended through option functions (Option).
Core Components
- Application Controller App: Responsible for application lifecycle, HTTP server startup, graceful shutdown, subprocess and subscriber management, event bus and message stream integration.
- IoC Container Container: Supports anonymous and named dependency registration and resolution, has instance caching and automatic dependency resolution capabilities.
- Configuration System Config/Loader: Unified loading of YAML/JSON/TOML/Properties and other format configurations, supports .env environment variable override, built-in default values and basic validation.
- Database Connection Aggregation Database: Aggregates Redis, SQL, Badger and other connections, convenient for unified container registration and resolution.
- Authorization and Middleware Authorization: Centrally manages JWT/RSA/Casbin and other authentication middleware, supports named access and sequential composition.
Architecture Overview
Sparrow's startup and operation forms a closed loop of "configuration loading → container registration → application assembly → service startup → graceful shutdown".
Detailed Component Analysis
Application Startup Process
- Configuration Loading: Prioritizes loading from configuration file corresponding to application name, supports multi-format detection; simultaneously loads .env and automatically maps environment variables; sets default values and basic validation.
- Logging and Routing: Creates logger and Gin engine based on configuration.
- Container Initialization: Creates IoC container, then injects database, message bus, task scheduling, session, authentication middleware, etc. through Option.
- Subprocess and Retry: Supports Startable subprocess startup and exponential backoff retry; failed items enter background retry queue.
- HTTP Service: Starts HTTP server based on configuration; listens for system signals, executes graceful shutdown and resource cleanup.
Configuration System
- Configuration Model: Config aggregates subsystem configurations (application, server, CORS, logging, NATS, SQL, Redis, Badger, RabbitMQ, Kafka, Casbin).
- Default Values: SetDefaults sets reasonable default values for each field, ensuring minimum available configuration.
- Loading Strategy: Supports multi-format configuration files and .env override; automatically maps environment variable key names (dot to underscore).
- Validation: validateConfig performs basic validation on necessary fields (such as port range, application name non-empty).
Dependency Injection Container
- Registration: Register/RegisterNamed supports anonymous and named providers; constructor functions need at least one return value.
- Resolution: Resolve supports named and anonymous resolution; internally resolves constructor parameters through reflection and recursively resolves dependencies; first resolution result is cached.
- Helpers: ResolveInstance (anonymous) and ResolveByName (named) simplify invocation; error handling is clear (type mismatch, missing dependency, etc.).
Service Lifecycle Management
- Subprocesses and Subscribers: Unified into App.CleanUp management through NeedCleanup/GracefulClose interfaces; supports timeout control and error logging.
- Retry Mechanism: When subprocess startup fails, it enters background retry queue, adopts exponential backoff (maximum 1 minute, maximum 10 retries), improves startup robustness.
- Graceful Shutdown: Listens for system signals, provides 30-second timeout graceful shutdown for HTTP server, and cleans up all subprocesses and subscribers.
Option Functions and Extension Points
- Server: ServerHost/ServerPort quickly modify host and port.
- Database: SQLiteDB/RedisDB/BadgerDB provide connection registration for different storage backends.
- Message and Events: Nats/NatStreamBus provide NATS connection and event bus; WithProjection registers full projection.
- Task System: Tasks provides scheduler wrapper; Sessions registers session service and routes.
- Middleware: Middlewares directly mount; WithJWT/WithRSA/WithRBAC register authentication middleware and inject into Auth.
- Health Check: HealthCheck registers health check route.
- Debug Mode: DebugMode controls container behavior (such as Badger memory mode).
Database Connection Management
- Database aggregates Redis, SQL, Badger connections, convenient for unified registration and resolution.
- Option Functions:
- SQLiteDB: Opens sqlite3 connection, enables WAL, sync strategy, cache size, timeout and foreign key constraints, and executes Schema.
- RedisDB: Creates Redis client based on configuration.
- BadgerDB: Supports memory mode (debug) and production configuration (file storage, compression, threshold, memtable count, etc.).
- Repository Registration: BadgerRepo/SQLRepo/RedisRepo/MemRepo register named repositories for entities, naming rules and prefix generation determined by utility functions.
Configuration Loading and Validation
- Configuration File Format: YAML/YML/JSON/TOML/Properties/Props/Prop, detects first existing file in order.
- Environment Variables: After .env file loading, automatically maps through AutomaticEnv; dot key names converted to underscores (e.g., app.name → APP_NAME).
- Default Values: SetDefaults provides default values for each subsystem, reduces manual configuration.
- Validation: validateConfig performs basic validation on application name and port.
Authorization and Middleware
- Authorization: Centrally manages TokenGenerator and middleware list; supports named middleware registration and retrieval.
- WithJWT: Registers token generator and JWT middleware.
- WithRSA: Loads client public key from KeyPath, registers RSA client authentication middleware.
- WithRBAC: Registers Casbin Enforcer and injects RBAC middleware.
- Middleware Mounting: Middlewares directly mount to Gin engine.
Dependency Analysis
- App depends on Config, Container, Logger, Gin Engine, Authorization, Scheduler, Subscribers, etc.
- Container depends on reflection to resolve constructor parameters, forming dependency chain.
- Loader and Config together complete configuration loading and validation.
- Option functions inject external dependencies into container through Register/RegisterNamed.
Performance Considerations
- Container Resolution: Dependency chain resolution and instance caching significantly reduce repeated creation costs; recommend registering frequently used singleton services as named for reuse.
- Database: SQLite enables WAL and sync strategy to improve concurrency; Redis/SQL/Badger connection pool and timeout configuration need adjustment based on load assessment.
- NATS/JetStream: Event stream MaxAge and compression strategy affect storage and transmission overhead, should be configured according to business retention policy.
- Retry Strategy: Exponential backoff upper limit and maximum retry count can avoid cascading failures, recommend combining with monitoring alerts.
Troubleshooting Guide
- Configuration Loading Failure: Confirm configuration file format and path; check if .env exists and key name mapping is correct; verify if default values meet minimum requirements.
- Dependency Resolution Failure: Check constructor signature (at least one return value); confirm if dependency is registered; named resolution and anonymous resolution share cache, pay attention to naming consistency.
- Database Connection Abnormal: Verify driver, DSN, credentials and network connectivity; SQLite Schema execution failure needs to check SQL statements and permissions.
- NATS Connection Failure: Verify URL and authentication information; confirm NATS service is reachable.
- HTTP Server Cannot Gracefully Shutdown: Check subprocess/subscriber Close implementation and timeout settings.
Conclusion
Sparrow provides complete infrastructure from startup to operation through clear configuration system, flexible IoC container and pluggable option mechanism. Users can quickly assemble required capabilities through a small number of options; extenders can seamlessly integrate custom services and middleware based on container and option system. It is recommended to combine monitoring and logging in production environment, continuously optimize database and messaging system parameter configuration.
Appendix
Configuration Items Overview and Default Values
Application and Security
- app.name: Application name (default: sparrow)
- app.version: Version number (default: 1.0.0)
- app.secret: Secret key (default: randomly generated)
- app.key_path: RSA public key directory (default: ./data/perms)
Server
- server.host: Host address (default: 0.0.0.0)
- server.port: Port (default: 8080)
CORS
- cors.allow_origins: Allowed origins (default: ["*"])
- cors.allow_methods: Allowed methods (default: ["GET","POST","PUT","DELETE","OPTIONS"])
- cors.allow_headers: Allowed headers (default: ["Origin","Content-Type","Accept","Authorization"])
- cors.allow_credentials: Allow credentials (default: true)
- cors.max_age_hours: Preflight cache hours (default: 1)
Logging
- log.level: Log level (default: info)
- log.format: Output format (default: json)
- log.output: Output location (default: stdout)
- log.filename: File name (default: ./logs/info.log)
- log.mode: Mode (default: dev)
NATS
- nats.url: Service address (default: nats://localhost:4222)
- nats.stream_name: Event stream name (default: default_stream)
- nats.max_age: Event stream maximum retention days (default: 0)
Redis
- redis.host: Host (default: localhost)
- redis.port: Port (default: 6379)
- redis.password: Password (default: empty)
- redis.db: Database number (default: 0)
- redis.es_db: Event store database number (default: 1)
Badger
- badger.data_dir: Repository storage directory (default: ./data/badger/views)
- badger.es_dir: Event store directory (default: ./data/badger/es)
- badger.value_threshold: Value threshold (default: 1MB)
- badger.num_compactors: Concurrent compactor count (default: 1)
- badger.in_memory: Memory mode (default: false)
Casbin
- casbin.model_path: Model file path (default: ./data/casbin/model.conf)
- casbin.policy_path: Policy file path (default: ./data/casbin/policy.csv)
SQL
- sql.driver: Driver (default: postgres)
- sql.host: Host (default: localhost)
- sql.port: Port (default: 5432)
- sql.user: User (default: postgres)
- sql.password: Password (default: postgres)
- sql.dbname: Database name (default: postgres)
- sql.es_dbname: Event store database name (default: postgres)
Environment Variable Mapping Rules
- Key Name Replacement: Replace dots (.) in configuration keys with underscores (_), e.g., app.name → APP_NAME.
- Automatic Mapping: After enabling AutomaticEnv, environment variables will automatically override same-named keys in configuration file.
Extension Development Guide
Add Custom Service
- Register constructor function through Container.Register/RegisterNamed in option function.
- If service depends on other services, constructor parameters will be automatically resolved by container.
Add Custom Middleware
- Use Middlewares to directly mount to Gin engine.
- Or register named middleware through Authorization.AddMiddleware and enable as needed in routes.
Add Custom Repository
- Use BadgerRepo/SQLRepo/RedisRepo/MemRepo to register named repository for entity.
- Naming rule: Entity short name + "Repo", prefix uses snake_case of entity short name.
Add Custom Message Bus
- Register custom Bus/Hub through NATS connection, and include in App.NeedCleanup management.