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

Какие реализовал pet-проект?

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

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

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

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

Pet-проекты как лаборатория для экспериментов

Любой опытный разработчик использует pet-проекты как площадку для экспериментов с новыми технологиями и паттернами. Я реализовал несколько проектов, которые значительно расширили мои компетенции.

1. High-Load Messaging Platform

Один из самых амбициозных проектов — real-time мессенджер с поддержкой 100K+ одновременных подключений.

Технологический стек:

  • Node.js с кластеризацией
  • WebSocket (Socket.io)
  • PostgreSQL + Redis
  • Docker + Kubernetes

Что изучил:

// Оптимизация памяти и CPU
interface ConnectionPool {
  clients: Map<string, ClientSocket>;
  capacity: number;
  currentLoad: number;
}

class HighLoadMessenger {
  private connectionPool: ConnectionPool;
  private messageQueue: Queue;
  private cache: RedisCluster;

  async handleHighLoad(messageCount: number): Promise<void> {
    // Батчинг сообщений для оптимизации БД
    const batch = this.messageQueue.getBatch(1000);
    
    // Параллельное сохранение и кеширование
    await Promise.all([
      this.saveToDB(batch),
      this.cacheInRedis(batch),
      this.broadcastToClients(batch)
    ]);
  }

  // Sharding по user_id для масштабируемости
  getShardId(userId: string): number {
    return hash(userId) % this.shardCount;
  }
}

Результаты:

  • Достигнул 100K RPS на одном сервере
  • 99.9% uptime с zero-downtime deployments
  • Latency message delivery < 50ms

2. GraphQL Federation Gateway

Проект: Федерированный GraphQL API, объединяющий микросервисы

Зачем: Понять, как работает Apollo Federation и как разделить монолитный API.

interface FederatedSchema {
  services: GraphQLService[];
  gateway: ApolloGateway;
}

class GraphQLFederation {
  // Кэширование schema для избежания лишних запросов
  private schemaCache: Map<string, GraphQLSchema> = new Map();

  async composeSchema(): Promise<GraphQLSchema> {
    const schemas = await Promise.all(
      this.services.map(s => this.fetchServiceSchema(s))
    );
    return buildFederatedSchema(schemas);
  }

  // Умная маршрутизация запросов к нужному сервису
  async routeQuery(
    query: string,
    variables: Record<string, any>
  ): Promise<any> {
    const requiredServices = this.analyzeQuery(query);
    return this.executeAcrossServices(requiredServices, query, variables);
  }

  // Batch resolve для оптимизации N+1 проблемы
  async batchResolve(
    parentIds: string[],
    field: string
  ): Promise<any[]> {
    return this.dataLoader.loadMany(parentIds);
  }
}

Что получилось:

  • Разделение монолита на 5 микросервисов
  • Single query endpoint для фронтенда
  • Снижение payload на 40% благодаря GraphQL

3. Distributed Cache Layer

Цель: Разобраться с кешированием в распределенных системах

class DistributedCache {
  private redis: Redis.Cluster;
  private bloomFilter: BloomFilter;
  private consistentHash: ConsistentHash;

  // Cache-Aside паттерн
  async get<T>(
    key: string,
    loader: () => Promise<T>,
    ttl: number = 3600
  ): Promise<T> {
    // Проверка в Bloom filter для быстрого отрицания
    if (this.bloomFilter.has(key)) {
      const cached = await this.redis.get(key);
      if (cached) return JSON.parse(cached);
    }

    // Загрузка из источника
    const data = await loader();
    
    // Сохранение в кеш и Bloom filter
    await this.redis.setex(key, ttl, JSON.stringify(data));
    this.bloomFilter.add(key);
    
    return data;
  }

  // Write-through кеширование для критичных данных
  async set<T>(
    key: string,
    value: T,
    ttl: number = 3600
  ): Promise<void> {
    await this.saveToDatabase(key, value);
    await this.redis.setex(key, ttl, JSON.stringify(value));
    this.bloomFilter.add(key);
  }

  // Инвалидация кеша с использованием consistent hashing
  async invalidate(pattern: string): Promise<void> {
    const nodes = this.consistentHash.getNodes(pattern);
    await Promise.all(
      nodes.map(node => node.redis.eval(invalidateLuaScript, 0, pattern))
    );
  }
}

