{"id":29615728,"url":"https://github.com/edgartec97/user-task-api","last_synced_at":"2026-04-09T01:32:32.543Z","repository":{"id":305212191,"uuid":"1020321546","full_name":"EdgarTec97/User-Task-API","owner":"EdgarTec97","description":"Project developed in NestJS with Docker and multiple services and architecture for a maintainable, scalable, and highly efficient application, making the most of the necessary resources.","archived":false,"fork":false,"pushed_at":"2025-07-18T19:00:49.000Z","size":933,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-01-03T17:18:24.287Z","etag":null,"topics":["clean-architecture","docker","docker-compose","domain-driven-design","nestjs","postgresql","typeorm","typescript"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/EdgarTec97.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-07-15T17:23:29.000Z","updated_at":"2025-07-18T19:00:53.000Z","dependencies_parsed_at":"2025-07-18T23:51:46.173Z","dependency_job_id":null,"html_url":"https://github.com/EdgarTec97/User-Task-API","commit_stats":null,"previous_names":["edgartec97/user-task-api"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/EdgarTec97/User-Task-API","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EdgarTec97%2FUser-Task-API","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EdgarTec97%2FUser-Task-API/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EdgarTec97%2FUser-Task-API/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EdgarTec97%2FUser-Task-API/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/EdgarTec97","download_url":"https://codeload.github.com/EdgarTec97/User-Task-API/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EdgarTec97%2FUser-Task-API/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31581864,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-08T14:31:17.711Z","status":"ssl_error","status_checked_at":"2026-04-08T14:31:17.202Z","response_time":54,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["clean-architecture","docker","docker-compose","domain-driven-design","nestjs","postgresql","typeorm","typescript"],"created_at":"2025-07-21T00:35:15.869Z","updated_at":"2026-04-09T01:32:32.522Z","avatar_url":"https://github.com/EdgarTec97.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# User Task API (Challenge)\n\nThis is a comprehensive documentation for the application. It outlines the necessary technologies, setup instructions, and architectural overview.\n\n## Technologies\n\nTo run and develop this project, the following technologies are required:\n\n- **Node.js**: `\u003e=20.0.0 \u003c21.0.0`\n- **Docker**: `v28`\n- **Docker Compose**: `v2`\n- **NestJS**: `v11`\n\n## Setup Instructions\n\nFollow these steps to set up and run the project locally:\n\n1.  **Install Dependencies**\n\n    Use pnpm to install all project dependencies:\n\n    ```bash\n    pnpm install\n    ```\n\n2.  **Start Service Containers**\n\n    Bring up the necessary service containers (PostgreSQL, Redis, Kafka, Zookeeper) using Docker Compose:\n\n    ```bash\n    pnpm containers:up\n    ```\n\n3.  **Build the Application**\n\n    Compile the NestJS application:\n\n    ```bash\n    pnpm build\n    ```\n\n4.  **Generate Database Migrations**\n\n    Generate a new database migration. Replace `GeneralMigration` with a descriptive name for your migration:\n\n    ```bash\n    pnpm migrate generate GeneralMigration\n    ```\n\n5.  **Run Database Migrations**\n\n    Apply the pending database migrations to your PostgreSQL database:\n\n    ```bash\n    pnpm migrate up\n    ```\n\n6.  **Start the Application in Production Mode**\n\n    Launch the NestJS application in production mode:\n\n    ```bash\n    pnpm start:prod\n    ```\n\n### Running the Application with Docker\n\nIf you prefer to run the application directly within a Docker container, you can use the following command after setting up the service containers:\n\n```bash\npnpm containers:app\n```\n\n## Architecture\n\nThis project is built following a **Clean Architecture** approach, emphasizing separation of concerns and testability. It adopts a **modular design** with **Hexagonal Architecture** and **Domain-Driven Design (DDD)** principles.\n\n### Core Principles\n\n- **Clean Architecture**: The architecture is organized into concentric layers, with the innermost layers being independent of the outermost layers. This ensures that business rules are not coupled to external frameworks or databases.\n- **Modular Design**: The application is divided into distinct, self-contained modules (e.g., `user`, `task`), each responsible for a specific domain area. This promotes maintainability and scalability.\n- **Hexagonal Architecture (Ports and Adapters)**: This pattern ensures that the application's core logic is isolated from external concerns like databases, UI, or third-party services. The core application interacts with the outside world through 'ports' (interfaces), and 'adapters' implement these ports for specific technologies.\n- **Domain-Driven Design (DDD)**: The design focuses on a rich understanding of the domain, with concepts like Entities, Value Objects, Aggregates, and Domain Services being central to the codebase.\n\n### Layered Structure\n\nThe project's directory structure reflects its architectural layers. You will observe a distinct layering, particularly within the `shared` module and other domain-specific modules.\n\n#### Shared Module Layers\n\nThe `shared` module, which contains common functionalities and foundational elements, is structured into three primary layers:\n\n1.  **Domain Layer (`src/shared/domain`)**:\n\n    This is the core of the application, containing the enterprise-wide business rules. It is independent of any external concerns. This layer includes:\n\n    - **Entities**: Represent business objects with a distinct identity.\n    - **Value Objects**: Describe characteristics of a thing.\n    - **Domain Services**: Operations that don't naturally fit within an Entity or Value Object.\n    - **Repositories Interfaces**: Define contracts for data persistence, without specifying implementation details.\n\n    ```\n    src/shared/domain/\n    ├── exceptions/\n    ├── interfaces/\n    ├── models/\n    └── value-objects/\n    ```\n\n2.  **Application Layer (`src/shared/application`)**:\n\n    This layer orchestrates the domain objects to perform specific use cases. It contains application-specific business rules and depends on the Domain layer but is independent of the Infrastructure layer. This layer typically includes:\n\n    - **Application Services**: Coordinate domain objects to fulfill use cases.\n    - **DTOs (Data Transfer Objects)**: Used for data input and output.\n    - **Queries and Commands**: Part of CQRS (Command Query Responsibility Segregation) pattern, separating read and write models.\n\n    ```\n    src/shared/application/\n    ├── commands/\n    ├── dtos/\n    ├── queries/\n    └── services/\n    ```\n\n3.  **Infrastructure Layer (`src/shared/infrastructure`)**:\n\n    This layer deals with external concerns such as databases, external APIs, and frameworks. It implements the interfaces defined in the Domain layer. This layer includes:\n\n    - **Persistence Implementations**: Concrete implementations of repository interfaces (e.g., TypeORM repositories for PostgreSQL).\n    - **External Service Integrations**: Adapters for interacting with third-party services.\n    - **Framework-specific code**: NestJS modules, providers, and controllers that handle HTTP requests and responses.\n\n    ```\n    src/shared/infrastructure/\n    ├── database/\n    ├── openapi/\n    ├── services/\n    └── utils/\n    ```\n\n#### Module-Specific Gateway Layer\n\nBeyond the `shared` module, other domain-specific modules (e.g., `user`, `task`) introduce an additional layer called `gateway`. This layer is specifically designed to handle external incoming information, primarily HTTP requests.\n\n- **Gateway Layer (`src/[module]/v1/gateway`)**:\n\n  This layer acts as the entry point for external interactions. It is responsible for:\n\n  - **Request Handling**: Receiving and validating incoming HTTP requests.\n  - **Data Transformation**: Converting external request data into application-layer DTOs.\n  - **Response Formatting**: Transforming application-layer output into appropriate HTTP responses.\n  - **API Endpoints**: Defining the routes and controllers for the module's API.\n\n  For example, within the `user` module, you would find:\n\n  ```\n  src/user/v1/gateway/\n  ├── controllers/\n  ├── dtos/\n  └── guards/\n  ```\n\n  This structure ensures that the core application logic remains decoupled from the specifics of the web framework, allowing for easier changes to the presentation layer if needed.\n\n### Additional Architectural Features\n\nDepending on evolving requirements, the following capabilities can be seamlessly integrated without disrupting existing modules:\n\n#### Scheduled Tasks with Cron Jobs\n\nThe project can leverage the `@nestjs/schedule` package to run background tasks at fixed intervals (e.g., cleanup scripts, report generation, or periodic synchronizations).\n\n```typescript\n// src/task/application/jobs/sample.job.ts\nimport { Injectable } from '@nestjs/common';\nimport { Cron, CronExpression } from '@nestjs/schedule';\n\n@Injectable()\nexport class SampleCronJob {\n  // Runs every day at midnight\n  @Cron(CronExpression.EVERY_DAY_AT_MIDNIGHT)\n  handleCron(): void {\n    // Business logic here\n    console.log('🕛 Running daily task at midnight');\n  }\n}\n```\n\nTo enable cron jobs, register the **ScheduleModule** in your feature module:\n\n```typescript\n// src/task/task.module.ts\nimport { Module } from '@nestjs/common';\nimport { ScheduleModule } from '@nestjs/schedule';\nimport { SampleCronJob } from './application/jobs/sample.job';\n\n@Module({\n  imports: [ScheduleModule.forRoot()],\n  providers: [SampleCronJob],\n})\nexport class TaskModule {}\n```\n\n\u003e **Tip:** Cron jobs adhere to the same modular and DDD boundaries—keep job logic in the _application_ layer and only orchestrate domain services.\n\n#### CQRS with CommandBus and QueryBus\n\nIf read and write workloads must scale independently, **CQRS (Command Query Responsibility Segregation)** can be adopted using NestJS's `@nestjs/cqrs` package. This separates write operations (commands) from read operations (queries) while maintaining a clean domain model.\n\n```typescript\n// src/user/application/commands/create-user.command.ts\nexport class CreateUserCommand {\n  constructor(\n    public readonly email: string,\n    public readonly password: string,\n  ) {}\n}\n\n// src/user/application/handlers/create-user.handler.ts\nimport { CommandHandler, ICommandHandler } from '@nestjs/cqrs';\nimport { CreateUserCommand } from '../commands/create-user.command';\n\n@CommandHandler(CreateUserCommand)\nexport class CreateUserHandler implements ICommandHandler\u003cCreateUserCommand\u003e {\n  async execute(command: CreateUserCommand): Promise\u003cvoid\u003e {\n    const { email, password } = command;\n    // TODO: delegate to domain service / aggregate\n  }\n}\n\n// src/user/application/queries/get-user.query.ts\nexport class GetUserQuery {\n  constructor(public readonly id: string) {}\n}\n\n// src/user/application/handlers/get-user.handler.ts\nimport { QueryHandler, IQueryHandler } from '@nestjs/cqrs';\nimport { GetUserQuery } from '../queries/get-user.query';\n\n@QueryHandler(GetUserQuery)\nexport class GetUserHandler implements IQueryHandler\u003cGetUserQuery\u003e {\n  async execute(query: GetUserQuery): Promise\u003cUserDto\u003e {\n    const { id } = query;\n    // TODO: fetch and return user data\n    return {} as UserDto;\n  }\n}\n\n// src/user/user.module.ts\nimport { Module } from '@nestjs/common';\nimport { CqrsModule } from '@nestjs/cqrs';\nimport { CreateUserHandler } from './application/handlers/create-user.handler';\nimport { GetUserHandler } from './application/handlers/get-user.handler';\n\n@Module({\n  imports: [CqrsModule],\n  providers: [CreateUserHandler, GetUserHandler],\n})\nexport class UserModule {}\n\n// Example usage inside a controller\nawait this.commandBus.execute(new CreateUserCommand(email, password));\nconst user = await this.queryBus.execute(new GetUserQuery(id));\n```\n\nBy introducing CQRS only where necessary (high‑throughput write paths or complex read models), the codebase stays lightweight while providing the flexibility to evolve into more sophisticated patterns (event sourcing, snapshotting) later.\n\n### Services Used\n\nThis project leverages several external services to provide robust and scalable functionality:\n\n- **PostgreSQL**:\n\n  Used as the primary relational database for storing and managing application data. It provides reliability, data integrity, and powerful querying capabilities.\n\n  _Configuration in `docker-compose.yml`:_\n\n  ```yaml\n  postgres:\n    container_name: postgres_${PROJECT_NAME}\n    image: postgres:14.5-alpine\n    environment:\n      - POSTGRES_DB=${POSTGRES_DB}\n      - POSTGRES_USER=${POSTGRES_USER}\n      - POSTGRES_ROL=${POSTGRES_ROL}\n      - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}\n      - PGDATA=/data/postgres\n    volumes:\n      - postgres:/data/postgres\n    ports:\n      - \\'${POSTGRES_PORT}:5432\\'\n    networks:\n      - users-api\n    restart: always\n  ```\n\n- **Redis**:\n\n  Integrated for caching information from certain flows. This significantly improves response times and overall application performance by reducing the load on the primary database.\n\n  _Configuration in `docker-compose.yml`:_\n\n  ```yaml\n  redis:\n    container_name: redis-${PROJECT_NAME}\n    image: bitnami/redis:6.2.7\n    restart: always\n    environment:\n      - REDIS_PASSWORD=${REDIS_PASSWORD}\n    volumes:\n      - redis:/var/lib/redis\n      - redis-config:/usr/local/etc/redis/redis.conf\n    ports:\n      - ${REDIS_PORT}:6379\n    networks:\n      - users-api\n  ```\n\n- **Kafka \u0026 Zookeeper**:\n\n  These are used to implement an **event-driven architecture**, specifically for the user creation flow. Kafka acts as a distributed streaming platform, enabling asynchronous communication and decoupling of services, while Zookeeper manages Kafka brokers.\n\n  _Configuration in `docker-compose.yml`:_\n\n  ```yaml\n  zookeeper:\n    container_name: zookeeper-${PROJECT_NAME}\n    image: \\'bitnami/zookeeper:3.8.0\\'\n    restart: always\n    ports:\n      - ${ZOOKEEPER_PORT}:2181\n    networks:\n      - users-api\n    volumes:\n      - kafka:/data/zookeeper\n    environment:\n      - ALLOW_ANONYMOUS_LOGIN=yes\n  kafka:\n    container_name: kafka-${PROJECT_NAME}\n    image: \\'bitnami/kafka:3.1.0\\'\n    restart: always\n    ports:\n      - ${KAFKA_PORT}:9092\n    environment:\n      - KAFKA_CFG_ZOOKEEPER_CONNECT=zookeeper:${ZOOKEEPER_PORT}\n      - KAFKA_CFG_ADVERTISED_LISTENERS=PLAINTEXT://localhost:${KAFKA_PORT}\n      - ALLOW_PLAINTEXT_LISTENER=yes\n    networks:\n      - users-api\n    volumes:\n      - kafka:/data/kafka\n  ```\n\n- **Swagger**:\n\n  Used for comprehensive API documentation. Once the application is running, you can access the interactive API documentation at the `/api` endpoint. This allows developers to understand, test, and interact with the API endpoints easily.\n\n  _Integration in `src/main.ts`:_\n\n  ```typescript\n  import { NestFactory } from \\'@nestjs/core\\';\n  import { ConfigService } from \\'@nestjs/config\\';\n  import { AppModule } from \\'@/app.module\\';\n  import { SwaggerAPI } from \\'@/shared/infrastructure/openapi/swagger.api\\';\n\n  async function bootstrap() {\n    const app = await NestFactory.create(AppModule);\n    const config: ConfigService = app.get(ConfigService);\n    const port: number = config.get\u003cnumber\u003e(\\'PORT\\') || 3000;\n\n    app.enableCors();\n\n    SwaggerAPI.setup(app);\n\n    await app.listen(port);\n    return port;\n  }\n\n  bootstrap()\n    .then((port: number) =\u003e console.log(`Application is running on port:${port}`))\n    .catch((error) =\u003e console.error(\\'Error starting the application:\\', error));\n  ```\n\n## Further Documentation\n\nThis section will be expanded with more details based on further code analysis. This may include:\n\n- Detailed API Endpoints and Usage\n- Environment Variables\n- Testing Guidelines\n- Deployment Information\n- Contribution Guidelines\n\n## Environment Variables\n\nThis project uses environment variables for configuration. A `.env` file should be created in the root directory of the project, based on the `.env.example` (if available) or the variables used in `docker-compose.yml` and the application code. Below are the key environment variables identified:\n\n- `PROJECT_NAME`: Name of the project, used for naming Docker containers.\n- `PROJECT_PORT`: Port on which the NestJS application will run.\n- `POSTGRES_DB`: Database name for PostgreSQL.\n- `POSTGRES_USER`: Username for PostgreSQL database access.\n- `POSTGRES_ROL`: Role for PostgreSQL database access.\n- `POSTGRES_PASSWORD`: Password for PostgreSQL database access.\n- `POSTGRES_PORT`: Port for PostgreSQL database.\n- `PGADMIN_DEFAULT_EMAIL`: Default email for pgAdmin login.\n- `PGADMIN_DEFAULT_PASSWORD`: Default password for pgAdmin login.\n- `REDIS_PASSWORD`: Password for Redis.\n- `REDIS_PORT`: Port for Redis.\n- `REDIS_COMMANDER_USER`: Username for Redis Commander.\n- `REDIS_COMMANDER_PASSWORD`: Password for Redis Commander.\n- `ZOOKEEPER_PORT`: Port for Zookeeper.\n- `KAFKA_PORT`: Port for Kafka.\n\nIt is crucial to configure these variables correctly for the application and its services to function as expected.\n\n## Advanced Clustering Flow\n\n\u003e **Purpose:** Scale a Node/Nest application horizontally—one worker per CPU core—while an **internal load‑balancing master** evenly distributes incoming traffic.  \n\u003e Result: a resilient architecture capable of handling **high‑throughput** workloads with minimal latency spikes.\n\n### How It Works\n\n1. **Primary (Master) Process**\n\n   - Detects the total number of logical CPU cores (`os.cpus().length`).\n   - Forks a **worker** for each core via Node’s native `cluster` module.\n   - Acts as an **internal load balancer**, accepting incoming connections and routing them to the least‑busy worker in a round‑robin fashion.\n   - Listens for the `'exit'` event; any crashed worker is **automatically respawned** to maintain full capacity.\n\n2. **Worker Processes**\n   - Each worker boots a full instance of your NestJS application (or any Node server).\n   - All workers share the **same TCP port**, but their sockets are managed by the master, preventing port conflicts.\n   - If a worker encounters an unhandled exception and exits, the master transparently replaces it without downtime.\n\n### Benefits\n\n| Feature                 | Impact                                                     |\n| ----------------------- | ---------------------------------------------------------- |\n| Multi‑core utilisation  | Leverages **all CPU cores** instead of a single thread.    |\n| Built‑in load balancing | Master process balances requests without external proxies. |\n| Fault tolerance         | Automatic worker **respawn** maintains availability.       |\n| Zero code changes       | Application logic remains agnostic to clustering.          |\n\n### When to Use\n\n- APIs expected to receive **thousands of concurrent requests**.\n- Workloads with **CPU‑bound** or blocking operations where a single event loop becomes a bottleneck.\n- Environments where external load balancers (e.g., Nginx, HAProxy) are not yet introduced but horizontal scaling is required.\n\n### Quick Start\n\n````ts\n// main.ts\nimport { NestFactory } from '@nestjs/core';\nimport { AppModule } from './app.module';\nimport { AppClusterService } from './app-cluster.service';\n\nasync function bootstrap(): Promise\u003cnumber\u003e {\n  const app  = await NestFactory.create(AppModule);\n  const port = Number(process.env.PORT) || 3000;\n  await app.listen(port);\n  return port;\n}\n\nAppClusterService.clusterize(bootstrap);\n\n\n## Testing\n\nThe project includes a comprehensive suite of tests to ensure code quality and functionality. Jest is used as the testing framework.\n\n- **Run all tests**:\n\n  ```bash\n  pnpm test\n````\n\n- **Run tests in watch mode** (re-runs tests when files change):\n\n  ```bash\n  pnpm test:watch\n  ```\n\n- **Generate test coverage report**:\n\n  ```bash\n  pnpm test:cov\n  ```\n\n- **Run end-to-end tests**:\n\n  ```bash\n  pnpm test:e2e\n  ```\n\n- **Debug tests**:\n\n  ```bash\n  pnpm test:debug\n  ```\n\n## 💻 Swagger API\n\n![Image text](https://edgar-serverless-bucket.s3.us-east-2.amazonaws.com/swagger.png)\n\n## 💻 Workflow API\n\n![Image text](https://edgar-serverless-bucket.s3.us-east-2.amazonaws.com/user_creation_flow.png)\n\n## 💻 Architecture API\n\n![Image text](https://edgar-serverless-bucket.s3.us-east-2.amazonaws.com/architecture_diagram.png)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fedgartec97%2Fuser-task-api","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fedgartec97%2Fuser-task-api","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fedgartec97%2Fuser-task-api/lists"}