This is an automated email from the ASF dual-hosted git repository.
ianmcook pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow-experiments.git
The following commit(s) were added to refs/heads/main by this push:
new d3ef5dc Add simple Ruby server example (#17)
d3ef5dc is described below
commit d3ef5dcf62b9a22a737f393bdc2b4c354c449b03
Author: Sutou Kouhei <[email protected]>
AuthorDate: Thu Mar 14 06:54:28 2024 +0900
Add simple Ruby server example (#17)
fix apache/arrow#40479
---
http/get_simple/ruby/server/.gitignore | 18 +++++++
http/get_simple/ruby/server/Gemfile | 21 ++++++++
http/get_simple/ruby/server/README.md | 32 ++++++++++++
http/get_simple/ruby/server/config.ru | 94 ++++++++++++++++++++++++++++++++++
4 files changed, 165 insertions(+)
diff --git a/http/get_simple/ruby/server/.gitignore
b/http/get_simple/ruby/server/.gitignore
new file mode 100644
index 0000000..f07a468
--- /dev/null
+++ b/http/get_simple/ruby/server/.gitignore
@@ -0,0 +1,18 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+/Gemfile.lock
diff --git a/http/get_simple/ruby/server/Gemfile
b/http/get_simple/ruby/server/Gemfile
new file mode 100644
index 0000000..cc981d1
--- /dev/null
+++ b/http/get_simple/ruby/server/Gemfile
@@ -0,0 +1,21 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+source "https://rubygems.org/"
+
+gem "rackup"
+gem "red-arrow"
diff --git a/http/get_simple/ruby/server/README.md
b/http/get_simple/ruby/server/README.md
new file mode 100644
index 0000000..1e2cf88
--- /dev/null
+++ b/http/get_simple/ruby/server/README.md
@@ -0,0 +1,32 @@
+<!---
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+
+# HTTP GET Arrow Data: Simple Ruby Server Example
+
+This directory contains a minimal example of an HTTP server implemented in
Ruby. The server:
+1. Creates a list of record batches and populates it with synthesized data.
+2. Listens for HTTP GET requests from clients.
+3. Upon receiving a request, sends an HTTP 200 response with the body
containing an Arrow IPC stream of record batches.
+
+To run this example:
+
+```sh
+bundle install
+bundle exec rackup --port=8008
+```
diff --git a/http/get_simple/ruby/server/config.ru
b/http/get_simple/ruby/server/config.ru
new file mode 100644
index 0000000..cbc7416
--- /dev/null
+++ b/http/get_simple/ruby/server/config.ru
@@ -0,0 +1,94 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+require "arrow"
+
+class ArrowStreamGenerator
+ def initialize(env)
+ @env = env
+ @schema = Arrow::Schema.new(a: :int64,
+ b: :int64,
+ c: :int64,
+ d: :int64)
+ generate_record_batches
+ end
+
+ def each(&block)
+ body = RackBody.new(block, need_manual_chunked?)
+ Gio::RubyOutputStream.open(body) do |gio_output|
+ Arrow::GIOOutputStream.open(gio_output) do |arrow_output|
+ Arrow::RecordBatchStreamWriter.open(arrow_output, @schema) do |writer|
+ @record_batches.each do |record_batch|
+ writer.write_record_batch(record_batch)
+ end
+ end
+ end
+ end
+ end
+
+ private
+ def need_manual_chunked?
+ not (@env["SERVER_SOFTWARE"] || "").start_with?("WEBrick")
+ end
+
+ def generate_record_batches
+ n_total_records = 100000000
+ n_columns = 4
+
+ n_rows = 4096
+ max_int64 = 2 ** 63 - 1
+ arrays = n_columns.times.collect do
+ Arrow::Int64Array.new(n_rows.times.collect {rand(max_int64)})
+ end
+
+ record_batch = Arrow::RecordBatch.new(@schema, n_rows, arrays)
+ @record_batches = [record_batch] * (n_total_records / n_rows)
+ n_remained_records = n_total_records % n_rows
+ if n_remained_records
+ @record_batches << record_batch.slice(0, n_remained_records)
+ end
+ end
+
+ class RackBody
+ def initialize(block, need_manual_chunked)
+ @block = block
+ @need_manual_chunked = need_manual_chunked
+ end
+
+ def write(buffer)
+ @block.call("#{buffer.bytesize.to_s(16)}\r\n") if @need_manual_chunked
+ @block.call(buffer)
+ @block.call("\r\n") if @need_manual_chunked
+ buffer.bytesize
+ end
+
+ def flush
+ end
+
+ def close
+ @block.call("0\r\n\r\n") if @need_manual_chunked
+ end
+ end
+end
+
+run do |env|
+ headers = {
+ "content-type" => "application/vnd.apache.arrow.stream",
+ "transfer-encoding" => "chunked",
+ }
+ [200, headers, ArrowStreamGenerator.new(env)]
+end