Skip to content

Instantly share code, notes, and snippets.

@Varun-garg
Created September 30, 2021 07:47
Show Gist options
  • Save Varun-garg/f9ddb7c63ec229225bef6cea4cdd7b65 to your computer and use it in GitHub Desktop.
Save Varun-garg/f9ddb7c63ec229225bef6cea4cdd7b65 to your computer and use it in GitHub Desktop.
small key value store
require 'sinatra'
require 'json'
class Value
attr_accessor :type, :value
def initialize(value)
@value = value
if ['true', 'false'].include? value.downcase
@type = 'boolean'
elsif value.match(/^(\d)+$/) # integer or double
value = value.to_i
if value >= -2147483648 && value <= 2147483647
@type = 'integer'
else
@type = 'double'
end
else
@type = 'string'
end
end
end
class SecondaryValue
attr_accessor :type, :primary_keys
def initialize()
@type = nil
@primary_keys = Set.new
end
def check_value(value)
return @type.nil? || @type == value.type
end
def insert_primary_key(key, type)
@type = type
primary_keys << key
end
end
db = Hash.new
secondary_db = Hash.new
lock = Mutex.new
get '/' do
'Hello world!'
end
post '/store' do
params = JSON.parse(request.body.read)
puts "params #{params}"
key = params['key']
values = params["values"]
if db[key].nil?
db[key] = Hash.new
end
puts "key: #{key}"
puts "values: #{values}"
values.each do |value|
puts "debug: #{value}"
secondary_key = value["attribute_name"]
val = Value.new(value["attribute_value"])
seondary_value = secondary_db[secondary_key]
if seondary_value.nil?
secondary_db[secondary_key] = SecondaryValue.new
seondary_value = secondary_db[secondary_key]
end
if !seondary_value.check_value(val)
status 403
body "attribute: #{secondary_key} must be of type #{seondary_value.type}"
return
end
lock.synchronize do
db[key][secondary_key] = val
seondary_value.insert_primary_key(key, val.type)
end
end
'Success'
end
get '/fetch' do
key = params["key"]
puts "fetching key #{key}"
values = db[key]
if values.nil?
status 404
body "no values set for #{key}"
return
end
results = []
puts "values #{values.class} #{values}"
values.each do |key, value|
puts "key #{key}"
puts "value #{value}"
puts "value.value #{value.value}"
results << {
attribute_name: key,
attribute_value: value.value,
}
end
puts "values #{results}"
results.to_json
end
get '/delete' do
key = params["key"]
values = db[key]
if values.nil?
status 404
body "no values set for #{key}"
return
end
results = []
lock.synchronize do
values.each do |skey, value|
secondary_db[skey].primary_keys.delete key
if secondary_db[skey].primary_keys.size == 0 # optional?
secondary_db[skey].type = nil
end
end
db.delete key
end
'OK'
end
get '/stretch' do
secondary_key = params["attribute_name"]
search_value = Value.new params["attribute_value"]
results = []
secondary_value = secondary_db[secondary_key]
if secondary_value && secondary_value.type == search_value.type
secondary_value.primary_keys.each do |key|
if db[key][secondary_key].value == search_value.value
results << key
end
end
end
status results.size == 0 ? 404 : 200
results.to_json
end
get '/debug' do
"db #{db} \n secondary_db #{secondary_db}\n"
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment