Browse Source

[ruby/hanami] Add support for queries and updates tests (#9657)

Petrik de Heus 5 months ago
parent
commit
8501d7efa0

+ 3 - 0
frameworks/Ruby/hanami/.env

@@ -0,0 +1,3 @@
+HANAMI_ENV=production
+HANAMI_PORT=8080
+DATABASE_URL=postgres://benchmarkdbuser:benchmarkdbpass@tfb-database:5432/hello_world

+ 166 - 0
frameworks/Ruby/hanami/Gemfile.lock

@@ -0,0 +1,166 @@
+GEM
+  remote: https://rubygems.org/
+  specs:
+    bigdecimal (3.1.9)
+    concurrent-ruby (1.3.4)
+    dry-auto_inject (1.1.0)
+      dry-core (~> 1.1)
+      zeitwerk (~> 2.6)
+    dry-cli (1.2.0)
+    dry-configurable (1.3.0)
+      dry-core (~> 1.1)
+      zeitwerk (~> 2.6)
+    dry-core (1.1.0)
+      concurrent-ruby (~> 1.0)
+      logger
+      zeitwerk (~> 2.6)
+    dry-events (1.1.0)
+      concurrent-ruby (~> 1.0)
+      dry-core (~> 1.1)
+    dry-files (1.1.0)
+    dry-inflector (1.2.0)
+    dry-initializer (3.2.0)
+    dry-logger (1.0.4)
+    dry-logic (1.6.0)
+      bigdecimal
+      concurrent-ruby (~> 1.0)
+      dry-core (~> 1.1)
+      zeitwerk (~> 2.6)
+    dry-monitor (1.0.1)
+      dry-configurable (~> 1.0, < 2)
+      dry-core (~> 1.0, < 2)
+      dry-events (~> 1.0, < 2)
+    dry-schema (1.13.4)
+      concurrent-ruby (~> 1.0)
+      dry-configurable (~> 1.0, >= 1.0.1)
+      dry-core (~> 1.0, < 2)
+      dry-initializer (~> 3.0)
+      dry-logic (>= 1.4, < 2)
+      dry-types (>= 1.7, < 2)
+      zeitwerk (~> 2.6)
+    dry-struct (1.7.0)
+      dry-core (~> 1.1)
+      dry-types (~> 1.8)
+      ice_nine (~> 0.11)
+      zeitwerk (~> 2.6)
+    dry-system (1.2.0)
+      dry-auto_inject (~> 1.1)
+      dry-configurable (~> 1.3)
+      dry-core (~> 1.1)
+      dry-inflector (~> 1.1)
+    dry-transformer (1.0.1)
+      zeitwerk (~> 2.6)
+    dry-types (1.8.0)
+      bigdecimal (~> 3.0)
+      concurrent-ruby (~> 1.0)
+      dry-core (~> 1.0)
+      dry-inflector (~> 1.0)
+      dry-logic (~> 1.4)
+      zeitwerk (~> 2.6)
+    dry-validation (1.10.0)
+      concurrent-ruby (~> 1.0)
+      dry-core (~> 1.0, < 2)
+      dry-initializer (~> 3.0)
+      dry-schema (>= 1.12, < 2)
+      zeitwerk (~> 2.6)
+    hanami (2.2.1)
+      bundler (>= 1.16, < 3)
+      dry-configurable (~> 1.0, >= 1.2.0, < 2)
+      dry-core (~> 1.0, < 2)
+      dry-inflector (~> 1.0, >= 1.1.0, < 2)
+      dry-logger (~> 1.0, < 2)
+      dry-monitor (~> 1.0, >= 1.0.1, < 2)
+      dry-system (~> 1.1)
+      hanami-cli (~> 2.2.1)
+      hanami-utils (~> 2.2)
+      json (>= 2.7.2)
+      zeitwerk (~> 2.6)
+    hanami-cli (2.2.1)
+      bundler (~> 2.1)
+      dry-cli (~> 1.0, >= 1.1.0)
+      dry-files (~> 1.0, >= 1.0.2, < 2)
+      dry-inflector (~> 1.0, < 2)
+      rake (~> 13.0)
+      zeitwerk (~> 2.6)
+    hanami-controller (2.1.0)
+      dry-configurable (~> 1.0, < 2)
+      dry-core (~> 1.0)
+      hanami-utils (~> 2.1)
+      rack (~> 2.0)
+      zeitwerk (~> 2.6)
+    hanami-router (2.1.0)
+      mustermann (~> 3.0)
+      mustermann-contrib (~> 3.0)
+      rack (~> 2.0)
+    hanami-utils (2.2.0)
+      concurrent-ruby (~> 1.0)
+      dry-core (~> 1.0, < 2)
+      dry-transformer (~> 1.0, < 2)
+    hanami-validations (2.1.0)
+      dry-validation (>= 1.10, < 2)
+      zeitwerk (~> 2.6.0)
+    hansi (0.2.1)
+    ice_nine (0.11.2)
+    json (2.9.1)
+    logger (1.6.4)
+    mustermann (3.0.3)
+      ruby2_keywords (~> 0.0.1)
+    mustermann-contrib (3.0.3)
+      hansi (~> 0.2.0)
+      mustermann (= 3.0.3)
+    nio4r (2.7.4)
+    pg (1.5.9)
+    puma (6.5.0)
+      nio4r (~> 2.0)
+    rack (2.2.9)
+    rake (13.2.1)
+    rom (5.3.2)
+      rom-changeset (~> 5.3, >= 5.3.0)
+      rom-core (~> 5.3, >= 5.3.2)
+      rom-repository (~> 5.3, >= 5.3.0)
+    rom-changeset (5.3.0)
+      dry-core (~> 1.0)
+      rom-core (~> 5.3)
+      transproc (~> 1.0, >= 1.1.0)
+    rom-core (5.3.2)
+      concurrent-ruby (~> 1.1)
+      dry-configurable (~> 1.0)
+      dry-core (~> 1.0)
+      dry-inflector (~> 1.0)
+      dry-initializer (~> 3.0, >= 3.0.1)
+      dry-struct (~> 1.0)
+      dry-types (~> 1.6)
+      transproc (~> 1.0, >= 1.1.0)
+    rom-repository (5.3.0)
+      dry-core (~> 1.0)
+      dry-initializer (~> 3.0, >= 3.0.1)
+      rom-core (~> 5.3, >= 5.3.0)
+    rom-sql (3.6.5)
+      dry-core (~> 1.0)
+      dry-types (~> 1.0)
+      rom (~> 5.2, >= 5.2.1)
+      sequel (>= 4.49)
+    ruby2_keywords (0.0.5)
+    sequel (5.88.0)
+      bigdecimal
+    transproc (1.1.1)
+    zeitwerk (2.6.18)
+
+PLATFORMS
+  ruby
+  x86_64-darwin-23
+
+DEPENDENCIES
+  dry-types (~> 1.0, >= 1.6.1)
+  hanami (~> 2.0)
+  hanami-controller (~> 2.0)
+  hanami-router (~> 2.0)
+  hanami-validations (~> 2.0)
+  pg
+  puma
+  rake
+  rom (~> 5.3)
+  rom-sql (~> 3.6)
+
+BUNDLED WITH
+   2.5.16

+ 1 - 1
frameworks/Ruby/hanami/app/actions/db/index.rb

@@ -8,7 +8,7 @@ module HelloWorld
         include Deps["persistence.rom"]
         include Deps["persistence.rom"]
 
 
         def handle(*, response)
         def handle(*, response)
-          world = rom.relations[:World].where(id: random_id).one
+          world = rom.relations[:World].by_pk(random_id).one
           response.headers['Server'] = 'hanami'
           response.headers['Server'] = 'hanami'
           response.headers['Date'] = Time.now.httpdate
           response.headers['Date'] = Time.now.httpdate
           response.format = :json
           response.format = :json

+ 32 - 0
frameworks/Ruby/hanami/app/actions/queries/index.rb

@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+module HelloWorld
+  module Actions
+    module Queries
+      class Index < HelloWorld::Action
+        QUERY_RANGE = 1..10_000    # range of IDs in the Fortune DB
+        ALL_IDS = QUERY_RANGE.to_a # enumeration of all the IDs in fortune DB
+        MIN_QUERIES = 1            # min number of records that can be retrieved
+        MAX_QUERIES = 500          # max number of records that can be retrieved
+
+        include Deps["persistence.rom"]
+
+        def handle(request, response)
+          worlds = ALL_IDS.sample(queries(request)).map do |id|
+            rom.relations[:World].by_pk(id).one
+          end
+          response.headers['Server'] = 'hanami'
+          response.headers['Date'] = Time.now.httpdate
+          response.format = :json
+          response.body = worlds.to_json
+        end
+
+        private
+
+        def queries(request)
+          request.params[:queries].to_i.clamp(MIN_QUERIES, MAX_QUERIES)
+        end
+      end
+    end
+  end
+end

+ 42 - 0
frameworks/Ruby/hanami/app/actions/updates/index.rb

@@ -0,0 +1,42 @@
+# frozen_string_literal: true
+
+module HelloWorld
+  module Actions
+    module Updates
+      class Index < HelloWorld::Action
+        QUERY_RANGE = 1..10_000    # range of IDs in the Fortune DB
+        ALL_IDS = QUERY_RANGE.to_a # enumeration of all the IDs in fortune DB
+        MIN_QUERIES = 1            # min number of records that can be retrieved
+        MAX_QUERIES = 500          # max number of records that can be retrieved
+
+        include Deps["persistence.rom"]
+
+        def handle(request, response)
+          worlds = ALL_IDS.sample(queries(request)).map do |id|
+            world = rom.relations[:World].by_pk(id)
+            world_struct = world.one
+            new_value = random_id
+            new_value = random_id while new_value == world_struct[:randomnumber]
+            world_struct[:randomnumber] = new_value
+            world.command(:update).call(randomnumber: world_struct[:randomnumber])
+            world_struct
+          end
+          response.headers['Server'] = 'hanami'
+          response.headers['Date'] = Time.now.httpdate
+          response.format = :json
+          response.body = worlds.to_json
+        end
+
+        private
+
+        def queries(request)
+          request.params[:queries].to_i.clamp(MIN_QUERIES, MAX_QUERIES)
+        end
+
+        def random_id
+          Random.rand(QUERY_RANGE)
+        end
+      end
+    end
+  end
+end

+ 3 - 1
frameworks/Ruby/hanami/benchmark_config.json

@@ -2,8 +2,10 @@
   "framework": "hanami",
   "framework": "hanami",
   "tests": [{
   "tests": [{
     "default": {
     "default": {
-      "db_url": "/db",
       "json_url": "/json",
       "json_url": "/json",
+      "db_url": "/db",
+      "query_url": "/queries?queries=",
+      "update_url": "/updates?queries=",
       "plaintext_url": "/plaintext",
       "plaintext_url": "/plaintext",
       "port": 8080,
       "port": 8080,
       "approach": "Realistic",
       "approach": "Realistic",

+ 8 - 6
frameworks/Ruby/hanami/config/providers/persistence.rb

@@ -5,12 +5,10 @@ Hanami.app.register_provider :persistence, namespace: true do
     require_relative '../auto_tune'
     require_relative '../auto_tune'
     num_workers, num_threads = auto_tune
     num_workers, num_threads = auto_tune
 
 
-    opts = {}
-
-    if (threads = num_threads) > 1
-      opts[:max_connections] = (2 * Math.log(threads)).floor
-      opts[:pool_timeout] = 10
-    end
+    opts = {
+      max_connections: 3,
+      pool_timeout: 10
+    }
     config = ROM::Configuration.new(:sql, target["settings"].database_url, opts)
     config = ROM::Configuration.new(:sql, target["settings"].database_url, opts)
 
 
     register "config", config
     register "config", config
@@ -27,4 +25,8 @@ Hanami.app.register_provider :persistence, namespace: true do
 
 
     register "rom", ROM.container(config)
     register "rom", ROM.container(config)
   end
   end
+
+  stop do
+    target["persistence.rom"].disconnect
+  end
 end
 end

+ 1 - 1
frameworks/Ruby/hanami/config/puma.rb

@@ -5,7 +5,7 @@ require_relative 'auto_tune'
 num_workers, num_threads = auto_tune
 num_workers, num_threads = auto_tune
 
 
 workers num_workers
 workers num_workers
-threads num_threads, num_threads
+threads 3, 3
 
 
 port        ENV.fetch("HANAMI_PORT", 2300)
 port        ENV.fetch("HANAMI_PORT", 2300)
 environment ENV.fetch("HANAMI_ENV", "development")
 environment ENV.fetch("HANAMI_ENV", "development")

+ 2 - 0
frameworks/Ruby/hanami/config/routes.rb

@@ -4,6 +4,8 @@ module HelloWorld
   class Routes < Hanami::Routes
   class Routes < Hanami::Routes
     get "/db", to: "db.index"
     get "/db", to: "db.index"
     get "/json", to: "json.index"
     get "/json", to: "json.index"
+    get "/updates", to: "updates.index"
     get "/plaintext", to: "plaintext.index"
     get "/plaintext", to: "plaintext.index"
+    get "/queries", to: "queries.index"
   end
   end
 end
 end

+ 1 - 4
frameworks/Ruby/hanami/hanami.dockerfile

@@ -7,15 +7,12 @@ RUN apt-get update && \
     apt-get install -y --no-install-recommends libjemalloc2
     apt-get install -y --no-install-recommends libjemalloc2
 ENV LD_PRELOAD=libjemalloc.so.2
 ENV LD_PRELOAD=libjemalloc.so.2
 
 
+ADD ./ /hanami
 WORKDIR /hanami
 WORKDIR /hanami
 
 
-COPY Gemfile  ./
-
 ENV BUNDLE_FORCE_RUBY_PLATFORM=true
 ENV BUNDLE_FORCE_RUBY_PLATFORM=true
 RUN bundle install --jobs=8
 RUN bundle install --jobs=8
 
 
-COPY . .
-
 EXPOSE 8080
 EXPOSE 8080
 
 
 ENV HANAMI_ENV=production
 ENV HANAMI_ENV=production