Skip to content

Instantly share code, notes, and snippets.

@Mardiniii
Last active May 24, 2018 18:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Mardiniii/9886621bbd6f31c16b64d7424ec844a3 to your computer and use it in GitHub Desktop.
Save Mardiniii/9886621bbd6f31c16b64d7424ec844a3 to your computer and use it in GitHub Desktop.
1st approach to solve data replication problem using Ruby.
require 'minitest/autorun'
# Problem
# https://softwareengineering.stackexchange.com/questions/153806/conflict-resolution-for-two-way-sync
# interface DB {
# String Get(String)
# void Set(String, String)
# []String Keys()
#
# // we can add extra methods as we sit fit
# }
#
# We want to implement the replicate method
#
# db1.set("a", "a")
# db2.set("b", "b")
# replicate(db1, db2)
# assert db2.get("a") == "a"
# assert db1.get("b") == "b"
class Database
attr_accessor :records
attr_reader :logs
def initialize
@records = {}
@logs = {} # key, last_set
end
def get(key)
@records[key]
end
def set(key, value)
@records[key] = value
@logs[key] = Time.now
end
def size
@records.count
end
def keys
@records.keys
end
end
def replicate(db1, db2)
db = Database.new
db1_records = db1.records
db2_records = db2.records
db1_keys = db1.records.keys
db2_keys = db2.records.keys
db1_records.each do |k, v|
if db2_records.keys.include?(k)
value = db1.logs[k] > db2.logs[k] ? v : db2.get(k)
db.set(k, value)
else
db.set(k, v)
end
end
db2_records.each do |k, v|
unless db1_records.keys.include?(k)
db.set(k, v)
end
end
db1.records = db.records
db2.records = db.records
end
# Test Database class
class TestDatabase < Minitest::Test
def setup
@db = Database.new
end
def test_that_database_start_with_empty_records
assert_equal 0, @db.size, "Database size is not 0"
end
def test_that_database_can_set_and_get_key
@db.set("foo", "bar")
assert_equal "bar", @db.records["foo"], "Value wasn't stored"
assert_equal "bar", @db.get("foo"), "Value wasn't fetched"
assert_equal 1, @db.size, "Database size is incorrect"
end
def test_that_database_returns_nil_for_non_existing_key
assert_nil @db.get("foo"), "Not nil value returned for non existing key"
end
def test_that_database_keys_return_keys
@db.set("hi", "bye")
@db.set("salt", "sugar")
@db.set("black", "white")
assert_equal ["hi", "salt", "black"], @db.keys, "Wrong existing keys returned"
end
end
# Test replicate method
class TestReplicate < Minitest::Test
def setup
@db1 = Database.new
@db2 = Database.new
@db1.set("a", "a")
@db2.set("b", "b")
end
def test_that_database_are_replicated_without_conflicts
replicate(@db1, @db2)
assert_equal "b", @db1.get("b"), "Database one is not replicated correctly"
assert_equal "a", @db2.get("a"), "Database two is not replicated correctly"
end
def test_that_database_are_replicated_with_conflicts
@db1.set("c", "d")
@db2.set("c", "f")
replicate(@db1, @db2)
assert_equal "f", @db1.get("c"), "Database one is not consistent"
assert_equal "f", @db2.get("c"), "Database two is not consistent"
end
def test_that_database_are_replicated_with_conflicts_and_time_stamp_checking
@db1.set("c", "d")
@db2.set("c", "f")
@db1.set("c", "x")
replicate(@db1, @db2)
assert_equal "x", @db1.get("c"), "Database one is not consistent"
assert_equal "x", @db2.get("c"), "Database two is not consistent"
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment