@Override
  public void receive(ExchangeEvent exchangeEvent) {

    synchronized (exchangeList) {
      exchangeList.addFirst(
          new ExchangeWrapper(serialNumber.incrementAndGet(), exchangeEvent.getExchange()));
      if (exchangeList.size() > testPlan.getExchangeBufferSize()) {
        exchangeList.removeLast();
      }

      eventCompressor.inc();
    }
  }
  private boolean sendBatch(String batchedEvents, IStorage storage) {
    // This is "" if we upload an empty file which we should just skip
    if (batchedEvents.equals("")) {
      removedStorages.add(storage);
      return true;
    }

    byte[] compressedBatchedEvents = compressor.compress(batchedEvents);

    // Write event string
    try {
      if (compressedBatchedEvents != null) {
        sender.sendEvent(compressedBatchedEvents, true);
      } else {
        sender.sendEvent(batchedEvents);
      }
    } catch (IOException e) {
      logger.error(TAG, "Cannot send event: " + e.getMessage());
      int newPeriod = period * 2;
      if (newPeriod > SettingsStore.getCllSettingsAsInt(SettingsStore.Settings.MAXRETRYPERIOD)) {
        // The next scheduled drain is coming soon (~2.5 min so going higher exponentially won't
        // help)
        return false;
      }

      // If we don't remove these then on next call the drain method will end up creating a new
      // empty file by this name.
      storages.removeAll(removedStorages);

      EventQueueWriter r =
          new EventQueueWriter(
              endpoint, storages, clientTelemetry, cllEvents, logger, executorService, newPeriod);
      r.setSender(sender);
      future = executorService.schedule(r, newPeriod, TimeUnit.SECONDS);
      return false; // If we run into an error sending events we just return. This ensures we don't
                    // lose events
    }

    return true;
  }