Sobes.tech
Middle+

Implement an event manager that accepts events in arbitrary order and sends them in the correct order by ID (starting from 1, each next one is 1 greater). Events can come from multiple channels, and order must be maintained within each channel separately. Ignore duplicate events. Use the sendEvent function for sending.

sobes.tech AI

Answer from AI

To solve the event manager task with support for multiple channels and ordering events by ID within each channel, you can use a data structure that stores for each channel:

  • the expected next event ID (starting from 1)
  • a buffer for storing incoming events with IDs greater than the expected
  • a set to track already processed IDs (to ignore duplicates)

When a new event arrives:

  1. Check if it has already been processed (using the set).
  2. If the ID equals the expected, send the event and increment the expected ID, then check the buffer for subsequent events and send them in order.
  3. If the ID is greater than the expected, put the event in the buffer.
  4. If the ID is less than the expected — ignore it (duplicate or already processed).

Example in 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)) {
      // Duplicate
      return;
    }

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

      // Check buffer for sequential events
      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) {
      // Save in buffer
      if (!state.buffer.has(id)) {
        state.buffer.set(id, event);
      }
    }
    // If id < nextId — ignore
  }
}

// Usage example:
// 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}); // duplicate, ignored
Implement an event manager that accepts events in… - sobes.tech