Class: Procrastinator::Config

Inherits:
Object
  • Object
show all
Includes:
DSL
Defined in:
lib/procrastinator/config.rb

Overview

Configuration object (State Pattern) used to coordinate settings across various components within Procrastinator.

It is immutable after init; use the config DSL in the configuration block to set its state.

Author:

  • Robin Miller

Defined Under Namespace

Modules: DSL Classes: SetupError

Constant Summary collapse

DEFAULT_LOG_DIRECTORY =

Default directory to keep logs in.

Pathname.new('log').freeze
DEFAULT_LOG_SHIFT_AGE =

Default age to keep log files for.

See Also:

  • Logger
0
DEFAULT_LOG_SHIFT_SIZE =

Default max size to keep log files under.

See Also:

  • Logger
2 ** 20
DEFAULT_LOG_FORMATTER =

Default log formatter

See Also:

  • Logger
proc do |severity, datetime, progname, msg|
   [datetime.iso8601(8),
    severity,
    "#{ progname } (#{ Process.pid }):",
    msg].join("\t") << "\n"
end
DEFAULT_PRIORITY =

Default priority ‘nice’ level.

1

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from DSL

#adjust_priority, #define_queue, #log_with, #provide_container, #with_store

Constructor Details

#initializeConfig

Returns a new instance of Config.



53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/procrastinator/config.rb', line 53

def initialize
   @queues         = []
   @container      = nil
   @log_dir        = DEFAULT_LOG_DIRECTORY
   @log_level      = Logger::INFO
   @log_shift_age  = DEFAULT_LOG_SHIFT_AGE
   @log_shift_size = DEFAULT_LOG_SHIFT_SIZE
   @priority       = DEFAULT_PRIORITY

   with_store(csv: TaskStore::SimpleCommaStore::DEFAULT_FILE) do
      if block_given?
         yield(self)
         raise SetupError, SetupError::ERR_NO_QUEUE if @queues.empty?
      end
   end

   @log_dir = @log_dir.expand_path

   @queues.freeze
   freeze
end

Instance Attribute Details

#:container(: container) ⇒ Object (readonly)

Returns Container object that will be forwarded to tasks.

Returns:

  • (Object)

    Container object that will be forwarded to tasks



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
# File 'lib/procrastinator/config.rb', line 25

