burner 1.6.0 → 1.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/.tool-versions +1 -0
  3. data/CHANGELOG.md +36 -0
  4. data/README.md +60 -2
  5. data/lib/burner/data.rb +46 -0
  6. data/lib/burner/job.rb +2 -10
  7. data/lib/burner/job_set.rb +64 -0
  8. data/lib/burner/job_with_register.rb +8 -1
  9. data/lib/burner/jobs.rb +7 -0
  10. data/lib/burner/library.rb +7 -0
  11. data/lib/burner/library/collection/arrays_to_objects.rb +1 -1
  12. data/lib/burner/library/collection/coalesce.rb +14 -9
  13. data/lib/burner/library/collection/concatenate.rb +1 -1
  14. data/lib/burner/library/collection/graph.rb +1 -1
  15. data/lib/burner/library/collection/group.rb +15 -11
  16. data/lib/burner/library/collection/nested_aggregate.rb +1 -1
  17. data/lib/burner/library/collection/number.rb +51 -0
  18. data/lib/burner/library/collection/objects_to_arrays.rb +1 -1
  19. data/lib/burner/library/collection/pivot.rb +150 -0
  20. data/lib/burner/library/collection/shift.rb +1 -1
  21. data/lib/burner/library/collection/transform.rb +1 -1
  22. data/lib/burner/library/collection/unpivot.rb +1 -1
  23. data/lib/burner/library/collection/validate.rb +1 -1
  24. data/lib/burner/library/collection/values.rb +1 -1
  25. data/lib/burner/library/collection/zip.rb +1 -1
  26. data/lib/burner/library/compress/row_reader.rb +1 -1
  27. data/lib/burner/library/deserialize/yaml.rb +1 -1
  28. data/lib/burner/library/echo.rb +1 -1
  29. data/lib/burner/library/io/exist.rb +1 -1
  30. data/lib/burner/library/io/open_file_base.rb +1 -1
  31. data/lib/burner/library/io/row_reader.rb +1 -1
  32. data/lib/burner/library/io/write.rb +1 -1
  33. data/lib/burner/library/param/base.rb +29 -0
  34. data/lib/burner/library/param/from_register.rb +30 -0
  35. data/lib/burner/library/param/to_register.rb +28 -0
  36. data/lib/burner/library/serialize/csv.rb +1 -1
  37. data/lib/burner/library/sleep.rb +1 -1
  38. data/lib/burner/library/value/copy.rb +1 -1
  39. data/lib/burner/library/value/nest.rb +37 -0
  40. data/lib/burner/library/value/static.rb +1 -1
  41. data/lib/burner/library/value/transform.rb +38 -0
  42. data/lib/burner/payload.rb +39 -15
  43. data/lib/burner/pipeline.rb +6 -34
  44. data/lib/burner/util.rb +1 -0
  45. data/lib/burner/util/keyable.rb +23 -0
  46. data/lib/burner/version.rb +1 -1
  47. metadata +16 -5
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Copyright (c) 2020-present, Blue Marble Payroll, LLC
5
+ #
6
+ # This source code is licensed under the MIT license found in the
7
+ # LICENSE file in the root directory of this source tree.
8
+ #
9
+
10
+ require_relative 'base'
11
+
12
+ module Burner
13
+ module Library
14
+ module Param
15
+ # Copy a register's value into a param key. Generally speaking you should only be
16
+ # mutating registers, that way the params stay true to the passed in params for the
17
+ # pipeline. But this job is available in case a param needs to be updated.
18
+ #
19
+ # Expected Payload[register] input: anything.
20
+ # Payload.params(param_key) output: whatever value was specified in the register.
21
+ class FromRegister < Base
22
+ def perform(output, payload)
23
+ output.detail("Pushing value from register: #{register} to param: #{param_key}")
24
+
25
+ payload.update_param(param_key, payload[register])
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Copyright (c) 2020-present, Blue Marble Payroll, LLC
5
+ #
6
+ # This source code is licensed under the MIT license found in the
7
+ # LICENSE file in the root directory of this source tree.
8
+ #
9
+
10
+ require_relative 'base'
11
+
12
+ module Burner
13
+ module Library
14
+ module Param
15
+ # Copy a param key's value into a register.
16
+ #
17
+ # Expected Payload.param(param_key) input: anything.
18
+ # Payload[register] output: whatever value was specified as the param_key's value.
19
+ class ToRegister < Base
20
+ def perform(output, payload)
21
+ output.detail("Pushing value to register: #{register} from param: #{param_key}")
22
+
23
+ payload[register] = payload.param(param_key)
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -18,7 +18,7 @@ module Burner
18
18
  class Csv < JobWithRegister
19
19
  attr_reader :byte_order_mark
20
20
 
21
- def initialize(name:, byte_order_mark: nil, register: DEFAULT_REGISTER)
21
+ def initialize(byte_order_mark: nil, name: '', register: DEFAULT_REGISTER)
22
22
  super(name: name, register: register)
23
23
 
24
24
  @byte_order_mark = Modeling::ByteOrderMark.resolve(byte_order_mark)
@@ -15,7 +15,7 @@ module Burner
15
15
  class Sleep < Job
16
16
  attr_reader :seconds
17
17
 
18
- def initialize(name:, seconds: 0)
18
+ def initialize(name: '', seconds: 0)
19
19
  super(name: name)
20
20
 
21
21
  @seconds = seconds.to_f
@@ -19,7 +19,7 @@ module Burner
19
19
  class Copy < Job
20
20
  attr_reader :from_register, :to_register
21
21
 
22
- def initialize(name:, to_register: DEFAULT_REGISTER, from_register: DEFAULT_REGISTER)
22
+ def initialize(from_register: DEFAULT_REGISTER, name: '', to_register: DEFAULT_REGISTER)
23
23
  super(name: name)
24
24
 
25
25
  @from_register = from_register.to_s
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Copyright (c) 2020-present, Blue Marble Payroll, LLC
5
+ #
6
+ # This source code is licensed under the MIT license found in the
7
+ # LICENSE file in the root directory of this source tree.
8
+ #
9
+
10
+ module Burner
11
+ module Library
12
+ module Value
13
+ # This job will nest the current value within a new outer hash. The specified key
14
+ # passed in will be the corresponding new hash key entry for the existing value.
15
+ #
16
+ # Expected Payload[from_register] input: anything.
17
+ # Payload[to_register] output: hash.
18
+ class Nest < JobWithRegister
19
+ DEFAULT_KEY = 'key'
20
+
21
+ attr_reader :key
22
+
23
+ def initialize(key: DEFAULT_KEY, name: '', register: Burner::DEFAULT_REGISTER)
24
+ super(name: name, register: register)
25
+
26
+ @key = key.to_s
27
+
28
+ freeze
29
+ end
30
+
31
+ def perform(_output, payload)
32
+ payload[register] = { key => payload[register] }
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -17,7 +17,7 @@ module Burner
17
17
  class Static < JobWithRegister
18
18
  attr_reader :value
19
19
 
20
- def initialize(name:, register: DEFAULT_REGISTER, value: nil)
20
+ def initialize(name: '', register: DEFAULT_REGISTER, value: nil)
21
21
  super(name: name, register: register)
22
22
 
23
23
  @value = value
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Copyright (c) 2020-present, Blue Marble Payroll, LLC
5
+ #
6
+ # This source code is licensed under the MIT license found in the
7
+ # LICENSE file in the root directory of this source tree.
8
+ #
9
+
10
+ module Burner
11
+ module Library
12
+ module Value
13
+ # Transform the current value of the register through a Realize::Pipeline. This will
14
+ # transform the entire value, as opposed to the b/collection/transform job, which will
15
+ # iterate over each row/record in a dataset and transform each row/record.
16
+ #
17
+ # Expected Payload[register] input: anything.
18
+ # Payload[register] output: anything.
19
+ class Transform < JobWithRegister
20
+ attr_reader :pipeline
21
+
22
+ def initialize(name: '', register: DEFAULT_REGISTER, separator: '', transformers: [])
23
+ super(name: name, register: register)
24
+
25
+ resolver = Objectable.resolver(separator: separator)
26
+
27
+ @pipeline = Realize::Pipeline.new(transformers, resolver: resolver)
28
+
29
+ freeze
30
+ end
31
+
32
+ def perform(_output, payload)
33
+ payload[register] = pipeline.transform(payload[register], payload.time)
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -7,6 +7,8 @@
7
7
  # LICENSE file in the root directory of this source tree.
8
8
  #
9
9
 
10
+ require_relative 'data'
11
+
10
12
  module Burner
11
13
  # The input for all Job#perform methods. The main notion of this object is its 'registers'
12
14
  # attribute. This registers attribute is a key-indifferent hash, accessible on Payload using
@@ -24,10 +26,15 @@ module Burner
24
26
  # The 'time' attribute is important in that it should for the replaying of pipelines and jobs.
25
27
  # Instead of having job's utilizing Time.now, Date.today, etc... they should rather opt to
26
28
  # use this value instead.
29
+ #
30
+ # The notion of params are somewhat conflated with registers here. Both are hashes and both
31
+ # serve as data stores. The difference is registers are really meant to be the shared-data
32
+ # repository across jobs, while params are, more or less, the input into the _pipeline_.
33
+ # It is debatable if mutation of the params should be allowed but the design decision was made
34
+ # early on to allow for params to be mutable albeit with registers being the preferred mutable
35
+ # store.
27
36
  class Payload
28
- attr_reader :params,
29
- :registers,
30
- :side_effects,
37
+ attr_reader :side_effects,
31
38
  :time
32
39
 
33
40
  def initialize(
@@ -36,12 +43,32 @@ module Burner
36
43
  side_effects: [],
37
44
  time: Time.now.utc
38
45
  )
39
- @params = params || {}
40
- @registers = {}
46
+ @params = Data.new(params)
47
+ @registers = Data.new(registers)
41
48
  @side_effects = side_effects || []
42
49
  @time = time || Time.now.utc
50
+ end
43
51
 
44
- add_registers(registers)
52
+ # Backwards compatibility. This allows for control over the underlying data structure
53
+ # while still maintaining the same public API as before.
54
+ def params
55
+ @params.to_h
56
+ end
57
+
58
+ # Backwards compatibility. This allows for control over the underlying data structure
59
+ # while still maintaining the same public API as before.
60
+ def registers
61
+ @registers.to_h
62
+ end
63
+
64
+ # Law of Demeter: While params is an accessible hash, it is preferred that the
65
+ # public class methods are used.
66
+ def param(key)
67
+ @params[key]
68
+ end
69
+
70
+ def update_param(key, value)
71
+ tap { @params[key] = value }
45
72
  end
46
73
 
47
74
  # Add a side effect of a job. This helps to keep track of things jobs do outside of its
@@ -52,12 +79,12 @@ module Burner
52
79
 
53
80
  # Set a register's value.
54
81
  def []=(key, value)
55
- set(key, value)
82
+ @registers[key] = value
56
83
  end
57
84
 
58
85
  # Retrieve a register's value.
59
86
  def [](key)
60
- registers[key.to_s]
87
+ @registers[key]
61
88
  end
62
89
 
63
90
  # Set halt_pipeline to true. This will indicate to the pipeline to stop all
@@ -71,14 +98,11 @@ module Burner
71
98
  @halt_pipeline || false
72
99
  end
73
100
 
74
- private
75
-
76
- def set(key, value)
77
- registers[key.to_s] = value
78
- end
101
+ def params_and_registers_hash
102
+ registers_hash = @registers.transform_keys { |key| "__#{key}_register" }
103
+ params_hash = @params.to_h
79
104
 
80
- def add_registers(registers)
81
- (registers || {}).each { |k, v| set(k, v) }
105
+ params_hash.merge(registers_hash)
82
106
  end
83
107
  end
84
108
  end
@@ -7,7 +7,7 @@
7
7
  # LICENSE file in the root directory of this source tree.
8
8
  #
9
9
 
10
- require_relative 'jobs'
10
+ require_relative 'job_set'
11
11
  require_relative 'output'
12
12
  require_relative 'payload'
13
13
  require_relative 'step'
@@ -19,27 +19,13 @@ module Burner
19
19
  class Pipeline
20
20
  acts_as_hashable
21
21
 
22
- class JobNotFoundError < StandardError; end
23
- class DuplicateJobNameError < StandardError; end
24
-
25
22
  attr_reader :steps
26
23
 
27
24
  def initialize(jobs: [], steps: nil)
28
- jobs = Jobs.array(jobs)
29
-
30
- assert_unique_job_names(jobs)
31
-
32
- jobs_by_name = jobs.map { |job| [job.name, job] }.to_h
33
-
34
- step_names = steps ? Array(steps) : jobs_by_name.keys
35
-
36
- @steps = step_names.map do |step_name|
37
- job = jobs_by_name[step_name.to_s]
38
-
39
- raise JobNotFoundError, "#{step_name} was not declared as a job" unless job
40
-
41
- Step.new(job)
42
- end
25
+ @steps = JobSet
26
+ .new(jobs)
27
+ .jobs(steps)
28
+ .map { |job| Step.new(job) }
43
29
  end
44
30
 
45
31
  # The main entry-point for kicking off a pipeline.
@@ -68,22 +54,8 @@ module Burner
68
54
 
69
55
  private
70
56
 
71
- def assert_unique_job_names(jobs)
72
- unique_job_names = Set.new
73
-
74
- jobs.each do |job|
75
- if unique_job_names.include?(job.name)
76
- raise DuplicateJobNameError, "job with name: #{job.name} already declared"
77
- end
78
-
79
- unique_job_names << job.name
80
- end
81
-
82
- nil
83
- end
84
-
85
57
  def output_params(params, output)
86
- if params.keys.any?
58
+ if params.any?
87
59
  output.write('Parameters:')
88
60
  else
89
61
  output.write('No parameters passed in.')
