Skip to content

Commit d3ef5dc

Browse files
authored
Add simple Ruby server example (#17)
fix apache/arrow#40479
1 parent 43bab35 commit d3ef5dc

File tree

4 files changed

+165
-0
lines changed

4 files changed

+165
-0
lines changed
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Licensed to the Apache Software Foundation (ASF) under one
2+
# or more contributor license agreements. See the NOTICE file
3+
# distributed with this work for additional information
4+
# regarding copyright ownership. The ASF licenses this file
5+
# to you under the Apache License, Version 2.0 (the
6+
# "License"); you may not use this file except in compliance
7+
# with the License. You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing,
12+
# software distributed under the License is distributed on an
13+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
# KIND, either express or implied. See the License for the
15+
# specific language governing permissions and limitations
16+
# under the License.
17+
18+
/Gemfile.lock

http/get_simple/ruby/server/Gemfile

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Licensed to the Apache Software Foundation (ASF) under one
2+
# or more contributor license agreements. See the NOTICE file
3+
# distributed with this work for additional information
4+
# regarding copyright ownership. The ASF licenses this file
5+
# to you under the Apache License, Version 2.0 (the
6+
# "License"); you may not use this file except in compliance
7+
# with the License. You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing,
12+
# software distributed under the License is distributed on an
13+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
# KIND, either express or implied. See the License for the
15+
# specific language governing permissions and limitations
16+
# under the License.
17+
18+
source "https://rubygems.org/"
19+
20+
gem "rackup"
21+
gem "red-arrow"

http/get_simple/ruby/server/README.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<!---
2+
Licensed to the Apache Software Foundation (ASF) under one
3+
or more contributor license agreements. See the NOTICE file
4+
distributed with this work for additional information
5+
regarding copyright ownership. The ASF licenses this file
6+
to you under the Apache License, Version 2.0 (the
7+
"License"); you may not use this file except in compliance
8+
with the License. You may obtain a copy of the License at
9+
10+
http://www.apache.org/licenses/LICENSE-2.0
11+
12+
Unless required by applicable law or agreed to in writing,
13+
software distributed under the License is distributed on an
14+
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
KIND, either express or implied. See the License for the
16+
specific language governing permissions and limitations
17+
under the License.
18+
-->
19+
20+
# HTTP GET Arrow Data: Simple Ruby Server Example
21+
22+
This directory contains a minimal example of an HTTP server implemented in Ruby. The server:
23+
1. Creates a list of record batches and populates it with synthesized data.
24+
2. Listens for HTTP GET requests from clients.
25+
3. Upon receiving a request, sends an HTTP 200 response with the body containing an Arrow IPC stream of record batches.
26+
27+
To run this example:
28+
29+
```sh
30+
bundle install
31+
bundle exec rackup --port=8008
32+
```

http/get_simple/ruby/server/config.ru

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
# Licensed to the Apache Software Foundation (ASF) under one
2+
# or more contributor license agreements. See the NOTICE file
3+
# distributed with this work for additional information
4+
# regarding copyright ownership. The ASF licenses this file
5+
# to you under the Apache License, Version 2.0 (the
6+
# "License"); you may not use this file except in compliance
7+
# with the License. You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing,
12+
# software distributed under the License is distributed on an
13+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
# KIND, either express or implied. See the License for the
15+
# specific language governing permissions and limitations
16+
# under the License.
17+
18+
require "arrow"
19+
20+
class ArrowStreamGenerator
21+
def initialize(env)
22+
@env = env
23+
@schema = Arrow::Schema.new(a: :int64,
24+
b: :int64,
25+
c: :int64,
26+
d: :int64)
27+
generate_record_batches
28+
end
29+
30+
def each(&block)
31+
body = RackBody.new(block, need_manual_chunked?)
32+
Gio::RubyOutputStream.open(body) do |gio_output|
33+
Arrow::GIOOutputStream.open(gio_output) do |arrow_output|
34+
Arrow::RecordBatchStreamWriter.open(arrow_output, @schema) do |writer|
35+
@record_batches.each do |record_batch|
36+
writer.write_record_batch(record_batch)
37+
end
38+
end
39+
end
40+
end
41+
end
42+
43+
private
44+
def need_manual_chunked?
45+
not (@env["SERVER_SOFTWARE"] || "").start_with?("WEBrick")
46+
end
47+
48+
def generate_record_batches
49+
n_total_records = 100000000
50+
n_columns = 4
51+
52+
n_rows = 4096
53+
max_int64 = 2 ** 63 - 1
54+
arrays = n_columns.times.collect do
55+
Arrow::Int64Array.new(n_rows.times.collect {rand(max_int64)})
56+
end
57+
58+
record_batch = Arrow::RecordBatch.new(@schema, n_rows, arrays)
59+
@record_batches = [record_batch] * (n_total_records / n_rows)
60+
n_remained_records = n_total_records % n_rows
61+
if n_remained_records
62+
@record_batches << record_batch.slice(0, n_remained_records)
63+
end
64+
end
65+
66+
class RackBody
67+
def initialize(block, need_manual_chunked)
68+
@block = block
69+
@need_manual_chunked = need_manual_chunked
70+
end
71+
72+
def write(buffer)
73+
@block.call("#{buffer.bytesize.to_s(16)}\r\n") if @need_manual_chunked
74+
@block.call(buffer)
75+
@block.call("\r\n") if @need_manual_chunked
76+
buffer.bytesize
77+
end
78+
79+
def flush
80+
end
81+
82+
def close
83+
@block.call("0\r\n\r\n") if @need_manual_chunked
84+
end
85+
end
86+
end
87+
88+
run do |env|
89+
headers = {
90+
"content-type" => "application/vnd.apache.arrow.stream",
91+
"transfer-encoding" => "chunked",
92+
}
93+
[200, headers, ArrowStreamGenerator.new(env)]
94+
end

0 commit comments

Comments
 (0)