Retrieve events
  POST body should contain a JSON encoded version of:
    { namespace: namespace_name (optional),
      stream : stream_name,
      start_time : starting_time_as_kronos_time,
      end_time : ending_time_as_kronos_time,
      start_id : only_return_events_with_id_greater_than_me,
      limit: optional_maximum_number_of_events,
      order: ResultOrder.ASCENDING or ResultOrder.DESCENDING (default
             ResultOrder.ASCENDING)
    }
  Either start_time or start_id should be specified. If a retrieval breaks
  while returning results, you can send another retrieval request and specify
  start_id as the last id that you saw. Kronos will only return events that
  occurred after the event with that id.

def get_events(environment, start_response, headers):
  """
  Retrieve events
  POST body should contain a JSON encoded version of:
    { namespace: namespace_name (optional),
      stream : stream_name,
      start_time : starting_time_as_kronos_time,
      end_time : ending_time_as_kronos_time,
      start_id : only_return_events_with_id_greater_than_me,
      limit: optional_maximum_number_of_events,
      order: ResultOrder.ASCENDING or ResultOrder.DESCENDING (default
             ResultOrder.ASCENDING)
    }
  Either start_time or start_id should be specified. If a retrieval breaks
  while returning results, you can send another retrieval request and specify
  start_id as the last id that you saw. Kronos will only return events that
  occurred after the event with that id.
  """
  request_json = environment['json']
  try:
    stream = request_json['stream']
    validate_stream(stream)
  except Exception, e:
    log.exception('get_events: stream validation failed for `%s`',
                  request_json.get('stream'))
    start_response('400 Bad Request', headers)
    yield marshal.dumps({ERRORS_FIELD: [repr(e)],
                         SUCCESS_FIELD: False})
    return

  namespace = request_json.get('namespace', settings.default_namespace)
  limit = int(request_json.get('limit', MAX_LIMIT))
  if limit <= 0:
    events = []
  else:
    backend, configuration = router.backend_to_retrieve(namespace, stream)
    events = backend.retrieve(
      namespace,
      stream,
      long(request_json.get('start_time', 0)),
      long(request_json['end_time']),
      request_json.get('start_id'),
      configuration,
      order=request_json.get('order', ResultOrder.ASCENDING),
      limit=limit)

  start_response('200 OK', headers)

  string_buffer = StringIO()
  for event in events:
    # TODO(usmanm): Once all backends start respecting limit, remove this check.
    if limit <= 0:
      break
    if string_buffer.tell() >= settings.node.flush_size:
      yield string_buffer.getvalue()
      string_buffer.close()
      string_buffer = StringIO()
    string_buffer.write(event)
    string_buffer.write('\r\n')
    limit -= 1
  if string_buffer.tell():
    yield string_buffer.getvalue()
  string_buffer.close()
  yield ''