data/lib/burner/util.rb CHANGED
@@ -8,4 +8,5 @@
8
8
  #
9
9
 
10
10
  require_relative 'util/arrayable'
11
+ require_relative 'util/keyable'
11
12
  require_relative 'util/string_template'
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Copyright (c) 2020-present, Blue Marble Payroll, LLC
5
+ #
6
+ # This source code is licensed under the MIT license found in the
7
+ # LICENSE file in the root directory of this source tree.
8
+ #
9
+
10
+ module Burner
11
+ module Util
12
+ # Provide helper methods for keys.
13
+ module Keyable
14
+ def make_key(record, keys, resolver, insensitive)
15
+ keys.map do |key|
16
+ value = resolver.get(record, key)
17
+
18
+ insensitive ? value.to_s.downcase : value
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -8,5 +8,5 @@
8
8
  #
9
9
 
10
10
  module Burner
11
- VERSION = '1.6.0'
11
+ VERSION = '1.9.0'
12
12
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: burner
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.6.0
4
+ version: 1.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matthew Ruggio
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-12-22 00:00:00.000000000 Z
11
+ date: 2021-04-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: acts_as_hashable
@@ -220,6 +220,7 @@ files:
220
220
  - ".gitignore"
221
221
  - ".rubocop.yml"
222
222
  - ".ruby-version"
223
+ - ".tool-versions"
223
224
  - ".travis.yml"
224
225
  - CHANGELOG.md
225
226
  - CODE_OF_CONDUCT.md
@@ -234,9 +235,11 @@ files:
234
235
  - exe/burner
235
236
  - lib/burner.rb
236
237
  - lib/burner/cli.rb
238
+ - lib/burner/data.rb
237
239
  - lib/burner/disks.rb
238
240
  - lib/burner/disks/local.rb
239
241
  - lib/burner/job.rb
242
+ - lib/burner/job_set.rb
240
243
  - lib/burner/job_with_register.rb
241
244
  - lib/burner/jobs.rb
242
245
  - lib/burner/library.rb
@@ -246,7 +249,9 @@ files:
246
249
  - lib/burner/library/collection/graph.rb
247
250
  - lib/burner/library/collection/group.rb
248
251
  - lib/burner/library/collection/nested_aggregate.rb
252
+ - lib/burner/library/collection/number.rb
249
253
  - lib/burner/library/collection/objects_to_arrays.rb
254
+ - lib/burner/library/collection/pivot.rb
250
255
  - lib/burner/library/collection/shift.rb
251
256
  - lib/burner/library/collection/transform.rb
252
257
  - lib/burner/library/collection/unpivot.rb
@@ -264,12 +269,17 @@ files:
264
269
  - lib/burner/library/io/row_reader.rb
265
270
  - lib/burner/library/io/write.rb
266
271
  - lib/burner/library/nothing.rb
272
+ - lib/burner/library/param/base.rb
273
+ - lib/burner/library/param/from_register.rb
274
+ - lib/burner/library/param/to_register.rb
267
275
  - lib/burner/library/serialize/csv.rb
268
276
  - lib/burner/library/serialize/json.rb
269
277
  - lib/burner/library/serialize/yaml.rb
270
278
  - lib/burner/library/sleep.rb
271
279
  - lib/burner/library/value/copy.rb
280
+ - lib/burner/library/value/nest.rb
272
281
  - lib/burner/library/value/static.rb
282
+ - lib/burner/library/value/transform.rb
273
283
  - lib/burner/modeling.rb
274
284
  - lib/burner/modeling/attribute.rb
275
285
  - lib/burner/modeling/attribute_renderer.rb
@@ -288,6 +298,7 @@ files:
288
298
  - lib/burner/step.rb
289
299
  - lib/burner/util.rb
290
300
  - lib/burner/util/arrayable.rb
301
+ - lib/burner/util/keyable.rb
291
302
  - lib/burner/util/string_template.rb
292
303
  - lib/burner/version.rb
293
304
  homepage: https://github.com/bluemarblepayroll/burner
@@ -299,7 +310,7 @@ metadata:
299
310
  documentation_uri: https://www.rubydoc.info/gems/burner
300
311
  homepage_uri: https://github.com/bluemarblepayroll/burner
301
312
  source_code_uri: https://github.com/bluemarblepayroll/burner
302
- post_install_message:
313
+ post_install_message:
303
314
  rdoc_options: []
304
315
  require_paths:
305
316
  - lib
@@ -315,7 +326,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
315
326
  version: '0'
316
327
  requirements: []
317
328
  rubygems_version: 3.0.3
318
- signing_key:
329
+ signing_key:
319
330
  specification_version: 4
320
331
  summary: Declarative and extendable processing pipeline
321
332
  test_files: []