An authentication server
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

99 lines
1.8 KiB

require "sqlite3"
require "../config.cr"
class CacheLRU
def initialize
@store = Hash(String, Tuple(Time, User)).new
@mutex = Mutex.new
@cache_limit = 5000
end
def try(pair) : User | Nil
@mutex.synchronize do
if @store.has_key?(pair)
return @store[pair][1]
else return nil
end
end
end
def push(pair, data)
@mutex.synchronize do
@store[pair] = Tuple.new(Time.now+Time::Span.new(1,0,0), data)
if(@store.size > @cache_limit)
clean
end
end
end
def clean
@mutex.synchronize do
curr = Time.now
@store.reject! do |k, v|
return v[0]>curr
end
end
end
def invalidate(pair)
@mutex.synchronize do
@store.reject! pair
end
end
end
class KVStore
property database : DB::Database
property st_fetch : DB::PoolPreparedStatement
property st_push : DB::PoolPreparedStatement
property cache : CacheLRU
def initialize
@database = DB.open(Statics.data_path)
@database.exec "create table if not exists kv (k TEXT PRIMARY KEY, v TEXT);"
@st_fetch = DB::PoolPreparedStatement.new @database, "select v from kv where k=?;"
@st_push = DB::PoolPreparedStatement.new @database, "insert into kv(k,v) values(?,?) on conflict(k) do update set v=?;"
@cache = CacheLRU.new
end
def fetch(key : String) : User | Nil
begin
f = @cache.try(key)
if(f.nil?)
v = @st_fetch.scalar(key)
u = User.from_json v.to_s
@cache.push(key, u)
if(v.nil?)
return nil
else
return u
end
else
return f
end
rescue ex
return nil
end
end
def fetch!(key : String) : User
fetch(key).not_nil!
end
def push(key : String, value : String)
@cache.invalidate key
@st_push.exec(key, value, value)
end
def transaction()
@database.transaction do |tx|
yield self
end
end
def self.access
@@instance ||= new
end
end