← Назад к вопросам

Приведи пример проекта который реализовал в последнее время

1.6 Junior🔥 171 комментариев
#Soft skills и опыт работы

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI30 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Проект: Real-Time Collaborative Task Manager

Описание проекта

Недавно реализовал полнофункциональный веб-приложение для управления задачами в команде с real-time синхронизацией. Система позволяет пользователям создавать проекты, добавлять задачи, назначать их коллегам и видеть обновления в реальном времени.

Стек технологий

  • Backend: Node.js + Express.js + TypeScript
  • Database: PostgreSQL с миграциями Goose
  • Real-time: WebSocket (Socket.io) для синхронизации
  • Authentication: JWT + Refresh tokens
  • Queue: RabbitMQ для асинхронных задач
  • Deployment: Docker + Docker Compose + Dokku

Архитектура Backend

// src/domain/Task/Task.ts - Domain Entity
export class Task {
  constructor(
    public id: string,
    public title: string,
    public description: string,
    public status: "todo" | "in-progress" | "done",
    public assignedTo: string,
    public dueDate: Date,
    public projectId: string
  ) {}

  complete(): void {
    this.status = "done";
  }

  reassign(userId: string): void {
    this.assignedTo = userId;
  }
}
// src/application/usecase/CreateTaskUseCase.ts
export class CreateTaskUseCase {
  constructor(
    private taskRepository: ITaskRepository,
    private projectRepository: IProjectRepository,
    private eventPublisher: IEventPublisher
  ) {}

  async execute(command: CreateTaskCommand): Promise<Task> {
    // 1. Валидация проекта
    const project = await this.projectRepository.findById(command.projectId);
    if (!project) {
      throw new ProjectNotFoundError();
    }

    // 2. Создание задачи
    const task = new Task(
      uuid(),
      command.title,
      command.description,
      "todo",
      command.assignedTo,
      command.dueDate,
      command.projectId
    );

    // 3. Сохранение
    await this.taskRepository.save(task);

    // 4. Публикация события для real-time синхронизации
    await this.eventPublisher.publish("task.created", {
      taskId: task.id,
      projectId: task.projectId,
      title: task.title
    });

    return task;
  }
}

Real-Time синхронизация через WebSocket

// src/presentation/websocket/TaskNamespace.ts
export class TaskNamespace {
  constructor(
    private io: Server,
    private createTaskUseCase: CreateTaskUseCase,
    private updateTaskUseCase: UpdateTaskUseCase
  ) {}

  initialize(): void {
    this.io.on("connection", (socket) => {
      // Подписываемся на проект
      socket.on("subscribe:project", (projectId: string) => {
        socket.join(`project:${projectId}`);
      });

      // Создание новой задачи в real-time
      socket.on("task:create", async (data) => {
        const task = await this.createTaskUseCase.execute(data);
        
        // Отправляем обновление всем в проекте
        this.io.to(`project:${data.projectId}`).emit("task:created", {
          id: task.id,
          title: task.title,
          assignedTo: task.assignedTo
        });
      });

      // Обновление статуса задачи
      socket.on("task:update-status", async (data) => {
        const task = await this.updateTaskUseCase.execute(data);
        
        this.io.to(`project:${task.projectId}`).emit("task:status-changed", {
          taskId: task.id,
          newStatus: task.status,
          updatedAt: new Date()
        });
      });
    });
  }
}

API REST endpoints

// src/presentation/http/TaskController.ts
export class TaskController {
  constructor(private taskService: TaskService) {}

  // GET /api/v1/tasks?projectId=xxx
  async listTasks(req: Request, res: Response) {
    const tasks = await this.taskService.findByProject(req.query.projectId);
    res.json(tasks);
  }

  // POST /api/v1/tasks
  async createTask(req: Request, res: Response) {
    const task = await this.taskService.create(req.body);
    res.status(201).json(task);
  }

  // PATCH /api/v1/tasks/:id
  async updateTask(req: Request, res: Response) {
    const task = await this.taskService.update(req.params.id, req.body);
    res.json(task);
  }

  // DELETE /api/v1/tasks/:id
  async deleteTask(req: Request, res: Response) {
    await this.taskService.delete(req.params.id);
    res.status(204).send();
  }
}

Миграция БД (Goose)

-- migrations/0001_create_tasks_table.sql
CREATE TABLE tasks (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  project_id UUID NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
  title VARCHAR(255) NOT NULL,
  description TEXT,
  status VARCHAR(20) NOT NULL DEFAULT "todo",
  assigned_to UUID REFERENCES users(id),
  due_date TIMESTAMPTZ,
  created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE INDEX idx_tasks_project_id ON tasks(project_id);
CREATE INDEX idx_tasks_assigned_to ON tasks(assigned_to);

Docker Compose для локальной разработки

version: "3.8"

services:
  app:
    build: .
    ports:
      - "3000:3000"
    environment:
      DATABASE_URL: postgresql://user:pass@postgres:5432/tasks
      REDIS_URL: redis://redis:6379
    depends_on:
      - postgres
      - redis
      - rabbitmq

  postgres:
    image: postgres:15
    environment:
      POSTGRES_PASSWORD: password
    volumes:
      - postgres_data:/var/lib/postgresql/data

  redis:
    image: redis:7

  rabbitmq:
    image: rabbitmq:3.12-management

Результаты проекта

  • Обработка 500+ одновременных WebSocket соединений
  • Синхронизация в реальном времени (< 100ms задержка)
  • Полное покрытие тестами (92%)
  • Развертывание на production через Dokku