pg_db.rb 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. # frozen_string_literal: true
  2. require 'sequel'
  3. if RUBY_PLATFORM == 'java'
  4. require 'jdbc/postgres'
  5. Jdbc::Postgres.load_driver
  6. end
  7. class PgDb
  8. QUERY_RANGE = (1..10_000).freeze # range of IDs in the Fortune DB
  9. ALL_IDS = QUERY_RANGE.to_a # enumeration of all the IDs in fortune DB
  10. MIN_QUERIES = 1 # min number of records that can be retrieved
  11. MAX_QUERIES = 500 # max number of records that can be retrieved
  12. attr_reader :connection
  13. def initialize(connection_string = nil, max_connections = 512)
  14. @connection = Sequel.connect(connection_string, max_connections: max_connections, sql_log_level: :warning)
  15. if defined?(Falcon)
  16. Sequel.extension :fiber_concurrency if defined?(Falcon)
  17. else
  18. @connection.extension :async_thread_pool
  19. end
  20. prepare_statements
  21. end
  22. def prepare_statements
  23. @world_select = @connection['SELECT id, randomNumber FROM World WHERE id = ?', :$id].prepare(:select, :select_by_id)
  24. @world_update = @connection['UPDATE World SET randomNumber = ? WHERE id = ?', :$random_number, :$id].prepare(:update,
  25. :update_by_id)
  26. @fortune_select = @connection['SELECT id, message FROM Fortune'].prepare(:select, :select_all)
  27. end
  28. def select_random_world
  29. select_world(random_id)
  30. end
  31. def select_world(id)
  32. @world_select.call(id: id).first
  33. end
  34. def validate_count(count)
  35. count = count.to_i
  36. count.clamp(MIN_QUERIES, MAX_QUERIES)
  37. end
  38. def select_promises(count)
  39. count = validate_count(count)
  40. ALL_IDS.sample(count).map do |id|
  41. @connection.synchronize do
  42. @connection['SELECT id, randomNumber FROM World WHERE id = ?', id].async.first
  43. end
  44. end
  45. end
  46. def select_random_numbers(count)
  47. count = validate_count(count)
  48. ALL_IDS.sample(count).map do |id|
  49. @world_random_select.call(randomvalue: random_id, id: id).first
  50. end
  51. end
  52. def select_worlds(count)
  53. count = validate_count(count)
  54. ALL_IDS.sample(count).map do |id|
  55. @world_select.call(id: id).first
  56. end
  57. end
  58. def select_worlds_async(count)
  59. promises = select_promises(count)
  60. promises.map(&:to_hash)
  61. end
  62. def update_worlds(count, async = false)
  63. results = if async
  64. select_worlds_async(count)
  65. else
  66. select_worlds(count)
  67. end
  68. #values = []
  69. ids=[]
  70. sql = String.new("UPDATE world SET randomnumber = CASE id ")
  71. results.each do |r|
  72. r[:randomnumber] = random_id
  73. ids << r[:id]
  74. sql << "when #{r[:id]} then #{r[:randomnumber]} "
  75. end
  76. sql << "ELSE randomnumber END WHERE id IN ( #{ids.join(',')})"
  77. @connection[sql].update
  78. results
  79. end
  80. def select_fortunes
  81. @fortune_select.call
  82. end
  83. def random_id
  84. Random.rand(QUERY_RANGE)
  85. end
  86. end