class Config
   attr_reader :queues, :log_dir, :log_level, :log_shift_age, :log_shift_size, :container, :priority

   alias nice priority

   # Default directory to keep logs in.
   DEFAULT_LOG_DIRECTORY = Pathname.new('log').freeze

   # Default age to keep log files for.
   # @see Logger
   DEFAULT_LOG_SHIFT_AGE = 0

   # Default max size to keep log files under.
   # @see Logger
   DEFAULT_LOG_SHIFT_SIZE = 2 ** 20 # 1 MB

   # Default log formatter
   # @see Logger
   DEFAULT_LOG_FORMATTER = proc do |severity, datetime, progname, msg|
      [datetime.iso8601(8),
       severity,
       "#{ progname } (#{ Process.pid }):",
       msg].join("\t") << "\n"
   end

   # Default priority 'nice' level.
   DEFAULT_PRIORITY = 1

   def initialize
      @queues         = []
      @container      = nil
      @log_dir        = DEFAULT_LOG_DIRECTORY
      @log_level      = Logger::INFO
      @log_shift_age  = DEFAULT_LOG_SHIFT_AGE
      @log_shift_size = DEFAULT_LOG_SHIFT_SIZE
      @priority       = DEFAULT_PRIORITY

      with_store(csv: TaskStore::SimpleCommaStore::DEFAULT_FILE) do
         if block_given?
            yield(self)
            raise SetupError, SetupError::ERR_NO_QUEUE if @queues.empty?
         end
      end

      @log_dir = @log_dir.expand_path

      @queues.freeze
      freeze
   end

   # Collection of all of the methods intended for use within Procrastinator.setup
   #
   # @see Procrastinator
   module DSL
      # Assigns a task loader
      def with_store(store)
         raise(ArgumentError, 'with_store must be provided a block') unless block_given?

         old_store      = @default_store
         @default_store = interpret_store(store)
         yield
         @default_store = old_store
      end

      # Defines the container to assign to each Task Handler's :container attribute.
      #
      # @param container [Object] the container
      def provide_container(container)
         @container = container
      end

      # Defines a queue in the Procrastinator Scheduler.
      #
      # The Task Handler will be initialized for each task and assigned each of these attributes:
      #    :container, :logger, :scheduler
      #
      # @param name [Symbol, String] the identifier to label the queue. Referenced in #defer calls
      # @param task_class [Class] the Task Handler class.
      # @param properties [Hash] Settings options object for this queue
      # @option properties [Object] :store (Procrastinator::TaskStore::SimpleCommaStore)
      #                                    Storage strategy for tasks in the queue.
      # @option properties [Integer] :max_attempts (Procrastinator::Queue::DEFAULT_MAX_ATTEMPTS)
      #                                            Maximum number of times a task may be attempted before giving up.
      # @option properties [Integer] :timeout (Procrastinator::Queue::DEFAULT_TIMEOUT)
      #                                       Maximum number of seconds to wait for a single task to complete.
      # @option properties [Integer] :update_period (Procrastinator::Queue::DEFAULT_UPDATE_PERIOD)
      #                                             Time to wait before checking for new tasks.
      def define_queue(name, task_class, properties = {})
         raise ArgumentError, 'queue name cannot be nil' if name.nil?
         raise ArgumentError, 'queue task class cannot be nil' if task_class.nil?

         properties[:store] = interpret_store(properties[:store]) if properties.key? :store

         args = {name: name, task_class: task_class, store: @default_store}.merge(properties)

         @queues << Queue.new(**args)
      end

      # Sets details of logging behaviour
      #
      # @param directory [Pathname,String] the directory to save logs within.
      # @param level [Logger::UNKNOWN,Logger::FATAL,Logger::ERROR,Logger::WARN,Logger::INFO,Logger::DEBUG,Integer,Boolean] the Ruby Logger level to use. If falsey, no logging is performed.
      # @param shift_age [Integer] number of old log files to keep (see Ruby Logger for details)
      # @param shift_size [Integer] filesize before log is rotated to a fresh file (see Ruby Logger for details)
      def log_with(directory: @log_dir, level: @log_level, shift_age: @log_shift_age, shift_size: @log_shift_size)
         @log_dir        = directory ? Pathname.new(directory) : directory
         @log_level      = level
         @log_shift_age  = shift_age
         @log_shift_size = shift_size
      end

      # Sets the desired process 'nice' priority value adjustment. This value is added to whatever runtime priority
      # Procrastinator starts with.
      #
      # Higher numbers are more nice to other processes (lower priority); think of it as the position in line.
      # You can be more nice, but never less nice.
      #
      # @param new_priority [Number] the new priority.
      def adjust_priority(new_priority)
         @priority = new_priority
      end

      alias adjust_nice adjust_priority
   end

   include DSL

   def queue(name: nil)
      queue = if name
                 @queues.find do |q|
                    q.name == name
                 end
              else
                 if name.nil? && @queues.length > 1
                    raise ArgumentError,
                          "queue must be specified when more than one is defined. #{ known_queues }"
                 end

                 @queues.first
              end

      raise ArgumentError, "there is no :#{ name } queue registered. #{ known_queues }" unless queue

      queue
   end

   private

   def known_queues
      "Known queues are: #{ @queues.map { |queue| ":#{ queue.name }" }.join(', ') }"
   end

   def interpret_store(store)
      raise(ArgumentError, 'task store cannot be nil') if store.nil?

      case store
      when Hash
         store_strategy = :csv
         unless store.key? store_strategy
            raise ArgumentError, "Must pass keyword :#{ store_strategy } if specifying a location for CSV file"
         end

         TaskStore::SimpleCommaStore.new(store[store_strategy])
      when String, Pathname
         TaskStore::SimpleCommaStore.new(store)
      else
         store
      end
   end

   # Raised when there is an error in the setup configuration.
   class SetupError < RuntimeError
      # Standard error message for when there is no queue defined
      ERR_NO_QUEUE = 'setup block must call #define_queue on the environment'
   end
end

#:log_dir(: log_dir) ⇒ Pathname (readonly)

Returns Directory to write log files in.

Returns:

  • (Pathname)

    Directory to write log files in



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
# File 'lib/procrastinator/config.rb', line 25

class Config
   attr_reader :queues, :log_dir, :log_level, :log_shift_age, :log_shift_size, :container, :priority

   alias nice priority

   # Default directory to keep logs in.
   DEFAULT_LOG_DIRECTORY = Pathname.new('log').freeze

   # Default age to keep log files for.
   # @see Logger
   DEFAULT_LOG_SHIFT_AGE = 0

   # Default max size to keep log files under.
   # @see Logger
   DEFAULT_LOG_SHIFT_SIZE = 2 ** 20 # 1 MB

   # Default log formatter
   # @see Logger
   DEFAULT_LOG_FORMATTER = proc do |severity, datetime, progname, msg|
      [datetime.iso8601(8),
       severity,
       "#{ progname } (#{ Process.pid }):",
       msg].join("\t") << "\n"
   end

   # Default priority 'nice' level.
   DEFAULT_PRIORITY = 1

   def initialize
      @queues         = []
      @container      = nil
      @log_dir        = DEFAULT_LOG_DIRECTORY
      @log_level      = Logger::INFO
      @log_shift_age  = DEFAULT_LOG_SHIFT_AGE
      @log_shift_size = DEFAULT_LOG_SHIFT_SIZE
      @priority       = DEFAULT_PRIORITY

      with_store(csv: TaskStore::SimpleCommaStore::DEFAULT_FILE) do
         if block_given?
            yield(self)
            raise SetupError, SetupError::ERR_NO_QUEUE if @queues.empty?
         end
      end

      @log_dir = @log_dir.expand_path

      @queues.freeze
      freeze
   end

   # Collection of all of the methods intended for use within Procrastinator.setup
   #
   # @see Procrastinator
   module DSL
      # Assigns a task loader
      def with_store(store)
         raise(ArgumentError, 'with_store must be provided a block') unless block_given?

         old_store      = @default_store
         @default_store = interpret_store(store)
         yield
         @default_store = old_store
      end

      # Defines the container to assign to each Task Handler's :container attribute.
      #
      # @param container [Object] the container
      def provide_container(container)
         @container = container
      end

      # Defines a queue in the Procrastinator Scheduler.
      #
      # The Task Handler will be initialized for each task and assigned each of these attributes:
      #    :container, :logger, :scheduler
      #
      # @param name [Symbol, String] the identifier to label the queue. Referenced in #defer calls
      # @param task_class [Class] the Task Handler class.
      # @param properties [Hash] Settings options object for this queue
      # @option properties [Object] :store (Procrastinator::TaskStore::SimpleCommaStore)
      #                                    Storage strategy for tasks in the queue.
      # @option properties [Integer] :max_attempts (Procrastinator::Queue::DEFAULT_MAX_ATTEMPTS)
      #                                            Maximum number of times a task may be attempted before giving up.
      # @option properties [Integer] :timeout (Procrastinator::Queue::DEFAULT_TIMEOUT)
      #                                       Maximum number of seconds to wait for a single task to complete.
      # @option properties [Integer] :update_period (Procrastinator::Queue::DEFAULT_UPDATE_PERIOD)
      #                                             Time to wait before checking for new tasks.
      def define_queue(name, task_class, properties = {})
         raise ArgumentError, 'queue name cannot be nil' if name.nil?
         raise ArgumentError, 'queue task class cannot be nil' if task_class.nil?

         properties[:store] = interpret_store(properties[:store]) if properties.key? :store

         args = {name: name, task_class: task_class, store: @default_store}.merge(properties)

         @queues << Queue.new(**args)
      end

      # Sets details of logging behaviour
      #
      # @param directory [Pathname,String] the directory to save logs within.
      # @param level [Logger::UNKNOWN,Logger::FATAL,Logger::ERROR,Logger::WARN,Logger::INFO,Logger::DEBUG,Integer,Boolean] the Ruby Logger level to use. If falsey, no logging is performed.
      # @param shift_age [Integer] number of old log files to keep (see Ruby Logger for details)
      # @param shift_size [Integer] filesize before log is rotated to a fresh file (see Ruby Logger for details)
      def log_with(directory: @log_dir, level: @log_level, shift_age: @log_shift_age, shift_size: @log_shift_size)
         @log_dir        = directory ? Pathname.new(directory) : directory
         @log_level      = level
         @log_shift_age  = shift_age
         @log_shift_size = shift_size
      end

      # Sets the desired process 'nice' priority value adjustment. This value is added to whatever runtime priority
      # Procrastinator starts with.
      #
      # Higher numbers are more nice to other processes (lower priority); think of it as the position in line.
      # You can be more nice, but never less nice.
      #
      # @param new_priority [Number] the new priority.
      def adjust_priority(new_priority)
         @priority = new_priority
      end

      alias adjust_nice adjust_priority
   end

   include DSL

   def queue(name: nil)
      queue = if name
                 @queues.find do |q|
                    q.name == name
                 end
              else
                 if name.nil? && @queues.length > 1
                    raise ArgumentError,
                          "queue must be specified when more than one is defined. #{ known_queues }"
                 end

                 @queues.first
              end

      raise ArgumentError, "there is no :#{ name } queue registered. #{ known_queues }" unless queue

      queue
   end

   private

   def known_queues
      "Known queues are: #{ @queues.map { |queue| ":#{ queue.name }" }.join(', ') }"
   end

   def interpret_store(store)
      raise(ArgumentError, 'task store cannot be nil') if store.nil?

      case store
      when Hash
         store_strategy = :csv
         unless store.key? store_strategy
            raise ArgumentError, "Must pass keyword :#{ store_strategy } if specifying a location for CSV file"
         end

         TaskStore::SimpleCommaStore.new(store[store_strategy])
      when String, Pathname
         TaskStore::SimpleCommaStore.new(store)
      else
         store
      end
   end

   # Raised when there is an error in the setup configuration.
   class SetupError < RuntimeError
      # Standard error message for when there is no queue defined
      ERR_NO_QUEUE = 'setup block must call #define_queue on the environment'
   end
end

#:log_level(: log_level) ⇒ Integer (readonly)

Returns Logging level to use.

Returns:

  • (Integer)

    Logging level to use



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
# File 'lib/procrastinator/config.rb', line 25

class Config
   attr_reader :queues, :log_dir, :log_level, :log_shift_age, :log_shift_size, :container, :priority

   alias nice priority

   # Default directory to keep logs in.
   DEFAULT_LOG_DIRECTORY = Pathname.new('log').freeze

   # Default age to keep log files for.
   # @see Logger
   DEFAULT_LOG_SHIFT_AGE = 0

   # Default max size to keep log files under.
   # @see Logger
   DEFAULT_LOG_SHIFT_SIZE = 2 ** 20 # 1 MB

   # Default log formatter
   # @see Logger
   DEFAULT_LOG_FORMATTER = proc do |severity, datetime, progname, msg|
      [datetime.iso8601(8),
       severity,
       "#{ progname } (#{ Process.pid }):",
       msg].join("\t") << "\n"
   end

   # Default priority 'nice' level.
   DEFAULT_PRIORITY = 1

   def initialize
      @queues         = []
      @container      = nil
      @log_dir        = DEFAULT_LOG_DIRECTORY
      @log_level      = Logger::INFO
      @log_shift_age  = DEFAULT_LOG_SHIFT_AGE
      @log_shift_size = DEFAULT_LOG_SHIFT_SIZE
      @priority       = DEFAULT_PRIORITY

      with_store(csv: TaskStore::SimpleCommaStore::DEFAULT_FILE) do
         if block_given?
            yield(self)
            raise SetupError, SetupError::ERR_NO_QUEUE if @queues.empty?
         end
      end

      @log_dir = @log_dir.expand_path

      @queues.freeze
      freeze
   end

   # Collection of all of the methods intended for use within Procrastinator.setup
   #
   # @see Procrastinator
   module DSL
      # Assigns a task loader
      def with_store(store)
         raise(ArgumentError, 'with_store must be provided a block') unless block_given?

         old_store      = @default_store
         @default_store = interpret_store(store)
         yield
         @default_store = old_store
      end

      # Defines the container to assign to each Task Handler's :container attribute.
      #
      # @param container [Object] the container
      def provide_container(container)
         @container = container
      end

      # Defines a queue in the Procrastinator Scheduler.
      #
      # The Task Handler will be initialized for each task and assigned each of these attributes:
      #    :container, :logger, :scheduler
      #
      # @param name [Symbol, String] the identifier to label the queue. Referenced in #defer calls
      # @param task_class [Class] the Task Handler class.
      # @param properties [Hash] Settings options object for this queue
      # @option properties [Object] :store (Procrastinator::TaskStore::SimpleCommaStore)
      #                                    Storage strategy for tasks in the queue.
      # @option properties [Integer] :max_attempts (Procrastinator::Queue::DEFAULT_MAX_ATTEMPTS)
      #                                            Maximum number of times a task may be attempted before giving up.
      # @option properties [Integer] :timeout (Procrastinator::Queue::DEFAULT_TIMEOUT)
      #                                       Maximum number of seconds to wait for a single task to complete.
      # @option properties [Integer] :update_period (Procrastinator::Queue::DEFAULT_UPDATE_PERIOD)
      #                                             Time to wait before checking for new tasks.
      def define_queue(name, task_class, properties = {})
         raise ArgumentError, 'queue name cannot be nil' if name.nil?
         raise ArgumentError, 'queue task class cannot be nil' if task_class.nil?

         properties[:store] = interpret_store(properties[:store]) if properties.key? :store

         args = {name: name, task_class: task_class, store: @default_store}.merge(properties)

         @queues << Queue.new(**args)
      end

      # Sets details of logging behaviour
      #
      # @param directory [Pathname,String] the directory to save logs within.
      # @param level [Logger::UNKNOWN,Logger::FATAL,Logger::ERROR,Logger::WARN,Logger::INFO,Logger::DEBUG,Integer,Boolean] the Ruby Logger level to use. If falsey, no logging is performed.
      # @param shift_age [Integer] number of old log files to keep (see Ruby Logger for details)
      # @param shift_size [Integer] filesize before log is rotated to a fresh file (see Ruby Logger for details)
      def log_with(directory: @log_dir, level: @log_level, shift_age: @log_shift_age, shift_size: @log_shift_size)
         @log_dir        = directory ? Pathname.new(directory) : directory
         @log_level      = level
         @log_shift_age  = shift_age
         @log_shift_size = shift_size
      end

      # Sets the desired process 'nice' priority value adjustment. This value is added to whatever runtime priority
      # Procrastinator starts with.
      #
      # Higher numbers are more nice to other processes (lower priority); think of it as the position in line.
      # You can be more nice, but never less nice.
      #
      # @param new_priority [Number] the new priority.
      def adjust_priority(new_priority)
         @priority = new_priority
      end

      alias adjust_nice adjust_priority
   end

   include DSL

   def queue(name: nil)
      queue = if name
                 @queues.find do |q|
                    q.name == name
                 end
              else
                 if name.nil? && @queues.length > 1
                    raise ArgumentError,
                          "queue must be specified when more than one is defined. #{ known_queues }"
                 end

                 @queues.first
              end

      raise ArgumentError, "there is no :#{ name } queue registered. #{ known_queues }" unless queue

      queue
   end

   private

   def known_queues
      "Known queues are: #{ @queues.map { |queue| ":#{ queue.name }" }.join(', ') }"
   end

   def interpret_store(store)
      raise(ArgumentError, 'task store cannot be nil') if store.nil?

      case store
      when Hash
         store_strategy = :csv
         unless store.key? store_strategy
            raise ArgumentError, "Must pass keyword :#{ store_strategy } if specifying a location for CSV file"
         end

         TaskStore::SimpleCommaStore.new(store[store_strategy])
      when String, Pathname
         TaskStore::SimpleCommaStore.new(store)
      else
         store
      end
   end

   # Raised when there is an error in the setup configuration.
   class SetupError < RuntimeError
      # Standard error message for when there is no queue defined
      ERR_NO_QUEUE = 'setup block must call #define_queue on the environment'
   end
end

#:log_shift_age(: log_shift_age) ⇒ Integer (readonly)

Returns Number of previous files to keep (see Ruby Logger for details).

Returns:

  • (Integer)

    Number of previous files to keep (see Ruby Logger for details)



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
# File 'lib/procrastinator/config.rb', line 25

class Config
   attr_reader :queues, :log_dir, :log_level, :log_shift_age, :log_shift_size, :container, :priority

   alias nice priority

   # Default directory to keep logs in.
   DEFAULT_LOG_DIRECTORY = Pathname.new('log').freeze

   # Default age to keep log files for.
   # @see Logger
   DEFAULT_LOG_SHIFT_AGE = 0

   # Default max size to keep log files under.
   # @see Logger
   DEFAULT_LOG_SHIFT_SIZE = 2 ** 20 # 1 MB

   # Default log formatter
   # @see Logger
   DEFAULT_LOG_FORMATTER = proc do |severity, datetime, progname, msg|
      [datetime.iso8601(8),
       severity,
       "#{ progname } (#{ Process.pid }):",
       msg].join("\t") << "\n"
   end

   # Default priority 'nice' level.
   DEFAULT_PRIORITY = 1

   def initialize
      @queues         = []
      @container      = nil
      @log_dir        = DEFAULT_LOG_DIRECTORY
      @log_level      = Logger::INFO
      @log_shift_age  = DEFAULT_LOG_SHIFT_AGE
      @log_shift_size = DEFAULT_LOG_SHIFT_SIZE
      @priority       = DEFAULT_PRIORITY

      with_store(csv: TaskStore::SimpleCommaStore::DEFAULT_FILE) do
         if block_given?
            yield(self)
            raise SetupError, SetupError::ERR_NO_QUEUE if @queues.empty?
         end
      end

      @log_dir = @log_dir.expand_path

      @queues.freeze
      freeze
   end

   # Collection of all of the methods intended for use within Procrastinator.setup
   #
   # @see Procrastinator
   module DSL
      # Assigns a task loader
      def with_store(store)
         raise(ArgumentError, 'with_store must be provided a block') unless block_given?

         old_store      = @default_store
         @default_store = interpret_store(store)
         yield
         @default_store = old_store
      end

      # Defines the container to assign to each Task Handler's :container attribute.
      #
      # @param container [Object] the container
      def provide_container(container)
         @container = container
      end

      # Defines a queue in the Procrastinator Scheduler.
      #
      # The Task Handler will be initialized for each task and assigned each of these attributes:
      #    :container, :logger, :scheduler
      #
      # @param name [Symbol, String] the identifier to label the queue. Referenced in #defer calls
      # @param task_class [Class] the Task Handler class.
      # @param properties [Hash] Settings options object for this queue
      # @option properties [Object] :store (Procrastinator::TaskStore::SimpleCommaStore)
      #                                    Storage strategy for tasks in the queue.
      # @option properties [Integer] :max_attempts (Procrastinator::Queue::DEFAULT_MAX_ATTEMPTS)
      #                                            Maximum number of times a task may be attempted before giving up.
      # @option properties [Integer] :timeout (Procrastinator::Queue::DEFAULT_TIMEOUT)
      #                                       Maximum number of seconds to wait for a single task to complete.
      # @option properties [Integer] :update_period (Procrastinator::Queue::DEFAULT_UPDATE_PERIOD)
      #                                             Time to wait before checking for new tasks.
      def define_queue(name, task_class, properties = {})
         raise ArgumentError, 'queue name cannot be nil' if name.nil?
         raise ArgumentError, 'queue task class cannot be nil' if task_class.nil?

         properties[:store] = interpret_store(properties[:store]) if properties.key? :store

         args = {name: name, task_class: task_class, store: @default_store}.merge(properties)

         @queues << Queue.new(**args)
      end

      # Sets details of logging behaviour
      #
      # @param directory [Pathname,String] the directory to save logs within.
      # @param level [Logger::UNKNOWN,Logger::FATAL,Logger::ERROR,Logger::WARN,Logger::INFO,Logger::DEBUG,Integer,Boolean] the Ruby Logger level to use. If falsey, no logging is performed.
      # @param shift_age [Integer] number of old log files to keep (see Ruby Logger for details)
      # @param shift_size [Integer] filesize before log is rotated to a fresh file (see Ruby Logger for details)
      def log_with(directory: @log_dir, level: @log_level, shift_age: @log_shift_age, shift_size: @log_shift_size)
         @log_dir        = directory ? Pathname.new(directory) : directory
         @log_level      = level
         @log_shift_age  = shift_age
         @log_shift_size = shift_size
      end

      # Sets the desired process 'nice' priority value adjustment. This value is added to whatever runtime priority
      # Procrastinator starts with.
      #
      # Higher numbers are more nice to other processes (lower priority); think of it as the position in line.
      # You can be more nice, but never less nice.
      #
      # @param new_priority [Number] the new priority.
      def adjust_priority(new_priority)
         @priority = new_priority
      end

      alias adjust_nice adjust_priority
   end

   include DSL

   def queue(name: nil)
      queue = if name
                 @queues.find do |q|
                    q.name == name
                 end
              else
                 if name.nil? && @queues.length > 1
                    raise ArgumentError,
                          "queue must be specified when more than one is defined. #{ known_queues }"
                 end

                 @queues.first
              end

      raise ArgumentError, "there is no :#{ name } queue registered. #{ known_queues }" unless queue

      queue
   end

   private

   def known_queues
      "Known queues are: #{ @queues.map { |queue| ":#{ queue.name }" }.join(', ') }"
   end

   def interpret_store(store)
      raise(ArgumentError, 'task store cannot be nil') if store.nil?

      case store
      when Hash
         store_strategy = :csv
         unless store.key? store_strategy
            raise ArgumentError, "Must pass keyword :#{ store_strategy } if specifying a location for CSV file"
         end

         TaskStore::SimpleCommaStore.new(store[store_strategy])
      when String, Pathname
         TaskStore::SimpleCommaStore.new(store)
      else
         store
      end
   end

   # Raised when there is an error in the setup configuration.
   class SetupError < RuntimeError
      # Standard error message for when there is no queue defined
      ERR_NO_QUEUE = 'setup block must call #define_queue on the environment'
   end
end

#:log_shift_size(: log_shift_size) ⇒ Integer (readonly)

Returns Filesize before rotating to a new logfile (see Ruby Logger for details).

Returns:

  • (Integer)

    Filesize before rotating to a new logfile (see Ruby Logger for details)



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
# File 'lib/procrastinator/config.rb', line 25

class Config
   attr_reader :queues, :log_dir, :log_level, :log_shift_age, :log_shift_size, :container, :priority

   alias nice priority

   # Default directory to keep logs in.
   DEFAULT_LOG_DIRECTORY = Pathname.new('log').freeze

   # Default age to keep log files for.
   # @see Logger
   DEFAULT_LOG_SHIFT_AGE = 0

   # Default max size to keep log files under.
   # @see Logger
   DEFAULT_LOG_SHIFT_SIZE = 2 ** 20 # 1 MB

   # Default log formatter
   # @see Logger
   DEFAULT_LOG_FORMATTER = proc do |severity, datetime, progname, msg|
      [datetime.iso8601(8),
       severity,
       "#{ progname } (#{ Process.pid }):",
       msg].join("\t") << "\n"
   end

   # Default priority 'nice' level.
   DEFAULT_PRIORITY = 1

   def initialize
      @queues         = []
      @container      = nil
      @log_dir        = DEFAULT_LOG_DIRECTORY
      @log_level      = Logger::INFO
      @log_shift_age  = DEFAULT_LOG_SHIFT_AGE
      @log_shift_size = DEFAULT_LOG_SHIFT_SIZE
      @priority       = DEFAULT_PRIORITY

      with_store(csv: TaskStore::SimpleCommaStore::DEFAULT_FILE) do
         if block_given?
            yield(self)
            raise SetupError, SetupError::ERR_NO_QUEUE if @queues.empty?
         end
      end

      @log_dir = @log_dir.expand_path

      @queues.freeze
      freeze
   end

   # Collection of all of the methods intended for use within Procrastinator.setup
   #
   # @see Procrastinator
   module DSL
      # Assigns a task loader
      def with_store(store)
         raise(ArgumentError, 'with_store must be provided a block') unless block_given?

         old_store      = @default_store
         @default_store = interpret_store(store)
         yield
         @default_store = old_store
      end

      # Defines the container to assign to each Task Handler's :container attribute.
      #
      # @param container [Object] the container
      def provide_container(container)
         @container = container
      end

      # Defines a queue in the Procrastinator Scheduler.
      #
      # The Task Handler will be initialized for each task and assigned each of these attributes:
      #    :container, :logger, :scheduler
      #
      # @param name [Symbol, String] the identifier to label the queue. Referenced in #defer calls
      # @param task_class [Class] the Task Handler class.
      # @param properties [Hash] Settings options object for this queue
      # @option properties [Object] :store (Procrastinator::TaskStore::SimpleCommaStore)
      #                                    Storage strategy for tasks in the queue.
      # @option properties [Integer] :max_attempts (Procrastinator::Queue::DEFAULT_MAX_ATTEMPTS)
      #                                            Maximum number of times a task may be attempted before giving up.
      # @option properties [Integer] :timeout (Procrastinator::Queue::DEFAULT_TIMEOUT)
      #                                       Maximum number of seconds to wait for a single task to complete.
      # @option properties [Integer] :update_period (Procrastinator::Queue::DEFAULT_UPDATE_PERIOD)
      #                                             Time to wait before checking for new tasks.
      def define_queue(name, task_class, properties = {})
         raise ArgumentError, 'queue name cannot be nil' if name.nil?
         raise ArgumentError, 'queue task class cannot be nil' if task_class.nil?

         properties[:store] = interpret_store(properties[:store]) if properties.key? :store

         args = {name: name, task_class: task_class, store: @default_store}.merge(properties)

         @queues << Queue.new(**args)
      end

      # Sets details of logging behaviour
      #
      # @param directory [Pathname,String] the directory to save logs within.
      # @param level [Logger::UNKNOWN,Logger::FATAL,Logger::ERROR,Logger::WARN,Logger::INFO,Logger::DEBUG,Integer,Boolean] the Ruby Logger level to use. If falsey, no logging is performed.
      # @param shift_age [Integer] number of old log files to keep (see Ruby Logger for details)
      # @param shift_size [Integer] filesize before log is rotated to a fresh file (see Ruby Logger for details)
      def log_with(directory: @log_dir, level: @log_level, shift_age: @log_shift_age, shift_size: @log_shift_size)
         @log_dir        = directory ? Pathname.new(directory) : directory
         @log_level      = level
         @log_shift_age  = shift_age
         @log_shift_size = shift_size
      end

      # Sets the desired process 'nice' priority value adjustment. This value is added to whatever runtime priority
      # Procrastinator starts with.
      #
      # Higher numbers are more nice to other processes (lower priority); think of it as the position in line.
      # You can be more nice, but never less nice.
      #
      # @param new_priority [Number] the new priority.
      def adjust_priority(new_priority)
         @priority = new_priority
      end

      alias adjust_nice adjust_priority
   end

   include DSL

   def queue(name: nil)
      queue = if name
                 @queues.find do |q|
                    q.name == name
                 end
              else
                 if name.nil? && @queues.length > 1
                    raise ArgumentError,
                          "queue must be specified when more than one is defined. #{ known_queues }"
                 end

                 @queues.first
              end

      raise ArgumentError, "there is no :#{ name } queue registered. #{ known_queues }" unless queue

      queue
   end

   private

   def known_queues
      "Known queues are: #{ @queues.map { |queue| ":#{ queue.name }" }.join(', ') }"
   end

   def interpret_store(store)
      raise(ArgumentError, 'task store cannot be nil') if store.nil?

      case store
      when Hash
         store_strategy = :csv
         unless store.key? store_strategy
            raise ArgumentError, "Must pass keyword :#{ store_strategy } if specifying a location for CSV file"
         end

         TaskStore::SimpleCommaStore.new(store[store_strategy])
      when String, Pathname
         TaskStore::SimpleCommaStore.new(store)
      else
         store
      end
   end

   # Raised when there is an error in the setup configuration.
   class SetupError < RuntimeError
      # Standard error message for when there is no queue defined
      ERR_NO_QUEUE = 'setup block must call #define_queue on the environment'
   end
