Skip to content

Commit

Permalink
Make headers for batched records shorter (#298)
Browse files Browse the repository at this point in the history
* make headers for batched records shorter

* sort labels

* update docs

* update CHANGELOG
  • Loading branch information
atimin committed Jun 21, 2023
1 parent eabcd43 commit 12c6dce
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 27 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- `HEAD /api/v1/b/:bucket_name/:entry_name` and `HEAD /api/v1/b/:bucket_name/:entry_name/batch`
endpoints, [PR-296]https://github.com/reductstore/reductstore/pull/296)

### Changed

- Concise format for headers in `GET /api/v1/:bucket/:entry/batch` response, [PR-298](https://github.com/reductstore/reductstore/pull/298)

## [1.4.0] - 2023-06-09

### Fixed
Expand Down
8 changes: 4 additions & 4 deletions api_tests/entry_api_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -420,8 +420,8 @@ def test_read_batched_records(base_url, session, bucket, method, expected_conten
assert resp.content == expected_content
assert resp.headers['content-type'] == 'application/octet-stream'
assert resp.headers['content-length'] == '20'
assert resp.headers['x-reduct-time-1000'] == 'content-length=10,content-type=application/octet-stream'
assert resp.headers['x-reduct-time-1100'] == 'content-length=10,content-type=text/plain,label-x="[a,b]"'
assert resp.headers['x-reduct-time-1000'] == '10,application/octet-stream'
assert resp.headers['x-reduct-time-1100'] == '10,text/plain,x="[a,b]"'
assert resp.headers['x-reduct-last'] == 'true'


Expand All @@ -437,12 +437,12 @@ def test_read_batched_max_header_size(base_url, session, bucket):

resp = session.get(f'{base_url}/b/{bucket}/entry/batch?q={query_id}')
assert resp.status_code == 200
assert sum(header.startswith('x-reduct-time-') for header in resp.headers) == 84
assert sum(header.startswith('x-reduct-time-') for header in resp.headers) == 86
assert resp.headers['x-reduct-last'] == 'false'

resp = session.get(f'{base_url}/b/{bucket}/entry/batch?q={query_id}')
assert resp.status_code == 200
assert sum(header.startswith('x-reduct-time-') for header in resp.headers) == 16
assert sum(header.startswith('x-reduct-time-') for header in resp.headers) == 14
assert resp.headers['x-reduct-last'] == 'true'

resp = session.get(f'{base_url}/b/{bucket}/entry/batch?q={query_id}')
Expand Down
9 changes: 6 additions & 3 deletions docs/http-api/entry-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ A UNIX timestamp in microseconds. If it is empty, the latest record is returned.

{% swagger method="head" path="" baseUrl="/api/v1/b/:bucket_name/:entry_name " summary="Get only meta information about record" %}
{% swagger-description %}
The endpoint works exactly as
The endpoint works exactly as

`GET /api/v1/b/:bucket_name/:entry_name`

Expand All @@ -146,7 +146,10 @@ The endpoint works exactly as
{% swagger-description %}
Since version 1.5, ReductStore provides a way to read a multiple records in a request. This can improve latency when you have many small records to read. The endpoint sorts all the records by time and concatenates them into a blob and sends it in the body. The meta information is sent for each record as a separate header `x-reduct-time-<timestamp>` which has a value as a CSV row. An example:

`x-reduct-time-192312381273: content-type=text/plain,content-length=100,label-x=y,label-a="[a,b]"`
`x-reduct-time-192312381273: 100,text/plain,x=y,a="[a,b]"`

The first value is content-length, the second one is content-type, then labels as key=value pairs. If there is a comma in the value, it is escaped with double quotes.

{% endswagger-description %}

{% swagger-parameter in="path" name=":bucket_name" required="true" %}
Expand Down Expand Up @@ -190,7 +193,7 @@ Name of entry

{% swagger method="head" path="" baseUrl="/api/v1/b/:bucket_name/:entry_name/batch " summary="Get only meta information in bulk" %}
{% swagger-description %}
The endpoint works exactly as
The endpoint works exactly as

`GET /api/v1/b/:bucket_name/:entry_name/batch`

Expand Down
37 changes: 17 additions & 20 deletions src/http_frontend/entry_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,24 +120,24 @@ fn fetch_and_response_batched_records(
let name = HeaderName::from_str(&format!("x-reduct-time-{}", reader.timestamp())).unwrap();

let mut meta_data = vec![
format!("content-length={}", reader.content_length()),
format!("content-type={}", reader.content_type()),
reader.content_length().to_string(),
reader.content_type().clone(),
];
meta_data.append(
&mut reader
.labels()
.iter()
.map(|(k, v)| {
if v.contains(",") {
format!("label-{}=\"{}\"", k, v)
} else {
format!("label-{}={}", k, v)
}
})
.collect(),
);
meta_data.sort();

let mut labels: Vec<String> = reader
.labels()
.iter()
.map(|(k, v)| {
if v.contains(",") {
format!("{}=\"{}\"", k, v)
} else {
format!("{}={}", k, v)
}
})
.collect();
labels.sort();

meta_data.append(&mut labels);
let value: HeaderValue = meta_data.join(",").parse().unwrap();

(name, value)
Expand Down Expand Up @@ -819,10 +819,7 @@ mod tests {
.into_response();

let headers = response.headers();
assert_eq!(
headers["x-reduct-time-0"],
"content-length=6,content-type=text/plain,label-b=\"[a,b]\",label-x=y"
);
assert_eq!(headers["x-reduct-time-0"], "6,text/plain,b=\"[a,b]\",x=y");
assert_eq!(headers["content-type"], "application/octet-stream");
assert_eq!(headers["content-length"], "6");
assert_eq!(headers["x-reduct-last"], "true");
Expand Down

0 comments on commit 12c6dce

Please sign in to comment.