pg_db.rb 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  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. Sequel.extension :fiber_concurrency if defined?(Falcon)
  16. prepare_statements
  17. end
  18. def prepare_statements
  19. @world_select = @connection['SELECT id, randomNumber FROM World WHERE id = ?', :$id].prepare(:select, :select_by_id)
  20. @world_update = @connection['UPDATE World SET randomNumber = ? WHERE id = ?', :$random_number, :$id].prepare(:update,
  21. :update_by_id)
  22. @fortune_select = @connection['SELECT id, message FROM Fortune'].prepare(:select, :select_all)
  23. end
  24. def select_random_world
  25. select_world(random_id)
  26. end
  27. def select_world(id)
  28. @world_select.call(id: id).first
  29. end
  30. def validate_count(count)
  31. count = count.to_i
  32. count.clamp(MIN_QUERIES, MAX_QUERIES)
  33. end
  34. def select_promises(count)
  35. count = validate_count(count)
  36. ALL_IDS.sample(count).map do |id|
  37. @connection.synchronize do
  38. @connection['SELECT id, randomNumber FROM World WHERE id = ?', id].async.first
  39. end
  40. end
  41. end
  42. def select_random_numbers(count)
  43. count = validate_count(count)
  44. ALL_IDS.sample(count).map do |id|
  45. @world_random_select.call(randomvalue: random_id, id: id).first
  46. end
  47. end
  48. def select_worlds(count)
  49. count = validate_count(count)
  50. ALL_IDS.sample(count).map do |id|
  51. @world_select.call(id: id).first
  52. end
  53. end
  54. def select_worlds_async(count)
  55. promises = select_promises(count)
  56. promises.map(&:to_hash)
  57. end
  58. def update_worlds(count, async = false)
  59. results = if async
  60. select_worlds_async(count)
  61. else
  62. select_worlds(count)
  63. end
  64. #values = []
  65. ids=[]
  66. sql = String.new("UPDATE world SET randomnumber = CASE id ")
  67. results.each do |r|
  68. r[:randomnumber] = random_id
  69. ids << r[:id]
  70. sql << "when #{r[:id]} then #{r[:randomnumber]} "
  71. end
  72. sql << "ELSE randomnumber END WHERE id IN ( #{ids.join(',')})"
  73. @connection[sql].update
  74. results
  75. end
  76. def select_fortunes
  77. @fortune_select.call
  78. end
  79. def random_id
  80. Random.rand(QUERY_RANGE)
  81. end
  82. end