bricolage 5.8.7

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 (65) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +4 -0
  3. data/bin/bricolage +6 -0
  4. data/bin/bricolage-jobnet +6 -0
  5. data/jobclass/create.rb +21 -0
  6. data/jobclass/exec.rb +17 -0
  7. data/jobclass/insert-delta.rb +31 -0
  8. data/jobclass/insert.rb +33 -0
  9. data/jobclass/load.rb +39 -0
  10. data/jobclass/my-export.rb +40 -0
  11. data/jobclass/my-migrate.rb +103 -0
  12. data/jobclass/noop.rb +13 -0
  13. data/jobclass/rebuild-drop.rb +37 -0
  14. data/jobclass/rebuild-rename.rb +49 -0
  15. data/jobclass/s3-put.rb +19 -0
  16. data/jobclass/sql.rb +29 -0
  17. data/jobclass/td-delete.rb +20 -0
  18. data/jobclass/td-export.rb +30 -0
  19. data/jobclass/unload.rb +30 -0
  20. data/jobclass/wait-file.rb +48 -0
  21. data/lib/bricolage/application.rb +260 -0
  22. data/lib/bricolage/commandutils.rb +52 -0
  23. data/lib/bricolage/configloader.rb +126 -0
  24. data/lib/bricolage/context.rb +108 -0
  25. data/lib/bricolage/datasource.rb +144 -0
  26. data/lib/bricolage/eventhandlers.rb +47 -0
  27. data/lib/bricolage/exception.rb +47 -0
  28. data/lib/bricolage/filedatasource.rb +42 -0
  29. data/lib/bricolage/filesystem.rb +165 -0
  30. data/lib/bricolage/genericdatasource.rb +37 -0
  31. data/lib/bricolage/job.rb +212 -0
  32. data/lib/bricolage/jobclass.rb +98 -0
  33. data/lib/bricolage/jobfile.rb +100 -0
  34. data/lib/bricolage/jobflow.rb +389 -0
  35. data/lib/bricolage/jobnetrunner.rb +264 -0
  36. data/lib/bricolage/jobresult.rb +74 -0
  37. data/lib/bricolage/logger.rb +52 -0
  38. data/lib/bricolage/mysqldatasource.rb +223 -0
  39. data/lib/bricolage/parameters.rb +653 -0
  40. data/lib/bricolage/postgresconnection.rb +78 -0
  41. data/lib/bricolage/psqldatasource.rb +449 -0
  42. data/lib/bricolage/resource.rb +68 -0
  43. data/lib/bricolage/rubyjobclass.rb +42 -0
  44. data/lib/bricolage/s3datasource.rb +144 -0
  45. data/lib/bricolage/script.rb +120 -0
  46. data/lib/bricolage/sqlstatement.rb +351 -0
  47. data/lib/bricolage/taskqueue.rb +156 -0
  48. data/lib/bricolage/tddatasource.rb +116 -0
  49. data/lib/bricolage/variables.rb +208 -0
  50. data/lib/bricolage/version.rb +4 -0
  51. data/lib/bricolage.rb +8 -0
  52. data/libexec/sqldump +9 -0
  53. data/libexec/sqldump.Darwin +0 -0
  54. data/libexec/sqldump.Linux +0 -0
  55. data/test/all.rb +3 -0
  56. data/test/home/config/development/database.yml +57 -0
  57. data/test/home/config/development/password.yml +2 -0
  58. data/test/home/subsys/separated.job +1 -0
  59. data/test/home/subsys/separated.sql +1 -0
  60. data/test/home/subsys/unified.jobnet +1 -0
  61. data/test/home/subsys/unified.sql.job +5 -0
  62. data/test/test_filesystem.rb +19 -0
  63. data/test/test_parameters.rb +401 -0
  64. data/test/test_variables.rb +114 -0
  65. metadata +192 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: afb5228b706d506b2b2f7b468f216f76cdd82dc9
