Class: Brute::Contrib::LogFile

Inherits:
File
  • Object
show all
Includes:
File::Tail
Defined in:
lib/brute/contrib/log_file.rb

Overview

A line-oriented, append-only log file that doubles as a work queue.

Every entry is exactly one line — newlines in the input are folded to spaces on the way in — so a line is the unit of both storage and retrieval. Reads are destructive: pop takes the newest line off the end, drain yields every line oldest-first and empties the file.

log = Brute::Contrib::LogFile.new("tmp/queue.log")
log.append("something happened")
log.pop            # => "something happened"
log.drain { |line| handle(line) }

Safe across both threads (a mutex) and processes (an exclusive flock), so several agents can share one file without losing lines.

Instance Method Summary collapse

Constructor Details

#initialize(path) ⇒ LogFile

Returns a new instance of LogFile.



25
26
27
28
29
# File 'lib/brute/contrib/log_file.rb', line 25

def initialize(path)
  FileUtils.mkdir_p(File.dirname(path))
  super(path, File::RDWR | File::CREAT | File::APPEND)
  @mutex = Mutex.new
end

Instance Method Details

#append(line) ⇒ Object

Append one line. Blank (or whitespace-only) input is a no-op and returns nil; otherwise returns the stripped line that was written.



33
34
35
36
37
38
39
40
41
42
43
# File 'lib/brute/contrib/log_file.rb', line 33

def append(line)
  strip_whitespace(line).then do |stripped_text|
    unless stripped_text.empty?
      locked do
        puts(stripped_text)
        flush
        stripped_text
      end
    end
  end
end

#drainObject

Yield every line oldest-first, then empty the file. Requires a block — without one there is nowhere for the lines to go, so it raises rather than discarding them.



57
58
59
60
61
62
63
64
65
66
67
# File 'lib/brute/contrib/log_file.rb', line 57

def drain
  locked do
    if block_given?
      backward(line_count)
      each_line { |x| yield x.chomp }
      truncate(0)
    else
      raise "No block given..."
    end
  end
end

#popObject

Remove and return the newest line, or nil when the file is empty.



46
47
48
49
50
51
52
# File 'lib/brute/contrib/log_file.rb', line 46

def pop
  locked do
    backward(1)
    offset = tell
    gets&.chomp.tap { truncate(offset) }
  end
end