end

#:queues(: queues) ⇒ Array (readonly)

Returns List of defined queues.

Returns:

  • (Array)

    List of defined queues



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
# File 'lib/procrastinator/config.rb', line 25

class Config
   attr_reader :queues, :log_dir, :log_level, :log_shift_age, :log_shift_size, :container, :priority

   alias nice priority

   # Default directory to keep logs in.
   DEFAULT_LOG_DIRECTORY = Pathname.new('log').freeze

   # Default age to keep log files for.
   # @see Logger
   DEFAULT_LOG_SHIFT_AGE = 0

   # Default max size to keep log files under.
   # @see Logger
   DEFAULT_LOG_SHIFT_SIZE = 2 ** 20 # 1 MB

   # Default log formatter
   # @see Logger
   DEFAULT_LOG_FORMATTER = proc do |severity, datetime, progname, msg|
      [datetime.iso8601(8),
       severity,
       "#{ progname } (#{ Process.pid }):",
       msg].join("\t") << "\n"
   end

   # Default priority 'nice' level.
   DEFAULT_PRIORITY = 1

   def initialize
      @queues         = []
      @container      = nil
      @log_dir        = DEFAULT_LOG_DIRECTORY
      @log_level      = Logger::INFO
      @log_shift_age  = DEFAULT_LOG_SHIFT_AGE
      @log_shift_size = DEFAULT_LOG_SHIFT_SIZE
      @priority       = DEFAULT_PRIORITY

      with_store(csv: TaskStore::SimpleCommaStore::DEFAULT_FILE) do
         if block_given?
            yield(self)
            raise SetupError, SetupError::ERR_NO_QUEUE if @queues.empty?
         end
      end

      @log_dir = @log_dir.expand_path

      @queues.freeze
      freeze
   end

   # Collection of all of the methods intended for use within Procrastinator.setup
   #
   # @see Procrastinator
   module DSL
      # Assigns a task loader
      def with_store(store)
         raise(ArgumentError, 'with_store must be provided a block') unless block_given?

         old_store      = @default_store
         @default_store = interpret_store(store)
         yield
         @default_store = old_store
      end

      # Defines the container to assign to each Task Handler's :container attribute.
      #
      # @param container [Object] the container
      def provide_container(container)
         @container = container
      end

      # Defines a queue in the Procrastinator Scheduler.
      #
      # The Task Handler will be initialized for each task and assigned each of these attributes:
      #    :container, :logger, :scheduler
      #
      # @param name [Symbol, String] the identifier to label the queue. Referenced in #defer calls
      # @param task_class [Class] the Task Handler class.
      # @param properties [Hash] Settings options object for this queue
      # @option properties [Object] :store (Procrastinator::TaskStore::SimpleCommaStore)
      #                                    Storage strategy for tasks in the queue.
      # @option properties [Integer] :max_attempts (Procrastinator::Queue::DEFAULT_MAX_ATTEMPTS)
      #                                            Maximum number of times a task may be attempted before giving up.
      # @option properties [Integer] :timeout (Procrastinator::Queue::DEFAULT_TIMEOUT)
      #                                       Maximum number of seconds to wait for a single task to complete.
      # @option properties [Integer] :update_period (Procrastinator::Queue::DEFAULT_UPDATE_PERIOD)
      #                                             Time to wait before checking for new tasks.
      def define_queue(name, task_class, properties = {})
         raise ArgumentError, 'queue name cannot be nil' if name.nil?
         raise ArgumentError, 'queue task class cannot be nil' if task_class.nil?

         properties[:store] = interpret_store(properties[:store]) if properties.key? :store

         args = {name: name, task_class: task_class, store: @default_store}.merge(properties)

         @queues << Queue.new(**args)
      end

      # Sets details of logging behaviour
      #
      # @param directory [Pathname,String] the directory to save logs within.
      # @param level [Logger::UNKNOWN,Logger::FATAL,Logger::ERROR,Logger::WARN,Logger::INFO,Logger::DEBUG,Integer,Boolean] the Ruby Logger level to use. If falsey, no logging is performed.
      # @param shift_age [Integer] number of old log files to keep (see Ruby Logger for details)
      # @param shift_size [Integer] filesize before log is rotated to a fresh file (see Ruby Logger for details)
      def log_with(directory: @log_dir, level: @log_level, shift_age: @log_shift_age, shift_size: @log_shift_size)
         @log_dir        = directory ? Pathname.new(directory) : directory
         @log_level      = level
         @log_shift_age  = shift_age
         @log_shift_size = shift_size
      end

      # Sets the desired process 'nice' priority value adjustment. This value is added to whatever runtime priority
      # Procrastinator starts with.
      #
      # Higher numbers are more nice to other processes (lower priority); think of it as the position in line.
      # You can be more nice, but never less nice.
      #
      # @param new_priority [Number] the new priority.
      def adjust_priority(new_priority)
         @priority = new_priority
      end

      alias adjust_nice adjust_priority
   end

   include DSL

   def queue(name: nil)
      queue = if name
                 @queues.find do |q|
                    q.name == name
                 end
              else
                 if name.nil? && @queues.length > 1
                    raise ArgumentError,
                          "queue must be specified when more than one is defined. #{ known_queues }"
                 end

                 @queues.first
              end

      raise ArgumentError, "there is no :#{ name } queue registered. #{ known_queues }" unless queue

      queue
   end

   private

   def known_queues
      "Known queues are: #{ @queues.map { |queue| ":#{ queue.name }" }.join(', ') }"
   end

   def interpret_store(store)
      raise(ArgumentError, 'task store cannot be nil') if store.nil?

      case store
      when Hash
         store_strategy = :csv
         unless store.key? store_strategy
            raise ArgumentError, "Must pass keyword :#{ store_strategy } if specifying a location for CSV file"
         end

         TaskStore::SimpleCommaStore.new(store[store_strategy])
      when String, Pathname
         TaskStore::SimpleCommaStore.new(store)
      else
         store
      end
   end

   # Raised when there is an error in the setup configuration.
   class SetupError < RuntimeError
      # Standard error message for when there is no queue defined
      ERR_NO_QUEUE = 'setup block must call #define_queue on the environment'
   end