4
+ data.tar.gz: 9c947de18235c29e7db2b3a7b54fa095f8bf2335
5
+ SHA512:
6
+ metadata.gz: 3759c24eda01c02d78d0f3724c14254dc8dd8b687fc0bdd82869ec3db4ef9120b6cff2a5312533a04ef79d912fc9be96191edde3a81e0f79477783fc563245e9
7
+ data.tar.gz: 3873fafbb3f9dbbec2b2a38afbcbe4f2230ecd1f4467c421ceb37717a6be6723fa111a456c568adf03353471e9c3f5a89ecee9d1d649b02248b95d24858b36d0
data/README.md ADDED
@@ -0,0 +1,4 @@
1
+ bricolage
2
+ =========
3
+
4
+ SQL batch framework
data/bin/bricolage ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ Bundler.require(:default) if defined?(Bundler)
4
+ require 'bricolage/application'
5
+
6
+ Bricolage::Application.main
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ Bundler.require(:default) if defined?(Bundler)
4
+ require 'bricolage/jobnetrunner'
5
+
6
+ Bricolage::JobNetRunner.main
@@ -0,0 +1,21 @@
1
+ JobClass.define('create') {
2
+ parameters {|params|
3
+ params.add SQLFileParam.new('table-def', 'PATH', 'CREATE TABLE file.')
4
+ params.add DestTableParam.new
5
+ params.add OptionalBoolParam.new('drop', 'DROP table before CREATE.')
6
+ params.add OptionalBoolParam.new('analyze', 'ANALYZE table after SQL is executed.')
7
+ params.add DataSourceParam.new('sql')
8
+ }
9
+
10
+ declarations {|params|
11
+ params['table-def'].declarations
12
+ }
13
+
14
+ script {|params, script|
15
+ script.task(params['data-source']) {|task|
16
+ task.drop_force_if params['drop']
17
+ task.exec params['table-def']
18
+ task.analyze_if params['analyze']
19
+ }
20
+ }
21
+ }
data/jobclass/exec.rb ADDED
@@ -0,0 +1,17 @@
1
+ JobClass.define('exec') {
2
+ parameters {|params|
3
+ params.add StringListParam.new('args', 'ARG', 'Command line arguments.')
4
+ }
5
+
6
+ script {|params, script|
7
+ script.task(params.generic_ds) {|task|
8
+ task.action(params['args'].join(' ')) {|ds|
9
+ ds.logger.info '[CMD] ' + params['args'].join(' ')
10
+ system(*params['args'])
11
+ st = $?
12
+ ds.logger.info "status=#{st.exitstatus}"
13
+ JobResult.for_bool(st.exitstatus == 0)
14
+ }
15
+ }
16
+ }
17
+ }
@@ -0,0 +1,31 @@
1
+ JobClass.define('insert-delta') {
2
+ parameters {|params|
3
+ params.add SQLFileParam.new
4
+ params.add DestTableParam.new
5
+ params.add SrcTableParam.new
6
+ params.add StringParam.new('delete-cond', 'SQL_EXPR', 'DELETE condition.')
7
+ params.add OptionalBoolParam.new('analyze', 'ANALYZE table after SQL is executed.')
8
+ params.add OptionalBoolParam.new('vacuum', 'VACUUM table after SQL is executed.')
9
+ params.add OptionalBoolParam.new('vacuum-sort', 'VACUUM SORT table after SQL is executed.')
10
+ params.add DataSourceParam.new('sql')
11
+ }
12
+
13
+ parameters_filter {|job|
14
+ job.provide_sql_file_by_job_id
15
+ }
16
+
17
+ declarations {|params|
18
+ params['sql-file'].declarations
19
+ }
20
+
21
+ script {|params, script|
22
+ script.task(params['data-source']) {|task|
23
+ task.transaction {
24
+ task.exec SQLStatement.delete_where(params['delete-cond'])
25
+ task.exec params['sql-file']
26
+ }
27
+ task.vacuum_if params['vacuum'], params['vacuum-sort']
28
+ task.analyze_if params['analyze']
29
+ }
30
+ }
31
+ }
@@ -0,0 +1,33 @@
1
+ JobClass.define('insert') {
2
+ parameters {|params|
3
+ params.add SQLFileParam.new
4
+ params.add DestTableParam.new
5
+ params.add SrcTableParam.new
6
+ params.add SQLFileParam.new('table-def', 'PATH', 'Create table file.', optional: true)
7
+ params.add OptionalBoolParam.new('drop', 'DROP table before CREATE.')
8
+ params.add OptionalBoolParam.new('truncate', 'TRUNCATE table before SQL is executed.')
9
+ params.add OptionalBoolParam.new('analyze', 'ANALYZE table after SQL is executed.')
10
+ params.add OptionalBoolParam.new('vacuum', 'VACUUM table after SQL is executed.')
11
+ params.add OptionalBoolParam.new('vacuum-sort', 'VACUUM SORT table after SQL is executed.')
12
+ params.add DataSourceParam.new('sql')
13
+ }
14
+
15
+ parameters_filter {|job|
16
+ job.provide_sql_file_by_job_id
17
+ }
18
+
19
+ declarations {|params|
20
+ params['sql-file'].declarations
21
+ }
22
+
23
+ script {|params, script|
24
+ script.task(params['data-source']) {|task|
25
+ task.truncate_if params['truncate']
26
+ task.drop_force_if params['drop']
27
+ task.exec params['table-def'] if params['table-def']
28
+ task.exec params['sql-file']
29
+ task.vacuum_if params['vacuum'], params['vacuum-sort']
30
+ task.analyze_if params['analyze']
31
+ }
32
+ }
33
+ }
data/jobclass/load.rb ADDED
@@ -0,0 +1,39 @@
1
+ require 'bricolage/psqldatasource'
2
+
3
+ JobClass.define('load') {
4
+ parameters {|params|
5
+ params.add DataSourceParam.new('s3', 'src-ds', 'Input data source.')
6
+ params.add SrcFileParam.new
7
+ params.add DataSourceParam.new('sql', 'dest-ds', 'Target data source.')
8
+ params.add DestTableParam.new(optional: false)
9
+ params.add EnumParam.new('format', %w(tsv json), 'Data file format.', default: 'tsv')
10
+ params.add StringParam.new('jsonpath', 'PATH', 'jsonpath to specify columns of json format records', optional: true)
11
+ params.add KeyValuePairsParam.new('options', 'OPTIONS', 'Loader options.',
12
+ optional: true, default: PSQLLoadOptions.new,
13
+ value_handler: lambda {|value, ctx, vars| PSQLLoadOptions.parse(value) })
14
+ params.add SQLFileParam.new('table-def', 'PATH', 'Create table file.', optional: true)
15
+ params.add OptionalBoolParam.new('drop', 'DROP table before CREATE.')
16
+ params.add OptionalBoolParam.new('truncate', 'TRUNCATE table before SQL is executed.')
17
+ params.add OptionalBoolParam.new('analyze', 'ANALYZE table after SQL is executed.')
18
+ params.add OptionalBoolParam.new('vacuum', 'VACUUM table after SQL is executed.')
19
+ params.add OptionalBoolParam.new('vacuum-sort', 'VACUUM SORT table after SQL is executed.')
20
+ params.add KeyValuePairsParam.new('grant', 'KEY:VALUE', 'GRANT table after SQL is executed. (required keys: privilege, to)')
21
+ }
22
+
23
+ declarations {|params|
24
+ Declarations.new("dest_table" => nil)
25
+ }
26
+
27
+ script {|params, script|
28
+ script.task(params['dest-ds']) {|task|
29
+ task.drop_force_if params['drop']
30
+ task.exec params['table-def'] if params['table-def']
31
+ task.truncate_if params['truncate']
32
+ task.load params['src-ds'], params['src-file'], params['dest-table'],
33
+ params['format'], params['jsonpath'], params['options']
34
+ task.vacuum_if params['vacuum'], params['vacuum-sort']
35
+ task.analyze_if params['analyze']
36
+ task.grant_if params['grant'], params['dest-table']
37
+ }
38
+ }
39
+ }
@@ -0,0 +1,40 @@
1
+ JobClass.define('my-export') {
2
+ parameters {|params|
3
+ params.add SQLFileParam.new(optional: true)
4
+ params.add DestFileParam.new
5
+ params.add SrcTableParam.new
6
+ params.add EnumParam.new('format', %w(json tsv csv), 'Target file format.', default: 'json')
7
+ params.add OptionalBoolParam.new('gzip', 'If true, compresses target file by gzip.')
8
+ params.add OptionalBoolParam.new('override', 'If true, clears target file. Otherwise causes error.')
9
+ params.add OptionalBoolParam.new('sqldump', 'If true, clears use sqldump command to dump, only wheen usable.')
10
+ params.add DataSourceParam.new('mysql')
11
+ }
12
+
13
+ declarations {|params|
14
+ sql_statement(params).declarations
15
+ }
16
+
17
+ script {|params, script|
18
+ script.task(params['data-source']) {|task|
19
+ task.export sql_statement(params),
20
+ path: params['dest-file'],
21
+ format: params['format'],
22
+ override: params['override'],
23
+ gzip: params['gzip'],
24
+ sqldump: params['sqldump']
25
+ }
26
+ }
27
+
28
+ def sql_statement(params)
29
+ if sql = params['sql-file']
30
+ sql
31
+ else
32
+ srcs = params['src-tables']
33
+ raise ParameterError, "src-tables must be singleton when no sql-file is given" unless srcs.size == 1
34
+ src_table_var = srcs.keys.first
35
+ stmt = SQLStatement.for_string("select * from $#{src_table_var};")
36
+ stmt.declarations = Declarations.new({src_table_var => src_table_var})
37
+ stmt
38
+ end
39
+ end
40
+ }
@@ -0,0 +1,103 @@
1
+ require 'bricolage/psqldatasource'
2
+
3
+ JobClass.define('my-migrate') {
4
+ parameters {|params|
5
+ # Export
6
+ params.add SrcTableParam.new(optional: false)
7
+ params.add DataSourceParam.new('mysql', 'src-ds', 'Source data source.')
8
+ params.add DestFileParam.new('tmp-file', 'PATH', 'Temporary local file path.')
9
+ params.add OptionalBoolParam.new('sqldump', 'If true, use sqldump command to dump, only on available.', default: true)
10
+
11
+ # Put
12
+ params.add DestFileParam.new('s3-file', 'PATH', 'Temporary S3 file path.')
13
+ params.add DataSourceParam.new('s3', 's3-ds', 'Temporary file storage.')
14
+ params.add OptionalBoolParam.new('override', 'If true, overwrite s3 target file. Otherwise causes error.')
15
+
16
+ # Load
17
+ params.add DestTableParam.new(optional: false)
18
+ params.add DataSourceParam.new('sql', 'dest-ds', 'Destination data source.')
19
+ params.add KeyValuePairsParam.new('options', 'OPTIONS', 'Loader options.',
20
+ optional: true, default: PSQLLoadOptions.new,
21
+ value_handler: lambda {|value, ctx, vars| PSQLLoadOptions.parse(value) })
22
+ params.add SQLFileParam.new('table-def', 'PATH', 'Create table file.')
23
+
24
+ # Misc
25
+ params.add OptionalBoolParam.new('analyze', 'ANALYZE table after SQL is executed.', default: true)
26
+ params.add OptionalBoolParam.new('vacuum', 'VACUUM table after SQL is executed.')
27
+ params.add OptionalBoolParam.new('vacuum-sort', 'VACUUM SORT table after SQL is executed.')
28
+ params.add KeyValuePairsParam.new('grant', 'KEY:VALUE', 'GRANT table after SQL is executed.')
29
+
30
+ # All
31
+ params.add OptionalBoolParam.new('export', 'Runs EXPORT task.')
32
+ params.add OptionalBoolParam.new('put', 'Runs PUT task.')
33
+ params.add OptionalBoolParam.new('load', 'Runs LOAD task.')
34
+ params.add OptionalBoolParam.new('gzip', 'If true, compresses target file by gzip.', default: true)
35
+ }
36
+
37
+ declarations {|params|
38
+ decls = sql_statement(params).declarations
39
+ decls.declare 'dest-table', nil
40
+ decls
41
+ }
42
+
43
+ script {|params, script|
44
+ run_all = !params['export'] && !params['put'] && !params['load']
45
+
46
+ # Export
47
+ if params['export'] || run_all
48
+ script.task(params['src-ds']) {|task|
49
+ task.export sql_statement(params),
50
+ path: params['tmp-file'],
51
+ format: 'json',
52
+ override: true,
53
+ gzip: params['gzip'],
54
+ sqldump: params['sqldump']
55
+ }
56
+ end
57
+
58
+ # Put
59
+ if params['put'] || run_all
60
+ script.task(params['s3-ds']) {|task|
61
+ task.put params['tmp-file'], params['s3-file'], check_args: false
62
+ }
63
+ end
64
+
65
+ # Load
66
+ if params['load'] || run_all
67
+ script.task(params['dest-ds']) {|task|
68
+ prev_table = '${dest_table}_old'
69
+ work_table = '${dest_table}_wk'
70
+
71
+ # CREATE
72
+ task.drop_force prev_table
73
+ task.drop_force work_table
74
+ task.exec params['table-def'].replace(/\$\{?dest_table\}?\b/, work_table)
75
+
76
+ # COPY
77
+ task.load params['s3-ds'], params['s3-file'], work_table,
78
+ 'json', nil, params['options'].merge('gzip' => params['gzip'])
79
+
80
+ # VACUUM, ANALYZE, GRANT
81
+ task.vacuum_if params['vacuum'], params['vacuum-sort'], work_table
82
+ task.analyze_if params['analyze'], work_table
83
+ task.grant_if params['grant'], work_table
84
+
85
+ # RENAME
86
+ task.create_dummy_table '${dest_table}'
87
+ task.transaction {
88
+ task.rename_table params['dest-table'].to_s, "#{params['dest-table'].name}_old"
89
+ task.rename_table work_table, params['dest-table'].name
90
+ }
91
+ }
92
+ end
93
+ }
94
+
95
+ def sql_statement(params)
96
+ srcs = params['src-tables']
97
+ raise ParameterError, "src-tables must be singleton when no sql-file is given" unless srcs.size == 1
98
+ src_table_var = srcs.keys.first
99
+ stmt = SQLStatement.for_string("select * from $#{src_table_var};")
100
+ stmt.declarations = Declarations.new({src_table_var => src_table_var})
101
+ stmt
102
+ end
103
+ }
data/jobclass/noop.rb ADDED
@@ -0,0 +1,13 @@
1
+ JobClass.define('noop') {
2
+ parameters {|params|
3
+ params.add OptionalBoolParam.new('failure', 'Finish with failure or not.')
4
+ }
5
+
6
+ script {|params, script|
7
+ script.task(params.generic_ds) {|task|
8
+ task.action('return !$failure') {
9
+ JobResult.for_bool(!params['failure'])
10
+ }
11
+ }
12
+ }
13
+ }
@@ -0,0 +1,37 @@
1
+ JobClass.define('rebuild-drop') {
2
+ parameters {|params|
3
+ params.add SQLFileParam.new
4
+ params.add DestTableParam.new
5
+ params.add SrcTableParam.new
6
+ params.add SQLFileParam.new('table-def', 'PATH', 'Create table file.')
7
+ params.add OptionalBoolParam.new('analyze', 'ANALYZE table after SQL is executed.', default: true)
8
+ params.add OptionalBoolParam.new('vacuum', 'VACUUM table after SQL is executed.')
9
+ params.add OptionalBoolParam.new('vacuum-sort', 'VACUUM SORT table after SQL is executed.')
10
+ params.add KeyValuePairsParam.new('grant', 'KEY:VALUE', 'GRANT table after SQL is executed. (required keys: on, to)')
11
+ params.add DataSourceParam.new('sql')
12
+ }
13
+
14
+ parameters_filter {|job|
15
+ job.provide_sql_file_by_job_id
16
+ }
17
+
18
+ declarations {|params|
19
+ params['sql-file'].declarations
20
+ }
21
+
22
+ script {|params, script|
23
+ script.task(params['data-source']) {|task|
24
+ # CREATE
25
+ task.drop_force params['dest-table']
26
+ task.exec params['table-def']
27
+
28
+ # INSERT
29
+ task.exec params['sql-file']
30
+
31
+ # VACUUM, ANALYZE, GRANT
32
+ task.vacuum_if params['vacuum'], params['vacuum-sort'], params['dest-table']
33
+ task.analyze_if params['analyze'], params['dest-table']
34
+ task.grant_if params['grant'], params['dest-table']
35
+ }
36
+ }
37
+ }
@@ -0,0 +1,49 @@
1
+ JobClass.define('rebuild-rename') {
2
+ parameters {|params|
3
+ params.add SQLFileParam.new
4
+ params.add DestTableParam.new
5
+ params.add SrcTableParam.new
6
+ params.add SQLFileParam.new('table-def', 'PATH', 'Create table file.')
7
+ params.add OptionalBoolParam.new('analyze', 'ANALYZE table after SQL is executed.', default: true)
8
+ params.add OptionalBoolParam.new('vacuum', 'VACUUM table after SQL is executed.')
9
+ params.add OptionalBoolParam.new('vacuum-sort', 'VACUUM SORT table after SQL is executed.')
10
+ params.add KeyValuePairsParam.new('grant', 'KEY:VALUE', 'GRANT table after SQL is executed.')
11
+ params.add DataSourceParam.new('sql')
12
+ }
13
+
14
+ parameters_filter {|job|
15
+ job.provide_sql_file_by_job_id
16
+ }
17
+
18
+ declarations {|params|
19
+ params['sql-file'].declarations
20
+ }
21
+
22
+ script {|params, script|
23
+ script.task(params['data-source']) {|task|
24
+ prev_table = '${dest_table}_old'
25
+ work_table = '${dest_table}_wk'
26
+
27
+ # CREATE
28
+ task.drop_force prev_table
29
+ task.drop_force work_table
30
+ task.exec params['table-def'].replace(/\$\{?dest_table\}?\b/, work_table)
31
+
32
+ # INSERT
33
+ task.exec params['sql-file'].replace(/\$\{?dest_table\}?\b/, work_table)
34
+
35
+ # VACUUM, ANALYZE, GRANT
36
+ task.vacuum_if params['vacuum'], params['vacuum-sort'], work_table
37
+ task.analyze_if params['analyze'], work_table
38
+ task.grant_if params['grant'], work_table
39
+
40
+ # RENAME
41
+ task.create_dummy_table '$dest_table'
42
+ task.transaction {
43
+ dest_table = params['dest-table']
44
+ task.rename_table dest_table.to_s, "#{dest_table.name}_old"
45
+ task.rename_table "#{dest_table}_wk", dest_table.name
46
+ }
47
+ }
48
+ }
49
+ }
@@ -0,0 +1,19 @@
1
+ JobClass.define('s3-put') {
2
+ parameters {|params|
3
+ params.add DestFileParam.new
4
+ params.add SrcFileParam.new
5
+ params.add OptionalBoolParam.new('remove', 'Removes source files after PUT is succeeded.')
6
+ params.add DataSourceParam.new('s3')
7
+ }
8
+
9
+ script {|params, script|
10
+ script.task(params['data-source']) {|task|
11
+ task.put params['src-file'], params['dest-file']
12
+ }
13
+ if params['remove']
14
+ script.task(params.file_ds) {|task|
15
+ task.remove params['src-file']
16
+ }
17
+ end
18
+ }
19
+ }
data/jobclass/sql.rb ADDED
@@ -0,0 +1,29 @@
1
+ JobClass.define('sql') {
2
+ parameters {|params|
3
+ params.add SQLFileParam.new
4
+ params.add DestTableParam.new
5
+ params.add SrcTableParam.new
6
+ params.add OptionalBoolParam.new('truncate', 'TRUNCATE table before SQL is executed.')
7
+ params.add OptionalBoolParam.new('analyze', 'ANALYZE table after SQL is executed.')
8
+ params.add OptionalBoolParam.new('vacuum', 'VACUUM table after SQL is executed.')
9
+ params.add OptionalBoolParam.new('vacuum-sort', 'VACUUM SORT table after SQL is executed.')
10
+ params.add DataSourceParam.new('sql')
11
+ }
12
+
13
+ parameters_filter {|job|
14
+ job.provide_sql_file_by_job_id
15
+ }
16
+
17
+ declarations {|params|
18
+ params['sql-file'].declarations
19
+ }
20
+
21
+ script {|params, script|
22
+ script.task(params['data-source']) {|task|
23
+ task.truncate_if params['truncate']
24
+ task.exec params['sql-file']
25
+ task.vacuum_if params['vacuum'], params['vacuum-sort']
26
+ task.analyze_if params['analyze']
27
+ }
28
+ }
29
+ }
@@ -0,0 +1,20 @@
1
+ JobClass.define('td-delete') {
2
+ parameters {|params|
3
+ params.add DestTableParam.new(optional: false)
4
+ params.add DataSourceParam.new('td')
5
+ params.add DateParam.new('from', 'DATE', 'Start date of logs to delete (%Y-%m-%d).')
6
+ params.add DateParam.new('to', 'DATE', 'End date of logs to delete (%Y-%m-%d).')
7
+ }
8
+
9
+ declarations {|params|
10
+ Declarations.new("dest_table" => nil)
11
+ }
12
+
13
+ script {|params, script|
14
+ script.task(params['data-source']) {|task|
15
+ task.delete params['dest-table'],
16
+ from: params['from'],
17
+ to: params['to']
18
+ }
19
+ }
20
+ }
@@ -0,0 +1,30 @@
1
+ JobClass.define('td-export') {
2
+ parameters {|params|
3
+ params.add SQLFileParam.new
4
+ params.add DestFileParam.new
5
+ params.add SrcTableParam.new
6
+ params.add StringParam.new('src-database', 'NAME', 'Source TD database name.', optional: true)
7
+ params.add EnumParam.new('format', %w(msgpack tsv csv json), 'Target file format.', default: 'msgpack')
8
+ params.add OptionalBoolParam.new('gzip', 'If true, compresses target file by gzip.')
9
+ params.add OptionalBoolParam.new('override', 'If true, clears target file. Otherwise causes error.')
10
+ params.add DataSourceParam.new('td')
11
+ }
12
+
13
+ parameters_filter {|job|
14
+ job.provide_sql_file_by_job_id
15
+ }
16
+
17
+ declarations {|params|
18
+ params['sql-file'].declarations
19
+ }
20
+
21
+ script {|params, script|
22
+ script.task(params['data-source']) {|task|
23
+ task.export params['sql-file'],
24
+ path: params['dest-file'],
25
+ format: params['format'],
26
+ gzip: params['gzip'],
27
+ override: params['override']
28
+ }
29
+ }
30
+ }
@@ -0,0 +1,30 @@
1
+ require 'bricolage/psqldatasource'
2
+
3
+ JobClass.define('unload') {
4
+ parameters {|params|
5
+ params.add SQLFileParam.new
6
+ params.add DataSourceParam.new('sql', 'src-ds', 'Input data source (sql).')
7
+ params.add SrcTableParam.new(optional: false)
8
+ params.add DataSourceParam.new('s3', 'dest-ds', 'Target data source (s3).')
9
+ params.add DestFileParam.new
10
+ params.add EnumParam.new('format', %w(tsv), 'Data file format.', default: 'tsv')
11
+ params.add KeyValuePairsParam.new('options', 'OPTIONS', 'Loader options.',
12
+ optional: true, default: PSQLLoadOptions.new,
13
+ value_handler: lambda {|value, ctx, vars| PSQLLoadOptions.parse(value) })
14
+ }
15
+
16
+ parameters_filter {|job|
17
+ job.provide_sql_file_by_job_id
18
+ }
19
+
20
+ declarations {|params|
21
+ params['sql-file'].declarations
22
+ }
23
+
24
+ script {|params, script|
25
+ script.task(params['src-ds']) {|task|
26
+ task.unload params['sql-file'], params['dest-ds'], params['dest-file'],
27
+ params['format'], params['options']
28
+ }
29
+ }
30
+ }
@@ -0,0 +1,48 @@
1
+ JobClass.define('wait-file') {
2
+ parameters {|params|
3
+ params.add DestFileParam.new
4
+ params.add StringParam.new('condition-expr', 'RUBY_EXPR', 'Wait condition expression (in Ruby). (default: check file existance)', optional: true)
5
+ params.add StringParam.new('max-wait-minutes', 'NUM', 'Max waiting minutes.')
6
+ }
7
+
8
+ script {|params, script|
9
+ script.task(params.generic_ds) {|task|
10
+ dest_file = params['dest-file']
11
+ max_wait_minutes = params['max-wait-minutes'].to_i
12
+
13
+ default_expr = "File.exist?('#{dest_file}')"
14
+ condition_expr = params['condition-expr'] || default_expr
15
+
16
+ task.action("wait #{dest_file} (condition: #{condition_expr})") {|ds|
17
+ wait_file_condition(dest_file, condition_expr, max_wait_minutes, ds.logger)
18
+ }
19
+ }
20
+ }
21
+
22
+ REPORT_INTERVAL = 90 # 15 min
23
+ WAIT_INTERVAL = 5
24
+
25
+ def wait_file_condition(dest_file, condition_expr, max_wait_minutes, logger)
26
+ logger.info "waiting file by { #{condition_expr} }"
27
+
28
+ # DO NOT CHANGE these variables name; they are condition expression interface.
29
+ start_time = Time.now
30
+ wait_limit = start_time + max_wait_minutes * 60
31
+ last_log_time = start_time
32
+
33
+ until eval(condition_expr)
34
+ now = Time.now
35
+ if now > wait_limit
36
+ logger.error "exceeded wait limit (#{max_wait_minutes} minutes); abort"
37
+ return JobResult.for_bool(false)
38
+ end
39
+ if now - last_log_time > REPORT_INTERVAL
40
+ logger.info "waiting..."
41
+ last_log_time = Time.now
42
+ end
43
+ sleep WAIT_INTERVAL
44
+ end
45
+ logger.info "condition fullfilled"
46
+ JobResult.for_bool(true)
47
+ end
48
+ }