Skip to content

Commit

Permalink
feat: use a sequence for the version order on postgres
Browse files Browse the repository at this point in the history
  • Loading branch information
bethesque committed Oct 23, 2020
1 parent 884a5b9 commit da497a7
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
up do
if PactBroker::MigrationHelper.postgres?
row = from(:verification_sequence_number).select(:value).limit(1).first
start = row ? row[:value] + 1 : 1
start = row ? row[:value] + 100 : 1
run("CREATE SEQUENCE verification_number_sequence START WITH #{start}")
end
end
Expand Down
20 changes: 20 additions & 0 deletions db/migrations/20201024_create_version_order_sequence.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
require_relative 'migration_helper'

Sequel.migration do
up do
if PactBroker::MigrationHelper.postgres?
row = from(:version_sequence_number).select(:value).limit(1).first
start = row ? row[:value] + 100 : 1
run("CREATE SEQUENCE version_order_sequence START WITH #{start}")
end
end

down do
if PactBroker::MigrationHelper.postgres?
nextval = execute("SELECT nextval('version_order_sequence') as val") { |v| v.first["val"].to_i }
# Add a safety margin!
from(:version_sequence_number).update(value: nextval + 100)
run("DROP SEQUENCE version_order_sequence")
end
end
end
38 changes: 21 additions & 17 deletions lib/pact_broker/versions/sequence.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,27 @@ class Sequence < Sequel::Model(:version_sequence_number)
# The easiest way to implement a cross database compatible sequence.
# Sad, I know.
def next_val
db.transaction do
for_update.first
select_all.update(value: Sequel[:value]+1)
row = first
if row
row.value
else
# The first row should have been created in the migration, so this code
# should only ever be executed in a test context, after we've truncated all the
# tables after a test.
# There would be a risk of a race condition creating two rows if this
# code executed in prod, as I don't think you can lock an empty table
# to prevent another record being inserted.
max_version_order = PactBroker::Domain::Version.max(:order)
value = max_version_order ? max_version_order + 100 : 1
insert(value: value)
value
if PactBroker::Repositories::Helpers.postgres?
db.execute("SELECT nextval('version_order_sequence') as val") { |v| v.first["val"].to_i }
else
db.transaction do
for_update.first
select_all.update(value: Sequel[:value]+1)
row = first
if row
row.value
else
# The first row should have been created in the migration, so this code
# should only ever be executed in a test context, after we've truncated all the
# tables after a test.
# There would be a risk of a race condition creating two rows if this
# code executed in prod, as I don't think you can lock an empty table
# to prevent another record being inserted.
max_version_order = PactBroker::Domain::Version.max(:order)
value = max_version_order ? max_version_order + 100 : 1
insert(value: value)
value
end
end
end
end
Expand Down
1 change: 1 addition & 0 deletions tasks/database.rb
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ def drop_views
def drop_sequences
if psql?
database.run('DROP SEQUENCE verification_number_sequence')
database.run('DROP SEQUENCE version_order_sequence')
end
end

Expand Down

0 comments on commit da497a7

Please sign in to comment.