Software Architecture Document: Learnille Server
Software Architecture Document: Learnille Server
1. Introduction
1.1. Purpose1.2. Scope1.3. Definitions, Acronyms, and Abbreviations1.4. References1.5. Overview of the Remainder of the Document2. Architectural Representation
2.1. Architectural Goals - Modularity: Achieved through NestJS modules for distinct features. - Scalability: Leveraging technologies like Node.js, PostgreSQL, Redis, and BullMQ. - Maintainability: TypeScript for type safety, consistent structure via NestJS. - Security: JWT-based authentication, role-based access control (CASL observed), Helmet for security headers. - Testability: Structure supports unit, integration, and e2e testing (Jest setup observed).2.2. Constraints - Technology Stack: Primarily NestJS (Node.js/TypeScript), PostgreSQL, Redis. - Reliance on specific third-party services (e.g., Paystack, Novu, Sentry, New Relic, Cloudflare R2 / S3, InstantDB/Triplit, ClickHouse, Shlink).2.3. Key Architectural Decisions & Rationale - Choice of NestJS: Provides a robust, modular framework for building scalable server-side applications with TypeScript. - Modular Design: Enhances separation of concerns, maintainability, and team collaboration. - Use of TypeORM: Offers a powerful ORM for database interaction with PostgreSQL. - JWT for Authentication: Standard and stateless approach for API security. - Asynchronous Processing with BullMQ: For handling background tasks and improving responsiveness. - Centralized Configuration: Using `@nestjs/config` with environment-specific files and Joi validation. - Event-Driven Elements: Use of `@nestjs/event-emitter` for decoupling components.3. System Overview and Context
3.1. System Context Diagram (Conceptual - to be described textually for now) The Learnille Server acts as the central backend API for various clients (web application, mobile applications). It interacts with: - Databases: Self-Hosted PostgreSQL (primary), Redis (caching/session/rate-limiting), OpenSearch (search), InstantDB/Triplit. - Payment Gateways: Paystack, Flutterwave. - Notification Service: Novu. - Error Tracking & Monitoring: Sentry, New Relic. - File Storage: Cloudflare R2 (S3 API compatible) / MinIO. - Authentication: Google & Apple (for social login). - URL Shortening: Shlink.3.2. Major Components - API Layer: Exposes RESTful endpoints (NestJS Controllers). - Application Core: Business logic encapsulated in NestJS Services and Modules. - Data Access Layer: TypeORM repositories interacting with databases. - Infrastructure Services: Wrappers or integrations for Redis, BullMQ, OpenSearch, Novu, New Relic, Sentry, etc. - External Service Integrations: Clients/SDKs for Paystack, Flutterwave, Google, Cloudflare R2, etc.4. Architectural Views
4.1. Logical View / Module View 4.1.1. Overview The application is structured as a set of NestJS modules. A root `AppModule` imports core infrastructure modules and feature-specific modules.
```mermaid graph LR subgraph User Interaction UI(Frontend) end
subgraph Backend API (NestJS) subgraph Core Modules AppMod(AppModule) --> Cfg(ConfigModule) AppMod --> DB(DatabaseModule) AppMod --> Auth(AuthModule) AppMod --> Redis(RedisModule) AppMod --> Bull(BullMQModule) AppMod --> Elastic(ElasticModule) AppMod --> Notify(NotificationModule) AppMod --> Common(Common Utils) end
subgraph Feature Modules Market(MarketplaceModule) -- uses --> Elastic Consult(ConsultationModule) -- uses --> User(UsersModule) Consult -- uses --> Timeslot(TimeslotService) Consult -- triggers --> Pay(PaymentModule) Cart(CartModule) -- holds --> ConsultEntity(Consultation Entity) Cart -- holds --> CourseEntity(Course Entity) Pay -- uses --> User Pay -- uses --> PayGW(PaystackModule) Pay -- updates --> Wallet(WalletService) Pay -- triggers --> Enroll(EnrollmentModule) Pay -- triggers --> Notify end end
UI --> Market UI --> Consult UI --> Cart Market --> Consult Consult --> Pay Cart --> Pay # Assumed Checkout Flow ```
4.1.2. Core Infrastructure Modules - `ConfigModule`: Manages environment variables and application configuration with Joi validation. - `DatabaseModule` (custom, likely wraps `TypeOrmModule`): Manages PostgreSQL database connections and entity registration. - `AuthModule`: Handles authentication (JWT, local, Google), authorization strategies, and user session management. - `CryptoModule`: Provides cryptographic functions (password hashing, JWT signing/verification). - `RedisModule`: Manages Redis connections for caching and potentially other uses (e.g., Throttler storage). - `BullmqCustomModule`: Manages BullMQ for background job processing. - `ElasticModule`: Integrates with Elasticsearch for search capabilities. - `NotificationModule` & `NovuModule`: Manages notifications via Novu (workflows, subscribers). - `SentryModule`: Integrates Sentry for error tracking and performance monitoring. - `MailerModule`: Handles email sending via SMTP with Handlebars templating. - `ClickHouseModule`: Integrates ClickHouse for analytics. - `StorageModule` (with `SimpleStorageService`): Manages file storage (e.g., S3). - `LoggerModule` (nestjs-pino) / Winston: Provides structured logging capabilities. - `TerminusModule`: For health checks. - `ThrottlerModule`: For API rate limiting. - `EventEmitterModule`: For in-application event handling. 4.1.3. Key Feature Modules (Initial list based on analysis) - `UsersModule`: Manages user profiles, roles, and basic user data. - `CourseModule`: Manages course creation, content (sections, subsections, items), instructors, categories, levels, pricing, and related metadata. - `ConsultationModule`: Manages consultation offerings, consultant availability (timeslots), user bookings, and individual consultation sessions. It supports different consultation types (e.g., one-off, recurring) and integrates with `ElasticModule` for search, `PaymentModule` for billing, `NotificationModule` for reminders, and `ReviewsModule` for feedback. It has its own set of entities for consultations, bookings, timeslots, and type-specific metadata. - `PaymentModule`: Orchestrates financial transactions. It integrates with payment gateways (e.g., `PaystackModule`) to process incoming payments for orders. It manages `Payment` entities and includes a `WalletService` and `WalletController` for user fund management and withdrawals. It interacts closely with `OrderModule`, `UsersModule`, `CourseModule`, `ConsultationModule`, and `EnrollmentModule`. - `PaystackModule`: (If not already listed separately) Provides a dedicated interface for interacting with the Paystack payment gateway API, including payment initiation and webhook handling. - `InstructorsModule`: Manages instructor-specific profiles, linking them to base `User` accounts. It handles details like professional experience, achievements, expertise, and resume. It's tightly coupled with `UsersModule` and `CourseModule` (as instructors create courses) and interacts with `FilesModule` for resume/profile picture storage and potentially `EnrollmentModule` for viewing course enrollments. It may use a shared `ProviderService` for managing common profile sections like experiences and achievements. - `ConsultantModule`: Manages consultant-specific profiles, linking them to base `User` accounts. It handles details like professional experience, achievements, expertise, resume, and availability. It's tightly coupled with `UsersModule` and `ConsultationModule` (as consultants offer consultations) and interacts with `FilesModule` for resume/profile picture storage, `ReviewsModule` for feedback, and uses a shared `ProviderService` for managing common profile sections and availability. - `CartModule`: Provides shopping cart functionality, allowing users to add and manage items (courses, consultations) before purchase. It interacts with product modules for item details and `OrderModule` for checkout. - `OrderModule`: Manages the order creation process. It takes items (often from a cart), applies coupons, calculates totals, and creates `Order` records. It's a crucial intermediary to `PaymentModule` for initiating transactions and `EnrollmentModule` for post-payment fulfillment. - `ReviewsModule`: Handles user-submitted reviews and ratings for products (courses, consultations). Interacts with product modules to update aggregate ratings and `EnrollmentModule` for review eligibility. May integrate with `ElasticModule`. - `MarketplaceModule`: Powers the public-facing discovery of products. Relies heavily on `ElasticModule` for search/filtering and integrates `RecommendationModule`. - `StudentsModule`: Manages student-specific profiles (linked to `User`) and their interactions, particularly closely tied to `EnrollmentModule`. - `ImpressionModule`: Tracks user views/interactions with content like courses and consultations, likely feeding data to analytics or recommendation systems. - `EnrollmentModule`: Manages user enrollment in products, often triggered by successful payments. Includes an `EnrollmentListener` for event-driven enrollment creation and tracks granular progress. - `CommsModule`: Integrates with third-party communication platforms (e.g., Stream, CometChat) for features like chat/calls, managing user tokens for these services. - `CategoryModule`: Manages the hierarchical categorization of content (courses, consultations). - (Others to be detailed as analysis progresses: Product, etc.)4.2. Development View 4.2.1. Source Code Organization: Primarily within `src/`, with modules in dedicated subdirectories (e.g., `src/users`, `src/course`). Common utilities might reside in `src/common` or `src/shared`. Configuration in `src/config.ts` and `env/` directory. 4.2.2. Key Frameworks and Libraries: NestJS, TypeORM, Express.js (underlying NestJS), Passport.js, Joi, BullMQ, Elasticsearch client, Novu SDK, Sentry SDK, Paystack SDK. 4.2.3. Build Process: `npm run build` (uses `nest build`).4.3. Deployment View 4.3.1. Target Environment(s): Local, Development, Staging, Production (as indicated by `.env` file structure and `NODE_ENV` usage). 4.3.2. Physical Infrastructure (Conceptual): - Application Server(s) running Node.js (v22 specified). - PostgreSQL Database Server. - Redis Server. - Elasticsearch Cluster. - ClickHouse Server. - InstantDB/Triplit Server (can be run via `docker-compose.yml` locally). - Dependencies on external services (Paystack, Novu, Sentry, Google, S3, Shlink). 4.3.3. Containerization Strategy: `docker-compose.yml` provided is for `triplit-server`. The main application's containerization strategy for deployment is not yet fully detailed from current files but likely involves Docker. 4.3.4. Technology Stack Summary: Node.js (v22), TypeScript, NestJS, PostgreSQL, Redis, Elasticsearch, BullMQ, Novu, Sentry, Paystack, S3, ClickHouse, InstantDB.5. Data Architecture
5.1. Data Persistence Strategy - Primary Relational Database: PostgreSQL (managed via TypeORM). - Caching/Session/Rate-Limiting: Redis. - Search Indexing: Elasticsearch. - Analytics: ClickHouse. - Real-time/Collaborative Data: InstantDB/Triplit.5.2. High-Level Data Model (Key entities identified so far) - `User`: Core user information, roles, credentials. - `Login`: Tracks login sessions/attempts. - `ForgotPassword`, `VerifyEmail`: Tokens for account recovery/verification. - `Course`: Main course details, pricing, instructor, category, level. - `CourseSection`, `CourseSubSection`, `CourseItem`: Hierarchical course content. - `Instructor`: Profile specific to instructors, linked to a `User`, contains professional details, resume, and courses they manage. - `Consultant`: Profile specific to consultants, linked to a `User`, contains professional details, resume, availability, and consultations they offer. - `Student`: Role-specific profiles linked to Users. - `Consultation`: Main consultation offering details, type, consultant, pricing. - `Booking`: User bookings for consultations. - `ConsultationTimeSlot`: Consultant availability. - `ConsultationSession`: Individual consultation sessions. - `OneOffConsultationMeta`, `RecurringConsultation`: Metadata for specific consultation types. - `Payment`: Records of financial transactions, linked to orders, users, and gateways. - `Withdrawal`: Records of user withdrawal requests from their wallets. - `Order`: Represents a user's intention to purchase items (courses, consultations). - `OrderItem`: Represents individual items within an order. - `Cart`: Represents a user's shopping cart. - `CartItem`: Represents individual items within a cart. - `Coupon`, `CouponUsage`: For managing discount codes. - `Category`: For course categorization. - `Student`: Profile for student users. - `Enrollment`, `SectionEnrollment`: Tracks user enrollment and progress in products. - `Review`: Stores user reviews and ratings. - `UserAuthTokens` (Comms): Stores tokens for external communication services. - `File`: For storing references to uploaded files (profile photos, course materials). - (Others to be added: PaymentTransaction, EnrollmentRecord, Product, etc.)5.3. Data Flow for Key Use Cases - User Registration: Client -> API (`/auth/register`) -> `AuthService` -> `UsersService` (creates User) -> Role-specific service (creates Instructor/Student/Consultant profile) -> DB. Event emitted, Novu notification triggered. - Course Creation: Client -> API (`/course`) -> `CourseController` -> `CourseService` -> DB (creates Course, links to Instructor, Category, Files, etc.). Event emitted. - Consultation Booking: User (Client) browses consultations (via API, potentially using Elasticsearch) -> Selects a consultation and an available timeslot -> Submits booking request (API: `POST /consultation/booking`) -> `ConsultationController` -> `ConsultationService` (validates timeslot, creates `Booking` entity, potentially links to `ConsultationSession`) -> Triggers payment flow (via `PaymentModule`) -> On success, confirms booking, sends notifications (via `NovuModule`). - Checkout Flow: User adds items to Cart (via `CartModule`) -> User proceeds to checkout -> `OrderService` creates an `Order` from Cart items, applies coupons, calculates total, sets status to PENDING -> (Rest of payment flow as previously described, starting with `PaymentsService._initiatePaymentForOrder`). - Product Discovery: User searches/filters on Marketplace UI -> API (`/marketplace/*`) -> `MarketplaceController` -> `MarketplaceService` -> `ElasticModule` (queries Elasticsearch) -> Returns product list. - Leaving a Review: User (Student) submits review for a Course -> API (`/review`) -> `ReviewsController` -> `ReviewsService` (validates eligibility, e.g., via `EnrollmentService`) -> Saves `Review` entity -> Updates aggregate rating on `Course` entity.6. Cross-Cutting Concerns
6.1. Security Architecture - Authentication: JWT-based. `LocalStrategy` for email/password, `GoogleStrategy` for Google OAuth. Managed by `AuthModule` and Passport.js. - Authorization: Role-based access control (RBAC) implied by `UserRole` and potentially fine-grained with `CaslGuard` (seen in `CourseController`). - Input Validation: `class-validator` DTOs with `ValidationPipe`. - HTTP Security Headers: `helmet` middleware. - CORS: Enabled via `app.enableCors()`. - Secret Management: Primarily through environment variables (`.env` files, `ConfigModule`). `KEYS_DIR` in config suggests potential for local key storage.6.2. Error Handling and Fault Tolerance - Global Exception Filter: `AllExceptionsFilter` in `main.ts` for standardized error responses. - Custom exceptions defined per module (e.g., `PhotoNotFoundException` in `UsersModule`). - Sentry: Integrated for error tracking and reporting (`SentryModule`, process-level handlers in `main.ts`).6.3. Logging and Monitoring - Structured Logging: `nestjs-pino` or Winston (conditional in `main.ts`). `AppRequestLoggerMiddleware` for HTTP request logging. - Performance Monitoring: Sentry APM (implied by `instrument.ts` and Sentry setup). - Health Checks: `TerminusModule` imported, likely for `/health` endpoints.6.4. Configuration Management - `@nestjs/config` loading environment-specific `.env` files from `env/`. - Joi schema validation (`src/config.ts`) for environment variables. - Type-safe access via `ConfigService` and `Config` interface.6.5. API Design - RESTful principles generally followed. - Standardized response format via `ResponseInterceptor` (seen in `main.ts`). - API documentation via Swagger (setup in `main.ts`, available at `/docs`).6.6. Asynchronous Processing - `BullmqCustomModule` for background jobs (e.g., email sending, long computations).7. Design Rationale
7.1. Why NestJS? - Opinionated framework providing structure for large applications. - Excellent TypeScript support. - Modular architecture promotes separation of concerns. - Built-in support for microservices, testing, and common patterns.7.2. Why a Modular Architecture? - Improved maintainability and testability. - Allows for parallel development by teams. - Clear boundaries between different functional areas of the application.7.3. Rationale for Database Choices - PostgreSQL: Robust, feature-rich relational database suitable for complex data models. - Redis: High-performance key-value store ideal for caching, session management, and rate limiting. - Elasticsearch: Powerful search engine for providing fast and relevant search results (e.g., for courses). - ClickHouse: Columnar database optimized for OLAP queries and analytics. - InstantDB/Triplit: Real-time database capabilities.Appendix
- (Diagrams can be added here later if text-based representations are feasible)