Уроки:

  • Bloom filters для быстрой проверки отсутствия
  • Consistent hashing для масштабирования кеша
  • Различие между Cache-Aside, Write-Through, Write-Behind

4. API Rate Limiter

Задача: Реализовать sophisticated rate limiting с разными стратегиями

interface RateLimitStrategy {
  name: string;
  window: number;
  limit: number;
}

class AdvancedRateLimiter {
  // Token bucket алгоритм
  async checkTokenBucket(
    userId: string,
    tokensNeeded: number = 1
  ): Promise<boolean> {
    const key = `ratelimit:${userId}`;
    const lua = `
      local current = redis.call('GET', KEYS[1])
      if not current then
        redis.call('SET', KEYS[1], ARGV[1])
        redis.call('EXPIRE', KEYS[1], ARGV[2])
        return 1
      end
      if tonumber(current) >= tonumber(ARGV[1]) then
        return 0
      end
      redis.call('INCR', KEYS[1])
      return 1
    `;
    return await this.redis.eval(lua, 1, key, tokensNeeded, 60);
  }

  // Sliding window с использованием sorted sets
  async checkSlidingWindow(
    userId: string,
    limit: number = 100,
    windowSeconds: number = 60
  ): Promise<boolean> {
    const key = `ratelimit:sliding:${userId}`;
    const now = Date.now();
    const windowStart = now - windowSeconds * 1000;

    const count = await this.redis.zcount(key, windowStart, now);
    
    if (count >= limit) {
      return false;
    }

    await this.redis.zadd(key, now, `${now}-${Math.random()}`);
    await this.redis.expire(key, windowSeconds + 10);
    
    return true;
  }
}

5. Event Sourcing + CQRS

Цель: Изучить advanced паттерны архитектуры

interface Event {
  aggregateId: string;
  type: string;
  timestamp: Date;
  data: Record<string, any>;
  version: number;
}

class EventSourcingStore {
  // Сохранение всей истории событий
  async appendEvent(event: Event): Promise<void> {
    await this.db.query(
      'INSERT INTO events (aggregate_id, type, data, version) VALUES ($1, $2, $3, $4)',
      [event.aggregateId, event.type, JSON.stringify(event.data), event.version]
    );
  }

  // Восстановление состояния через replay
  async getAggregate(aggregateId: string): Promise<any> {
    const events = await this.db.query(
      'SELECT * FROM events WHERE aggregate_id = $1 ORDER BY version',
      [aggregateId]
    );

    let state = {};
    for (const event of events) {
      state = this.applyEvent(state, event);
    }
    return state;
  }

  private applyEvent(state: any, event: Event): any {
    switch (event.type) {
      case 'AccountCreated':
        return { ...state, id: event.data.id, balance: 0 };
      case 'MoneyDeposited':
        return { ...state, balance: state.balance + event.data.amount };
      case 'MoneyWithdrawn':
        return { ...state, balance: state.balance - event.data.amount };
      default:
        return state;
    }
  }
}

6. Load Testing Framework

Разработал собственный фреймворк для стресс-тестирования:

class LoadTester {
  async runLoadTest(config: LoadTestConfig): Promise<LoadTestResults> {
    const results: LoadTestResults = {
      totalRequests: 0,
      successfulRequests: 0,
      failedRequests: 0,
      avgLatency: 0,
      p95Latency: 0,
      p99Latency: 0,
      throughput: 0
    };

    const startTime = Date.now();
    
    // Рампирование нагрузки
    for (let i = 0; i < config.duration; i++) {
      const currentRPS = this.getRampingRPS(i, config);
      await this.sendRequests(currentRPS, results);
    }

    results.throughput = results.totalRequests / 
      ((Date.now() - startTime) / 1000);
    
    return results;
  }
}

Общие результаты

Что получилось:

  • Глубокое понимание performance optimization
  • Опыт работы с distributed systems
  • Умение выбирать правильные паттерны архитектуры
  • Практический опыт с DevOps инструментами

GitHub репозитории с этими проектами содержат примеры кода, документацию и результаты бенчмарков — отличный портфолио для интервью.

Какие реализовал pet-проект? | PrepBro