module Postspec class State attr_reader :id attr_reader :mode attr_accessor :ready attr_accessor :clean attr_accessor :status attr_reader :created_at attr_reader :updated_at def duration() @duraction ||= (1000 * (updated_at - created_at)).round(0) end # Maps from table UID to sorted list of record IDs. # TODO: Are they in use? Should they be used?? Used from postspec! # FIXME: Move to Frame - maybe? def inserted() get_multimap("inserts") end def updated() get_multimap("updates") end def deleted() get_multimap("deletes") end # Map from table UID to max record ID for that table def seeds() @seeds ||= get_map("seeds") end def refresh() @inserted = @updated = @deleted = @seeds = nil end def self.create(conn, mode) id, created_at = conn.tuple <<~EOS insert into postspec.runs (mode) values ('#{mode}') returning id, created_at EOS State.new(conn, id, mode, false, false, nil, created_at, nil) end # Return true if change-tables contains any records. It is used to check if # the developer made any changes to the database after a (successful) # postspec run def self.dirty?(conn) conn.value(%( select true as present from postspec.inserts union select true from postspec.updates union select true from postspec.deletes )) || false end def self.ensure(conn, mode) end def self.read(conn) tuples = conn.tuples <<~EOS select id, mode, ready, clean, status, created_at, updated_at from postspec.runs order by id desc limit 1 EOS tuple = tuples.first tuple && State.new(conn, *tuple) end def self.write(conn, state) conn.exec <<~EOS update postspec.runs set ready = #{state.ready}, clean = #{state.clean}, status = #{state.status.nil? ? 'null' : state.status}, updated_at = now() at time zone 'UTC' where id = #{state.id} EOS @updated_at = conn.value "select updated_at from postspec.runs where id = #{state.id}" end def dump puts "State" indent { puts "id: #{id.inspect}" puts "mode: #{mode.inspect}" puts "ready: #{ready.inspect}" puts "clean: #{clean.inspect}" puts "status: #{status.inspect}" puts "duration: #{@duration.inspect}" puts "created_at: #{created_at.inspect}" } end private attr_reader :conn def initialize(conn, id, mode, ready, clean, status, created_at, updated_at) @conn = conn @id = id @mode = mode.to_sym @ready = ready @clean = clean @status = status @created_at = created_at @updated_at = updated_at end def get_map(table_name) conn.map "select distinct table_uid, record_id from postspec.#{table_name}" end def get_multimap(table_name) h = Hash.new #([]) conn.tuples(%( select distinct table_uid, record_id from postspec.#{table_name} order by table_uid, record_id )).map { |uid, id| (h[uid] ||= []) << id } h end end end