metacrunch 2.2.3 → 3.0.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 (57) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +2 -1
  3. data/Gemfile +11 -13
  4. data/License.txt +1 -1
  5. data/Readme.md +139 -2
  6. data/bin/console +9 -6
  7. data/exe/metacrunch +1 -2
  8. data/lib/metacrunch/cli.rb +62 -14
  9. data/lib/metacrunch/db/reader.rb +27 -0
  10. data/lib/metacrunch/db/writer.rb +23 -0
  11. data/lib/metacrunch/db.rb +8 -0
  12. data/lib/metacrunch/fs/entry.rb +17 -0
  13. data/lib/metacrunch/{file_reader.rb → fs/reader.rb} +9 -10
  14. data/lib/metacrunch/fs.rb +6 -0
  15. data/lib/metacrunch/job/buffer.rb +26 -0
  16. data/lib/metacrunch/job/dsl/option_support.rb +102 -0
  17. data/lib/metacrunch/job/dsl.rb +42 -0
  18. data/lib/metacrunch/job.rb +149 -0
  19. data/lib/metacrunch/test_utils/dummy_callable.rb +14 -0
  20. data/lib/metacrunch/test_utils/dummy_destination.rb +21 -0
  21. data/lib/metacrunch/test_utils/dummy_source.rb +22 -0
  22. data/lib/metacrunch/test_utils.rb +7 -0
  23. data/lib/metacrunch/version.rb +1 -1
  24. data/lib/metacrunch.rb +14 -27
  25. data/metacrunch.gemspec +5 -10
  26. metadata +24 -144
  27. data/lib/metacrunch/cli/base.rb +0 -29
  28. data/lib/metacrunch/cli/command_definition.rb +0 -41
  29. data/lib/metacrunch/cli/command_registry.rb +0 -17
  30. data/lib/metacrunch/cli/main.rb +0 -16
  31. data/lib/metacrunch/command.rb +0 -27
  32. data/lib/metacrunch/file/reader/file_system_fetcher.rb +0 -21
  33. data/lib/metacrunch/file/reader/plain_file_reader.rb +0 -33
  34. data/lib/metacrunch/file/reader/scp_fetcher.rb +0 -56
  35. data/lib/metacrunch/file/reader/tar_file_reader.rb +0 -37
  36. data/lib/metacrunch/file/reader/zip_file_reader.rb +0 -30
  37. data/lib/metacrunch/file/reader.rb +0 -72
  38. data/lib/metacrunch/file/writer/plain_file_writer.rb +0 -19
  39. data/lib/metacrunch/file/writer/tar_file_writer.rb +0 -26
  40. data/lib/metacrunch/file/writer/zip_file_writer.rb +0 -29
  41. data/lib/metacrunch/file/writer.rb +0 -26
  42. data/lib/metacrunch/file.rb +0 -24
  43. data/lib/metacrunch/file_reader_entry.rb +0 -21
  44. data/lib/metacrunch/file_writer.rb +0 -40
  45. data/lib/metacrunch/hash.rb +0 -51
  46. data/lib/metacrunch/parallel.rb +0 -69
  47. data/lib/metacrunch/processor.rb +0 -10
  48. data/lib/metacrunch/snr/field.rb +0 -31
  49. data/lib/metacrunch/snr/section.rb +0 -74
  50. data/lib/metacrunch/snr.rb +0 -117
  51. data/lib/metacrunch/tar_writer.rb +0 -26
  52. data/lib/metacrunch/transformator/transformation/step.rb +0 -45
  53. data/lib/metacrunch/transformator/transformation.rb +0 -48
  54. data/lib/metacrunch/transformator.rb +0 -5
  55. data/lib/metacrunch/transformer/helper.rb +0 -29
  56. data/lib/metacrunch/transformer/step.rb +0 -37
  57. data/lib/metacrunch/transformer.rb +0 -38
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 071c720dfc2ad17aa71665f25579961eb1a0beea
4
- data.tar.gz: 622e3192f6021da9e5851485b7fb9181ec75e2c6
3
+ metadata.gz: 657c0cedb16066bee69a76a30a0e02783e5d0209
4
+ data.tar.gz: 7c0290c94a11af5daf8bfb40e0b0abab3f92c8df
5
5
  SHA512:
6
- metadata.gz: 6fe42cf29e183659f667cfac082cebebee345ab199a4fd99dd175a0ea1716ea3a5b38b3a4ce9ab13c790a4dc03d4775d343d55fe0593b43ba10eaac5557654c9
7
- data.tar.gz: f14bee54085db41b4ed15a6f551a9f6a1465541c896037a3674cafff4cbbab375574c0236b2e9c33b9c03e3fbef929d11e0aa473b11f4a8f763ef001c371e879
6
+ metadata.gz: ee0834cbe3f70238f1c5f7fbaf37284c0c7adedbdafe4c01e7b31819cfa8274585a4cd8407fd5cc35ca32c033f0944c86f872d09d8ee5d56ba22d48435898d4d
7
+ data.tar.gz: d9663a2b36247dcd20721e9e2016bc3f1d42dae47aa89acc671fb112437c925779bf5949edfb5409e3e6ff3aa2612216c93468847deb51ebc8b4ae6da064eb97
data/.travis.yml CHANGED
@@ -1,3 +1,4 @@
1
1
  language: ruby
2
2
  rvm:
3
- - "2.2.2"
3
+ - ruby-2.3.0
4
+ - jruby-9.0.5.0
data/Gemfile CHANGED
@@ -1,25 +1,23 @@
1
1
  source "https://rubygems.org"
2
2
 
3
- # Specify your gem's dependencies in your gemspec
4
3
  gemspec
5
4
 
6
5
  group :development do
7
- gem "bundler"
8
- gem "nokogiri"
9
- gem "rake"
10
- gem "rspec", ">= 3.0.0", "< 4.0.0"
11
- gem "simplecov", ">= 0.8.0"
6
+ gem "bundler", ">= 1.7"
7
+ gem "rake", ">= 11.1"
8
+ gem "rspec", ">= 3.0.0", "< 4.0.0"
9
+ gem "simplecov", ">= 0.11.0"
10
+ gem "sqlite3", ">= 1.3.11", platform: :ruby
11
+ gem "jdbc-sqlite3", ">= 3.8", platform: :jruby
12
12
 
13
13
  if !ENV["CI"]
14
- gem "hashdiff"
15
- gem "pry", "~> 0.9.12.6"
16
- gem "pry-byebug", "<= 1.3.2"
17
- gem "pry-rescue", "~> 1.4.2"
18
- gem "pry-stack_explorer", "~> 0.4.9.1"
19
- gem "pry-syntax-hacks", "~> 0.0.6"
14
+ gem "hashdiff", ">= 0.3.0", platform: :ruby
15
+ gem "pry-byebug", ">= 3.3.0", platform: :ruby
16
+ gem "pry-rescue", ">= 1.4.2", platform: :ruby
17
+ gem "pry-state", ">= 0.1.7", platform: :ruby
20
18
  end
21
19
  end
22
20
 
23
21
  group :test do
24
- gem "codeclimate-test-reporter", require: nil
22
+ gem "codeclimate-test-reporter", ">= 0.5.0", require: nil
25
23
  end
data/License.txt CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2013 René Sprotte, Michael Sievers, Marcel Otto
1
+ Copyright (c) 2016 René Sprotte, Michael Sievers, Marcel Otto
2
2
 
3
3
  MIT License
4
4
 
data/Readme.md CHANGED
@@ -1,7 +1,144 @@
1
- # metacrunch
1
+ metacrunch
2
+ ==========
2
3
 