end

#containerObject (readonly)

Returns the value of attribute container.



26
27
28
# File 'lib/procrastinator/config.rb', line 26

def container
  @container
end

#log_dirObject (readonly)

Returns the value of attribute log_dir.



26
27
28
# File 'lib/procrastinator/config.rb', line 26

def log_dir
  @log_dir
end

#log_levelObject (readonly)

Returns the value of attribute log_level.



26
27
28
# File 'lib/procrastinator/config.rb', line 26

def log_level
  @log_level
end

#log_shift_ageObject (readonly)

Returns the value of attribute log_shift_age.



26
27
28
# File 'lib/procrastinator/config.rb', line 26

def log_shift_age
  @log_shift_age
end

#log_shift_sizeObject (readonly)

Returns the value of attribute log_shift_size.



26
27
28
# File 'lib/procrastinator/config.rb', line 26

def log_shift_size
  @log_shift_size
end

#priorityObject (readonly) Also known as: nice

Returns the value of attribute priority.



26
27
28
# File 'lib/procrastinator/config.rb', line 26

def priority
  @priority
end

#queuesObject (readonly)

Returns the value of attribute queues.



26
27
28
# File 'lib/procrastinator/config.rb', line 26

def queues
  @queues
end

Instance Method Details

#queue(name: nil) ⇒ Object

Raises:

  • (ArgumentError)


152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
# File 'lib/procrastinator/config.rb', line 152

def queue(name: nil)
   queue = if name
              @queues.find do |q|
                 q.name == name
              end
           else
              if name.nil? && @queues.length > 1
                 raise ArgumentError,
                       "queue must be specified when more than one is defined. #{ known_queues }"
              end

              @queues.first
           end

   raise ArgumentError, "there is no :#{ name } queue registered. #{ known_queues }" unless queue

   queue
end