Class: Terret::Store::JSONL

Inherits:
Hames::Service
  • Object
show all
Defined in:
lib/terret/store.rb

Overview

JSONL provider: one file per session, one JSON envelope per line, made for grepping. at carries microseconds so Time round-trips exactly.

Instance Method Summary collapse

Instance Method Details

#append(event) ⇒ Object



45
46
47
48
49
50
51
52
# File 'lib/terret/store.rb', line 45

def append(event)
  File.open(path(event.session_id), "a") do |f|
    f.puts JSON.generate(
      id: event.id, session_id: event.session_id, seq: event.seq,
      at: event.at.iso8601(6), type: event.type, payload: event.payload
    )
  end
end

#read(session_id, from_seq: 0) ⇒ Object



54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/terret/store.rb', line 54

def read(session_id, from_seq: 0)
  return [] unless File.exist?(path(session_id))

  File.foreach(path(session_id)).filter_map do |line|
    h = begin
      JSON.parse(line, symbolize_names: true)
    rescue JSON::ParserError
      next # a torn line (crash mid-write) loses itself, not the session
    end
    next if h[:seq] < from_seq

    SessionEvent.new(id: h[:id], session_id: h[:session_id], seq: h[:seq],
                     at: Time.iso8601(h[:at]), type: h[:type], payload: h[:payload])
  end
end

#session_idsObject



70
71
72
# File 'lib/terret/store.rb', line 70

def session_ids
  Dir[File.join(@dir, "*.jsonl")].map { |f| File.basename(f, ".jsonl") }
end

#start(_ctx) ⇒ Object



41
42
43
# File 'lib/terret/store.rb', line 41

def start(_ctx)
  @dir ||= config.fetch(:dir).tap { |d| FileUtils.mkdir_p(d) }
end