Class: Procrastinator::TaskStore::SimpleCommaStore

Inherits:
Object
  • Object
show all
Defined in:
lib/procrastinator/task_store/simple_comma_store.rb

Overview

Simple Task I/O adapter that writes task information (ie. TaskMetaData attributes) to a CSV file.

SimpleCommaStore is not designed for efficiency or large loads (10,000+ tasks). For critical production environments, it is strongly recommended to use a more robust storage mechanism like a proper database.

Author:

  • Robin Miller

Defined Under Namespace

Classes: CSVFileTransaction

Constant Summary collapse

HEADERS =

Ordered list of CSV column headers

[:id, :queue, :run_at, :initial_run_at, :expire_at,
:attempts, :last_fail_at, :last_error, :data].freeze
EXT =

CSV file extension

'csv'
DEFAULT_FILE =

Default filename

Pathname.new("procrastinator-tasks.#{ EXT }").freeze
READ_CONVERTER =

CSV Converter lambda

See Also:

  • CSV
proc do |value, field_info|
   if field_info.header == :data
      value
   elsif Task::TIME_FIELDS.include? field_info.header
      value.empty? ? nil : Time.parse(value)
   else
      begin
         Integer(value)
      rescue ArgumentError
         value
      end
   end
end

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(file_path = DEFAULT_FILE) ⇒ SimpleCommaStore

Returns a new instance of SimpleCommaStore.



47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/procrastinator/task_store/simple_comma_store.rb', line 47

def initialize(file_path = DEFAULT_FILE)
   @path = Pathname.new(file_path)

   if @path.directory? || @path.to_s.end_with?('/')
      @path /= DEFAULT_FILE
   elsif @path.extname.empty?
      @path = @path.dirname / "#{ @path.basename }.csv"
   end

   @path = @path.expand_path

   freeze
end

Instance Attribute Details

#pathObject (readonly)

Returns the value of attribute path.



45
46
47
# File 'lib/procrastinator/task_store/simple_comma_store.rb', line 45

def path
  @path
end

Instance Method Details

#create(queue:, run_at:, expire_at: nil, data: '', initial_run_at: nil) ⇒ Object

Saves a task to the CSV file.

Parameters:

  • queue (String)

    queue name

  • run_at (Time, nil)

    time to run the task at

  • initial_run_at (Time, nil) (defaults to: nil)

    first time to run the task at. Defaults to run_at.

  • expire_at (Time, nil) (defaults to: nil)

    time to expire the task



81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/procrastinator/task_store/simple_comma_store.rb', line 81

def create(queue:, run_at:, expire_at: nil, data: '', initial_run_at: nil)
   CSVFileTransaction.new(@path).write do |tasks|
      max_id = tasks.collect { |task| task[:id] }.max || 0

      new_data = {
            id:             max_id + 1,
            queue:          queue,
            run_at:         run_at,
            initial_run_at: initial_run_at || run_at,
            expire_at:      expire_at,
            attempts:       0,
            data:           data
      }

      generate(tasks + [new_data])
   end
end

#delete(id) ⇒ Object

Removes an existing task from the CSV file.

Parameters:

  • id (Integer)

    task ID number



118
119
120
121
122
# File 'lib/procrastinator/task_store/simple_comma_store.rb', line 118

def delete(id)
   CSVFileTransaction.new(@path).write do |existing_data|
      generate(existing_data.reject { |task| task[:id] == id })
   end
end

#generate(data) ⇒ String

Generates a CSV string from the given data.

Parameters:

  • data (Array)

    list of data to convert into CSV

Returns:

  • (String)

    Generated CSV string



128
129
130
131
132
133
134
135
136
137
138
139
# File 'lib/procrastinator/task_store/simple_comma_store.rb', line 128

def generate(data)
   lines = data.collect do |d|
      Task::TIME_FIELDS.each do |field|
         d[field] = d[field]&.iso8601
      end
      CSV.generate_line(d, headers: HEADERS, force_quotes: true).strip
   end

   lines.unshift(HEADERS.join(','))

   lines.join("\n") << "\n"
end

#read(filter = {}) ⇒ Array<Hash>

Parses the CSV file for data matching the given filter, or all if no filter provided.

Parameters:

  • filter (Hash) (defaults to: {})

    Specified attributes to match.

Returns:

  • (Array<Hash>)


65
66
67
68
69
70
71
72
73
# File 'lib/procrastinator/task_store/simple_comma_store.rb', line 65

def read(filter = {})
   CSVFileTransaction.new(@path).read do |existing_data|
      existing_data.select do |row|
         filter.keys.all? do |key|
            row[key] == filter[key]
         end
      end
   end
end

#update(id, data) ⇒ Object

Updates an existing task in the CSV file.

Parameters:

  • id (Integer)

    task ID number

  • data (Hash)

    new data to save



103
104
105
106
107
108
109
110
111
112
113
# File 'lib/procrastinator/task_store/simple_comma_store.rb', line 103

def update(id, data)
   CSVFileTransaction.new(@path).write do |tasks|
      task_data = tasks.find do |task|
         task[:id] == id
      end

      task_data&.merge!(data)

      generate(tasks)
   end
end