burner 1.2.0 → 1.3.0.pre.alpha

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a2c3e9af2bbfbf80cd5c5884e05b1282f52871566103baf4ca1b599fc76af8ca
4
- data.tar.gz: e7c2eb8a00086e1937a4d9e39383d38a60c5ebaa5efa1d67da4e6af9741261cd
3
+ metadata.gz: 340ebade1c4d3cc238925cb21718571dd666c3c16b6ee60d8de73c4fe017d562
4
+ data.tar.gz: 33b272e7a4b4a15a8e92b5f7eccb9df7ec6d685f767ecbf8434dedcf7ed901b5
5
5
  SHA512:
6
- metadata.gz: e885c7bf710f613323bbc3fc49162815632d7785aa6e753f3cd53bb04d2b53e74f92be549f75b6997d4dedce5c2dabe01fd032796a6d6e2fadfd6e84c633b168
7
- data.tar.gz: e09d491b3fb7ef1b79932ac6094adedd74f806170a2a11aa1ff1eda838b6bf76cec1684dbfaba12d07a6e071062d432bcd5f3939f275830fc13fb71cabb39f8c
6
+ metadata.gz: a5d082d14302d38e2acf89ab1275004ae69f78087e40da2a68c15e25770a9ebfc7fa2cb8e9e7268d132e2ade6c3d6db9e259ab3e8254ae476fcd1d46a4f40eb2
7
+ data.tar.gz: c1a9bda279afa44c5cb5a41c4ac792a62af317d91985799a14609c7b6d33e5494d322ad14262281b3fead76cc6471bebd7b507e1158dea7f9278196b36ab1726
@@ -1,3 +1,8 @@
1
+ # 1.3.0 (TBD)
2
+
3
+ Additions:
4
+
5
+ * Decoupled storage: `Burner::Disks` factory, `Burner::Disks::Local` reference implementation, and `b/io/*` `disk` option for configuring IO jobs to use custom disks.
1
6
  # 1.2.0 (November 25th, 2020)
2
7
 
3
8
  #### Enhancements:
data/README.md CHANGED
@@ -42,7 +42,7 @@ pipeline = {
42
42
  {
43
43
  name: :output_value,
44
44
  type: 'b/echo',
45
- message: 'The current value is: {__value}'
45
+ message: 'The current value is: {__default_register}'
46
46
  },
47
47
  {
48
48
  name: :parse,
@@ -89,7 +89,7 @@ Some notes:
89
89
 
90
90
  * Some values are able to be string-interpolated using the provided Payload#params. This allows for the passing runtime configuration/data into pipelines/jobs.
91
91
  * The job's ID can be accessed using the `__id` key.
92
- * The current job's payload value can be accessed using the `__value` key.
92
+ * The current payload registers' values can be accessed using the `__<register_name>_register` key.
93
93
  * Jobs can be re-used (just like the output_id and output_value jobs).
94
94
  * If steps is nil then all jobs will execute in their declared order.
95
95
 
@@ -163,7 +163,7 @@ jobs:
163
163
 
164
164
  - name: output_value
165
165
  type: b/echo
166
- message: 'The current value is: {__value}'
166
+ message: 'The current value is: {__default_register}'
167
167
 
168
168
  - name: parse
169
169
  type: b/deserialize/json
@@ -236,9 +236,11 @@ This library only ships with very basic, rudimentary jobs that are meant to just
236
236
 
237
237
  #### IO
238
238
 
239
- * **b/io/exist** [path, short_circuit]: Check to see if a file exists. The path parameter can be interpolated using `Payload#params`. If short_circuit was set to true (defaults to false) and the file does not exist then the pipeline will be short-circuited.
240
- * **b/io/read** [binary, path, register]: Read in a local file. The path parameter can be interpolated using `Payload#params`. If the contents are binary, pass in `binary: true` to open it up in binary+read mode.
241
- * **b/io/write** [binary, path, register]: Write to a local file. The path parameter can be interpolated using `Payload#params`. If the contents are binary, pass in `binary: true` to open it up in binary+write mode.
239
+ By default all jobs will use the `Burner::Disks::Local` disk for its persistence. But this is configurable by implementing and registering custom disk-based classes in the `Burner::Disks` factory. For example: a consumer application may also want to interact with cloud-based storage providers and could leverage this as its job library instead of implementing custom jobs.
240
+
241
+ * **b/io/exist** [disk, path, short_circuit]: Check to see if a file exists. The path parameter can be interpolated using `Payload#params`. If short_circuit was set to true (defaults to false) and the file does not exist then the pipeline will be short-circuited.
242
+ * **b/io/read** [binary, disk, path, register]: Read in a local file. The path parameter can be interpolated using `Payload#params`. If the contents are binary, pass in `binary: true` to open it up in binary+read mode.
243
+ * **b/io/write** [binary, disk, path, register]: Write to a local file. The path parameter can be interpolated using `Payload#params`. If the contents are binary, pass in `binary: true` to open it up in binary+write mode.
242
244
 
243
245
  #### Serialization
244
246
 
@@ -299,7 +301,7 @@ pipeline = {
299
301
  {
300
302
  name: :output_value,
301
303
  type: 'b/echo',
302
- message: 'The current value is: {__value}'
304
+ message: 'The current value is: {__default_register}'
303
305
  },
304
306
  {
305
307
  name: :parse,
@@ -10,6 +10,7 @@
10
10
  require 'acts_as_hashable'
11
11
  require 'benchmark'
12
12
  require 'csv'
13
+ require 'fileutils'
13
14
  require 'forwardable'
14
15
  require 'hash_math'
15
16
  require 'hashematics'
@@ -23,6 +24,7 @@ require 'time'
23
24
  require 'yaml'
24
25
 
25
26
  # Common/Shared
27
+ require_relative 'burner/disks'
26
28
  require_relative 'burner/modeling'
27
29
  require_relative 'burner/side_effects'
28
30
  require_relative 'burner/util'
@@ -0,0 +1,26 @@
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 'disks/local'
11
+
12
+ module Burner
13
+ # A factory to register and emit instances that conform to the Disk interface with requests
14
+ # the instance responds to: #exist?, #read, and #write. See an example implementation within
15
+ # the lib/burner/disks directory.
16
+ #
17
+ # The benefit to this pluggable disk model is a consumer application can decide which file
18
+ # backend to use and how to store files. For example: an application may choose to use
19
+ # some cloud provider with their own file store implementation. This can be wrapped up
20
+ # in a Disk class and registered here and then referenced in the Pipeline's IO jobs.
21
+ class Disks
22
+ acts_as_hashable_factory
23
+
24
+ register 'local', '', Disks::Local
25
+ end
26
+ end
@@ -0,0 +1,61 @@
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
+ class Disks
12
+ # Operations against the local file system.
13
+ class Local
14
+ acts_as_hashable
15
+
16
+ # Check to see if the passed in path exists within the local file system.
17
+ # It will not make assumptions on what the 'file' is, only that it is recognized
18
+ # by Ruby's File class.
19
+ def exist?(path)
20
+ File.exist?(path)
21
+ end
22
+
23
+ # Open and read the contents of a local file. If binary is passed in as true then the file
24
+ # will be opened in binary mode.
25
+ def read(path, binary: false)
26
+ File.open(path, read_mode(binary), &:read)
27
+ end
28
+
29
+ # Open and write the specified data to a local file. If binary is passed in as true then
30
+ # the file will be opened in binary mode. It is important to note that if the file's
31
+ # directory structure will be automatically created if it does not exist.
32
+ def write(path, data, binary: false)
33
+ ensure_directory_exists(path)
34
+
35
+ File.open(path, write_mode(binary)) { |io| io.write(data) }
36
+
37
+ path
38
+ end
39
+
40
+ private
41
+
42
+ def ensure_directory_exists(path)
43
+ dirname = File.dirname(path)
44
+
45
+ return if File.exist?(dirname)
46
+
47
+ FileUtils.mkdir_p(dirname)
48
+
49
+ nil
50
+ end
51
+
52
+ def write_mode(binary)
53
+ binary ? 'wb' : 'w'
54
+ end
55
+
56
+ def read_mode(binary)
57
+ binary ? 'rb' : 'r'
58
+ end
59
+ end
60
+ end
61
+ end
@@ -7,8 +7,6 @@
7
7
  # LICENSE file in the root directory of this source tree.
8
8
  #
9
9
 
10
- require_relative 'base'
11
-
12
10
  module Burner
13
11
  module Library
14
12
  module IO
@@ -17,13 +15,14 @@ module Burner
17
15
  #
18
16
  # Note: this does not use Payload#registers.
19
17
  class Exist < Job
20
- attr_reader :path, :short_circuit
18
+ attr_reader :disk, :path, :short_circuit
21
19
 
22
- def initialize(name:, path:, short_circuit: false)
20
+ def initialize(name:, path:, disk: {}, short_circuit: false)
23
21
  super(name: name)
24
22
 
25
23
  raise ArgumentError, 'path is required' if path.to_s.empty?
26
24
 
25
+ @disk = Disks.make(disk)
27
26
  @path = path.to_s
28
27
  @short_circuit = short_circuit || false
29
28
  end
@@ -31,7 +30,7 @@ module Burner
31
30
  def perform(output, payload)
32
31
  compiled_path = job_string_template(path, output, payload)
33
32
 
34
- exists = File.exist?(compiled_path)
33
+ exists = disk.exist?(compiled_path)
35
34
  verb = exists ? 'does' : 'does not'
36
35
 
37
36
  output.detail("The path: #{compiled_path} #{verb} exist")
@@ -10,16 +10,20 @@
10
10
  module Burner
11
11
  module Library
12
12
  module IO
13
- # Common configuration/code for all IO Job subclasses.
14
- class Base < JobWithRegister
15
- attr_reader :path
13
+ # Common configuration/code for all IO Job subclasses that open a file.
14
+ class OpenFileBase < JobWithRegister
15
+ attr_reader :binary, :disk, :path
16
16
 
17
- def initialize(name:, path:, register: DEFAULT_REGISTER)
17
+ def initialize(name:, path:, binary: false, disk: {}, register: DEFAULT_REGISTER)
18
18
  super(name: name, register: register)
19
19
 
20
20
  raise ArgumentError, 'path is required' if path.to_s.empty?
21
21
 
22
- @path = path.to_s
22
+ @binary = binary || false
23
+ @disk = Disks.make(disk)
24
+ @path = path.to_s
25
+
26
+ freeze
23
27
  end
24
28
  end
25
29
  end
@@ -7,7 +7,7 @@
7
7
  # LICENSE file in the root directory of this source tree.
8
8
  #
9
9
 
10
- require_relative 'base'
10
+ require_relative 'open_file_base'
11
11
 
12
12
  module Burner
13
13
  module Library
@@ -16,29 +16,13 @@ module Burner
16
16
  #
17
17
  # Expected Payload[register] input: nothing.
18
18
  # Payload[register] output: contents of the specified file.
19
- class Read < Base
20
- attr_reader :binary
21
-
22
- def initialize(name:, path:, binary: false, register: DEFAULT_REGISTER)
23
- super(name: name, path: path, register: register)
24
-
25
- @binary = binary || false
26
-
27
- freeze
28
- end
29
-
19
+ class Read < OpenFileBase
30
20
  def perform(output, payload)
31
21
  compiled_path = job_string_template(path, output, payload)
32
22
 
33
23
  output.detail("Reading: #{compiled_path}")
34
24
 
35
- payload[register] = File.open(compiled_path, mode, &:read)
36
- end
37
-
38
- private
39
-
40
- def mode
41
- binary ? 'rb' : 'r'
25
+ payload[register] = disk.read(compiled_path, binary: binary)
42
26
  end
43
27
  end
44
28
  end
@@ -7,7 +7,7 @@
7
7
  # LICENSE file in the root directory of this source tree.
8
8
  #
9
9
 
10
- require_relative 'base'
10
+ require_relative 'open_file_base'
11
11
 
12
12
  module Burner
13
13
  module Library
@@ -16,54 +16,27 @@ module Burner
16
16
  #
17
17
  # Expected Payload[register] input: anything.
18
18
  # Payload[register] output: whatever was passed in.
19
- class Write < Base
20
- attr_reader :binary
21
-
22
- def initialize(name:, path:, binary: false, register: DEFAULT_REGISTER)
23
- super(name: name, path: path, register: register)
24
-
25
- @binary = binary || false
26
-
27
- freeze
28
- end
29
-
19
+ class Write < OpenFileBase
30
20
  def perform(output, payload)
31
- compiled_path = job_string_template(path, output, payload)
32
-
33
- ensure_directory_exists(output, compiled_path)
21
+ logical_filename = job_string_template(path, output, payload)
22
+ physical_filename = nil
34
23
 
35
- output.detail("Writing: #{compiled_path}")
24
+ output.detail("Writing: #{logical_filename}")
36
25
 
37
26
  time_in_seconds = Benchmark.measure do
38
- File.open(compiled_path, mode) { |io| io.write(payload[register]) }
27
+ physical_filename = disk.write(logical_filename, payload[register], binary: binary)
39
28
  end.real
40
29
 
30
+ output.detail("Wrote to: #{physical_filename}")
31
+
41
32
  side_effect = SideEffects::WrittenFile.new(
42
- logical_filename: compiled_path,
43
- physical_filename: compiled_path,
33
+ logical_filename: logical_filename,
34
+ physical_filename: physical_filename,
44
35
  time_in_seconds: time_in_seconds
45
36
  )
46
37
 
47
38
  payload.add_side_effect(side_effect)
48
39
  end
49
-
50
- private
51
-
52
- def ensure_directory_exists(output, compiled_path)
53
- dirname = File.dirname(compiled_path)
54
-
55
- return if File.exist?(dirname)
56
-
57
- output.detail("Outer directory does not exist, creating: #{dirname}")
58
-
59
- FileUtils.mkdir_p(dirname)
60
-
61
- nil
62
- end
63
-
64
- def mode
65
- binary ? 'wb' : 'w'
66
- end
67
40
  end
68
41
  end
69
42
  end
@@ -8,5 +8,5 @@
8
8
  #
9
9
 
10
10
  module Burner
11
- VERSION = '1.2.0'
11
+ VERSION = '1.3.0-alpha'
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.2.0
4
+ version: 1.3.0.pre.alpha
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matthew Ruggio
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-11-25 00:00:00.000000000 Z
11
+ date: 2020-12-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: acts_as_hashable
@@ -220,6 +220,8 @@ files:
220
220
  - exe/burner
221
221
  - lib/burner.rb
222
222
  - lib/burner/cli.rb
223
+ - lib/burner/disks.rb
224
+ - lib/burner/disks/local.rb
223
225
  - lib/burner/job.rb
224
226
  - lib/burner/job_with_register.rb
225
227
  - lib/burner/jobs.rb
@@ -240,8 +242,8 @@ files:
240
242
  - lib/burner/library/deserialize/json.rb
241
243
  - lib/burner/library/deserialize/yaml.rb
242
244
  - lib/burner/library/echo.rb
243
- - lib/burner/library/io/base.rb
244
245
  - lib/burner/library/io/exist.rb
246
+ - lib/burner/library/io/open_file_base.rb
245
247
  - lib/burner/library/io/read.rb
246
248
  - lib/burner/library/io/write.rb
247
249
  - lib/burner/library/nothing.rb
@@ -290,9 +292,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
290
292
  version: '2.5'
291
293
  required_rubygems_version: !ruby/object:Gem::Requirement
292
294
  requirements:
293
- - - ">="
295
+ - - ">"
294
296
  - !ruby/object:Gem::Version
295
- version: '0'
297
+ version: 1.3.1
296
298
  requirements: []
297
299
  rubygems_version: 3.0.3
298
300
  signing_key: