pg_db.rb 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  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. @world_select.call(id: random_id)[0]
  30. end
  31. def select_world(id)
  32. @world_select.call(id: id)[0]
  33. end
  34. def validate_count(count)
  35. count = count.to_i
  36. if count < MIN_QUERIES
  37. MIN_QUERIES
  38. elsif count > MAX_QUERIES
  39. MAX_QUERIES
  40. else
  41. count
  42. end
  43. end
  44. def select_promises(count)
  45. count = validate_count(count)
  46. promises = []
  47. count.times do
  48. @connection.synchronize do
  49. promises << @connection['SELECT id, randomNumber FROM World WHERE id = ?', random_id].async.first
  50. end
  51. end
  52. promises
  53. end
  54. def select_random_numbers(count)
  55. count = validate_count(count)
  56. results = []
  57. count.times do
  58. results << @world_random_select.call(randomvalue: random_id, id: random_id)[0]
  59. end
  60. results
  61. end
  62. def select_worlds(count)
  63. count = validate_count(count)
  64. results = []
  65. count.times do
  66. results << @world_select.call(id: random_id)[0]
  67. end
  68. results
  69. end
  70. def select_worlds_async(count)
  71. promises = select_promises(count)
  72. results = []
  73. promises.each do |p|
  74. results << p.to_hash
  75. end
  76. results
  77. end
  78. def update_worlds(count, async = false)
  79. results = if async
  80. select_worlds_async(count)
  81. else
  82. select_worlds(count)
  83. end
  84. #values = []
  85. ids=[]
  86. sql = String.new("UPDATE world SET randomnumber = CASE id ")
  87. results.each do |r|
  88. r[:randomnumber] = random_id
  89. ids << r[:id]
  90. sql << "when #{r[:id]} then #{r[:randomnumber]} "
  91. end
  92. sql << "ELSE randomnumber END WHERE id IN ( #{ids.join(',')})"
  93. @connection[sql].update
  94. results
  95. end
  96. def select_fortunes
  97. @fortune_select.call
  98. end
  99. def random_id
  100. Random.rand(QUERY_RANGE)
  101. end
  102. end