3
4
  [![Gem Version](https://badge.fury.io/rb/metacrunch.svg)](http://badge.fury.io/rb/metacrunch)
4
5
  [![Code Climate](https://codeclimate.com/github/ubpb/metacrunch/badges/gpa.svg)](https://codeclimate.com/github/ubpb/metacrunch)
5
6
  [![Build Status](https://travis-ci.org/ubpb/metacrunch.svg)](https://travis-ci.org/ubpb/metacrunch)
6
7
 
7
- Dokumentation folgt in Kürze...
8
+ metacrunch is a simple and lightweight data processing and ETL ([Extract-Transform-Load](http://en.wikipedia.org/wiki/Extract,_transform,_load))
9
+ toolkit for Ruby.
10
+
11
+
12
+ Installation
13
+ ------------
14
+
15
+ ```
16
+ $ gem install metacrunch
17
+ ```
18
+
19
+
20
+ Create ETL jobs
21
+ ---------------
22
+
23
+ The basic idea behind an ETL job in metacrunch is the concept of a data processing pipeline. Each ETL job reads data from one or more **sources** (extract step), runs one or more **transformations** (transform step) on the data and finally writes the transformed data back to one or more **destinations** (load step).
24
+
25
+ metacrunch provides you with a simple DSL to define such ETL jobs. Just create a text file with the extension `.metacrunch`. Note: The extension doesn't really matter but you should avoid `.rb` to not loading them by mistake from another Ruby component.
26
+
27
+ Let's take a look at an example. For a collection of working examples check out our [metacrunch-demo](https://github.com/ubpb/metacrunch-demo) repo.
28
+
29
+ ```ruby
30
+ # File: my_etl_job.metacrunch
31
+
32
+ # Every metacrunch job file is a regular Ruby file. So you can always use regular Ruby
33
+ # stuff like declaring methods
34
+ def my_helper
35
+ # ...
36
+ end
37
+
38
+ # ... declaring classes
39
+ class MyHelper
40
+ # ...
41
+ end
42
+
43
+ # ... declaring variables
44
+ foo = "bar"
45
+
46
+ # ... or loading other ruby files
47
+ require_relative "./some/other/ruby/file"
48
+
49
+ # Declare a source (use a build-in or 3rd party source or implement it – see notes below).
50
+ # At least one source is required to allow the job to run.
51
+ source MySource.new
52
+ # ... maybe another one. Sources are processed in the order they are defined.
53
+ source MyOtherSource.new
54
+
55
+ # Declare a destination (use a build-in or 3rd party destination or implement it – see notes below).
56
+ # Technically a destination is optional, but a job that doesn't store it's
57
+ # output doesn't really makes sense.
58
+ destination MyDestination.new
59
+ # ... you can have more destinations if you like
60
+ destination MyOtherDestination.new
61
+
62
+ # To process data use the #transformation hook.
63
+ transformation do |data|
64
+ # Called for each data object that has been put in the pipeline by a source.
65
+
66
+ # Do your data transformation process here.
67
+
68
+ # You must return the data to keep it in the pipeline. Dismiss the
69
+ # data conditionally by returning nil.
70
+ data
71
+ end
72
+
73
+ # Instead of passing a block to #transformation you can pass a
74
+ # `callable` object (an object responding to #call).
75
+ transformation Proc.new {
76
+ # Procs and Lambdas responds to #call
77
+ }
78
+
79
+ # MyTransformation defines #call
80
+ transformation MyTransformation.new
81
+
82
+ # To run arbitrary code before the first transformation use the #pre_process hook.
83
+ pre_process do
84
+ # Called before the first transformation
85
+ end
86
+
87
+ # To run arbitrary code after the last transformation use the #post_process hook.
88
+ post_process do
89
+ # Called after the last transformation
90
+ end
91
+
92
+ # Instead of passing a block to #pre_process or #post_process you can pass a
93
+ # `callable` object (an object responding to #call).
94
+ pre_process Proc.new {
95
+ # Procs and Lambdas responds to #call
96
+ }
97
+
98
+ # MyCallable class defines #call
99
+ post_process MyCallable.new
100
+
101
+ ```
102
+
103
+
104
+ Run ETL jobs
105
+ ------------
106
+
107
+ metacrunch comes with a handy command line tool. In your terminal just call
108
+
109
+
110
+ ```
111
+ $ metacrunch run my_etl_job.metacrunch
112
+ ```
113
+
114
+ to run the job.
115
+
116
+ Implementing sources
117
+ --------------------
118
+
119
+ TBD.
120
+
121
+ Implementing transformations
122
+ ----------------------------
123
+
124
+ TBD.
125
+
126
+ Implementing writers
127
+ ---------------------
128
+
129
+ TBD.
130
+
131
+ Defining job dependencies
132
+ -------------------------
133
+
134
+ TBD.
135
+
136
+ Defining job options
137
+ --------------------
138
+
139
+ TBD.
140
+
141
+ License
142
+ -------
143
+
144
+ metacrunch is available at [github](https://github.com/ubpb/metacrunch) under [MIT license](https://github.com/ubpb/metacrunch/blob/master/License.txt).
data/bin/console CHANGED
@@ -1,11 +1,14 @@
1
1
  #!/usr/bin/env ruby
2
-
3
2
  require "bundler/setup"
4
3
  require "metacrunch"
5
4
 
6
- # You can add fixtures and/or initialization code here to make experimenting
7
- # with your gem easier. You can also use a different console, if you like.
5
+ begin
6
+ require "pry"
7
+ rescue LoadError ; end
8
8
 
9
- # (If you use this, don't forget to add pry to your Gemfile!)
10
- require "pry"
11
- Pry.start
9
+ if defined?(Pry)
10
+ Pry.start
11
+ else
12
+ require "irb"
13
+ IRB.start
14
+ end
data/exe/metacrunch CHANGED
@@ -1,4 +1,3 @@
1
1
  #!/usr/bin/env ruby
2
2
  require "metacrunch"
3
- Metacrunch.load_plugins
4
- Metacrunch::Cli.start(ARGV)
3
+ Metacrunch::Cli.new.run
@@ -1,26 +1,74 @@
1
1
  module Metacrunch
2
2
  class Cli
3
- require_relative "./cli/main"
4
- require_relative "./cli/base"
5
- require_relative "./cli/command_registry"
6
- require_relative "./cli/command_definition"
3
+ ARGS_SEPERATOR = "@@"
7
4
 
8
- def self.start(argv)
9
- Main.start(argv)
5
+ def run
6
+ init_commander!
7
+ init_run_command!
8
+ run_commander!
10
9
  end
11
10
 
12
- def self.setup(namespace, description, &block)
13
- klass = Class.new(Base)
14
- klass.namespace(namespace)
11
+ private
12
+ def commander
13
+ @commander ||= Commander::Runner.new(metacrunch_args)
14
+ end
15
+
16
+ def init_commander!
17
+ commander.program :name, "metacrunch"
18
+ commander.program :version, Metacrunch::VERSION
19
+ commander.program :description, "Data processing and ETL toolkit for Ruby."
20
+ commander.default_command :help
21
+ end
22
+
23
+ def run_commander!
24
+ commander.run!
25
+ end
26
+
27
+ def init_run_command!
28
+ commander.command :run do |c|
29
+ c.syntax = "metacrunch run [options] FILE [@@ job_options]"
30
+ c.description = "Runs a metacrunch job description."
31
+
32
+ c.action do |filenames, program_options|
33
+ if filenames.empty?
34
+ say "You need to provide a job description file."
35
+ exit(1)
36
+ elsif filenames.count > 1
37
+ say "You must provide exactly one job description file."
38
+ else
39
+ filename = File.expand_path(filenames.first)
40
+ dir = File.dirname(filename)
15
41
 
16
- registry = CommandRegistry.new
17
- yield(registry)
42
+ setup_bundler(dir)
18
43
 
19
- registry.commands.each do |c|
20
- klass.register_thor_command(c)
44
+ Dir.chdir(dir) do
45
+ contents = File.read(filename)
46
+ context = Metacrunch::Job.define(contents, filename: filename, args: job_args)
47
+ context.run
48
+ end
49
+ end
50
+ end
21
51
  end
52
+ end
53
+
54
+ def metacrunch_args
55
+ index = ARGV.index(ARGS_SEPERATOR)
56
+ @metacrunch_args ||= index ? ARGV[0..index-1] : ARGV
57
+ end
22
58
 
23
- Main.register(klass, namespace, "#{namespace} [COMMAND]", description)
59
+ def job_args
60
+ index = ARGV.index(ARGS_SEPERATOR)
61
+ @job_args ||= index ? ARGV[index+1..-1] : nil
24
62
  end
63
+
64
+ def setup_bundler(dir)
65
+ ENV['BUNDLE_GEMFILE'] ||= File.join(dir, "Gemfile")
66
+ if File.exists?(ENV['BUNDLE_GEMFILE'])
67
+ puts "Using Gemfile `#{ENV['BUNDLE_GEMFILE']}`."
68
+ Bundler.setup
69
+ Bundler.require
70
+ end
71
+ end
72
+
25
73
  end
26
74
  end
@@ -0,0 +1,27 @@
1
+ module Metacrunch
2
+ class Db::Reader
3
+
4
+ def initialize(database_connection_or_url, dataset_proc, options = {})
5
+ @rows_per_fetch = options.delete(:rows_per_fetch) || 1000
6
+
7
+ @db = if database_connection_or_url.is_a?(String)
8
+ Sequel.connect(database_connection_or_url, options)
9
+ else
10
+ database_connection_or_url
11
+ end
12
+
13
+ @dataset = dataset_proc.call(@db)
14
+ end
15
+
16
+ def each(&block)
17
+ return enum_for(__method__) unless block_given?
18
+
19
+ @dataset.paged_each(rows_per_fetch: @rows_per_fetch) do |row|
20
+ yield(row)
21
+ end
22
+
23
+ self
24
+ end
25
+
26
+ end
27
+ end
@@ -0,0 +1,23 @@
1
+ module Metacrunch
2
+ class Db::Writer
3
+
4
+ def initialize(database_connection_or_url, dataset_proc, options = {})
5
+ @db = if database_connection_or_url.is_a?(String)
6
+ Sequel.connect(database_connection_or_url, options)
7
+ else
8
+ database_connection_or_url
9
+ end
10
+
11
+ @dataset = dataset_proc.call(@db)
12
+ end
13
+
14
+ def write(data)
15
+ @dataset.insert(data)
16
+ end
17
+
18
+ def close
19
+ @db.disconnect
20
+ end
21
+
22
+ end
23
+ end
@@ -0,0 +1,8 @@
1
+ require "sequel"
2
+
3
+ module Metacrunch
4
+ class Db
5
+ require_relative "db/reader"
6
+ require_relative "db/writer"
7
+ end
8
+ end
@@ -0,0 +1,17 @@
1
+ module Metacrunch
2
+ class Fs::Entry
3
+
4
+ attr_reader :filename, :archive_filename, :contents
5
+
6
+ def initialize(filename:, archive_filename: nil, contents: nil)
7
+ @filename = filename
8
+ @archive_filename = archive_filename.presence
9
+ @contents = contents
10
+ end
11
+
12
+ def from_archive?
13
+ @archive_filename != nil
14
+ end
15
+
16
+ end
17
+ end
@@ -1,10 +1,9 @@
1
1
  require "rubygems/package"
2
- require_relative "./file_reader_entry"
3
2
 
4
3
  module Metacrunch
5
- class FileReader
4
+ class Fs::Reader
6
5
 
7
- def initialize(filenames)
6
+ def initialize(filenames = nil)
8
7
  @filenames = [*filenames].map{|f| f.presence}.compact
9
8
  end
10
9
 
@@ -23,27 +22,27 @@ module Metacrunch
23
22
  private
24
23
 
25
24
  def is_archive?(filename)
26
- filename.ends_with?(".tar") || filename.ends_with?(".tar.gz")
25
+ filename.ends_with?(".tar") || filename.ends_with?(".tar.gz") || filename.ends_with?(".tgz")
27
26
  end
28
27
 
29
28
  def is_gzip_file?(filename)
30
- filename.ends_with?(".gz")
29
+ filename.ends_with?(".gz") || filename.ends_with?(".tgz")
31
30
  end
32
31
 
33
32
  def read_regular_file(filename, &block)
34
- if ::File.file?(filename)
35
- io = is_gzip_file?(filename) ? Zlib::GzipReader.open(filename) : ::File.open(filename, "r")
36
- yield Entry.new(filename: filename, archive_filename: nil, contents: io.read)
33
+ if File.file?(filename)
34
+ io = is_gzip_file?(filename) ? Zlib::GzipReader.open(filename) : File.open(filename, "r")
35
+ yield Fs::Entry.new(filename: filename, archive_filename: nil, contents: io.read)
37
36
  end
38
37
  end
39
38
 
40
39
  def read_archive(filename, &block)
41
- io = is_gzip_file?(filename) ? Zlib::GzipReader.open(filename) : ::File.open(filename, "r")
40
+ io = is_gzip_file?(filename) ? Zlib::GzipReader.open(filename) : File.open(filename, "r")
42
41
  tarReader = Gem::Package::TarReader.new(io)
43
42
 
44
43
  tarReader.each do |_tar_entry|
45
44
  if _tar_entry.file?
46
- yield Entry.new(
45
+ yield Fs::Entry.new(
47
46
  filename: filename,
48
47
  archive_filename: _tar_entry.full_name,
49
48
  contents: _tar_entry.read
@@ -0,0 +1,6 @@
1
+ module Metacrunch
2
+ module Fs
3
+ require_relative "fs/reader"
4
+ require_relative "fs/entry"
5
+ end
6
+ end
@@ -0,0 +1,26 @@
1
+ module Metacrunch
2
+ class Job::Buffer
3
+
4
+ def initialize(size)
5
+ @size = size
6
+ end
7
+
8
+ def buffer(data)
9
+ storage << data
10
+ flush if storage.count >= @size
11
+ end
12
+
13
+ def flush
14
+ storage
15
+ ensure
16
+ @buffer = nil
17
+ end
18
+
19
+ private
20
+
21
+ def storage
22
+ @buffer ||= []
23
+ end
24
+
25
+ end
26
+ end
@@ -0,0 +1,102 @@
1
+ module Metacrunch
2
+ class Job::Dsl::OptionSupport
3
+
4
+ def register_options(args, require_args: false, &block)
5
+ options = {}
6
+ registry.instance_eval(&block)
7
+
8
+ registry.each do |key, opt_def|
9
+ # Set default value
10
+ options[key] = opt_def[:default]
11
+
12
+ # Register with OptionParser
13
+ if opt_def[:args].present?
14
+ option = parser.define(*opt_def[:args]) { |value| options[key] = value }
15
+
16
+ option.desc << "REQUIRED" if opt_def[:required]
17
+ option.desc << "DEFAULT: #{opt_def[:default]}" if opt_def[:default].present?
18
+
19
+ parser_options[key] = option
20
+ end
21
+ end
22
+
23
+ # Finally parse CLI options with OptionParser
24
+ args = parser.parse(args || [])
25
+
26
+ # Make sure required options are present
27
+ ensure_required_options!(options)
28
+
29
+ # Make sure args are present if required
30
+ ensure_required_args!(args) if require_args
31
+
32
+ options
33
+ end
34
+
35
+ private
36
+
37
+ def parser
38
+ @parser ||= OptionParser.new do |parser|
39
+ parser.banner = "Usage: metacrunch run [options] JOB_FILE @@ [job-options] [ARGS]\nJob options:"
40
+ end
41
+ end
42
+
43
+ def parser_options
44
+ @parser_options ||= {}
45
+ end
46
+
47
+ def registry
48
+ @registry ||= OptionRegistry.new
49
+ end
50
+
51
+ def ensure_required_options!(options)
52
+ registry.each do |key, opt_def|
53
+ if opt_def[:required] && options[key].blank?
54
+ long_option = parser_options[key].long.try(:[], 0)
55
+ short_option = parser_options[key].short.try(:[], 0)
56
+
57
+ puts "Error: Required job option `#{long_option || short_option}` missing."
58
+ puts parser.help
59
+
60
+ exit(1)
61
+ end
62
+ end
63
+ end
64
+
65
+ def ensure_required_args!(args)
66
+ if args.blank?
67
+ puts "Error: Required ARGS are missing."
68
+ puts parser.help
69
+
70
+ exit(1)
71
+ end
72
+ end
73
+
74
+ private
75
+
76
+ class OptionRegistry
77
+
78
+ def add(name, *args, default: nil, required: false)
79
+ if default && required
80
+ raise ArgumentError, "You can't use `default` and `required` option at the same time."
81
+ end
82
+
83
+ options[name.to_sym] = {
84
+ args: args,
85
+ default: default,
86
+ required: required
87
+ }
88
+ end
89
+
90
+ def each(&block)
91
+ options.each(&block)
92
+ end
93
+
94
+ private
95
+
96
+ def options
97
+ @options ||= {}
98
+ end
99
+ end
100
+
101
+ end
102
+ end
@@ -0,0 +1,42 @@
1
+ module Metacrunch
2
+ class Job::Dsl
3
+ require_relative "dsl/option_support"
4
+
5
+ def initialize(job)
6
+ @_job = job
7
+ end
8
+
9
+ def source(source)
10
+ @_job.add_source(source)
11
+ end
12
+
13
+ def destination(destination)
14
+ @_job.add_destination(destination)
15
+ end
16
+
17
+ def pre_process(callable = nil, &block)
18
+ @_job.add_pre_process(callable, &block)
19
+ end
20
+
21
+ def post_process(callable = nil, &block)
22
+ @_job.add_post_process(callable, &block)
23
+ end
24
+
25
+ def transformation_buffer(size)
26
+ @_job.add_transformation_buffer(size)
27
+ end
28
+
29
+ def transformation(callable = nil, &block)
30
+ @_job.add_transformation(callable, &block)
31
+ end
32
+
33
+ def options(require_args: false, &block)
34
+ if block_given?
35
+ @_options = OptionSupport.new.register_options(@_job.args, require_args: require_args, &block)
36
+ else
37
+ @_options ||= {}
38
+ end
39
+ end
40
+
41
+ end
42
+ end