Sobes.tech
Back to questions
Middle+
6

Реализуйте менеджер событий, который принимает события в произвольном порядке и отправляет их в правильном порядке по ID (начиная с 1, каждый следующий на 1 больше). События могут приходить из нескольких каналов (channel), и порядок должен соблюдаться внутри каждого канала отдельно. Дубликаты событий нужно игнорировать. Для отправки использовать функцию sendEvent.

Companies where asked
А7-Технологии

Answer from AI

sobes.tech AI

Для решения задачи менеджера событий с поддержкой нескольких каналов и упорядочиванием событий по ID внутри каждого канала, можно использовать структуру данных, которая хранит для каждого канала:

  • ожидаемый следующий ID события (начинается с 1)
  • буфер для хранения пришедших событий с ID больше ожидаемого
  • множество для отслеживания уже обработанных ID (чтобы игнорировать дубликаты)

При поступлении нового события:

  1. Проверяем, не был ли он уже обработан (по множеству).
  2. Если ID равен ожидаемому, отправляем событие и увеличиваем ожидаемый ID, затем проверяем буфер, есть ли следующие события подряд, и отправляем их по порядку.
  3. Если ID больше ожидаемого, кладём событие в буфер.
  4. Если ID меньше ожидаемого — игнорируем (дубликат или уже обработано).

Пример на JavaScript:

class EventManager {
  constructor(sendEvent) {
    this.sendEvent = sendEvent;
    this.channels = new Map();
  }

  _getChannelState(channel) {
    if (!this.channels.has(channel)) {
      this.channels.set(channel, {
        nextId: 1,
        buffer: new Map(),
        processed: new Set()
      });
    }
    return this.channels.get(channel);
  }

  receiveEvent(channel, event) {
    const state = this._getChannelState(channel);
    const id = event.id;

    if (state.processed.has(id)) {
      // Дубликат
      return;
    }

    if (id === state.nextId) {
      this.sendEvent(channel, event);
      state.processed.add(id);
      state.nextId++;

      // Проверяем буфер на последовательные события
      while (state.buffer.has(state.nextId)) {
        const nextEvent = state.buffer.get(state.nextId);
        state.buffer.delete(state.nextId);
        this.sendEvent(channel, nextEvent);
        state.processed.add(state.nextId);
        state.nextId++;
      }
    } else if (id > state.nextId) {
      // Сохраняем в буфер
      if (!state.buffer.has(id)) {
        state.buffer.set(id, event);
      }
    }
    // Если id < nextId — игнорируем
  }
}

// Пример использования:
// const manager = new EventManager((channel, event) => console.log(`Send event ${event.id} from ${channel}`));
// manager.receiveEvent('channel1', {id: 2});
// manager.receiveEvent('channel1', {id: 1});
// manager.receiveEvent('channel1', {id: 2}); // дубликат, игнорируется