gd_bam 0.1.28 → 0.1.29

Sign up to get free protection for your applications and to get access to all the features.
data/lib/bam/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Bam
2
- VERSION = '0.1.28'
2
+ VERSION = '0.1.29'
3
3
  end
data/lib/base/graph.rb CHANGED
@@ -16,7 +16,6 @@ module GoodData
16
16
  })
17
17
  else
18
18
  # it is a URI
19
- # binding.pry
20
19
  {
21
20
  :inputs => [],
22
21
  :outputs => []
data/lib/base/project.rb CHANGED
@@ -81,6 +81,12 @@ module GoodData
81
81
  Project.create(project.merge({:sinks => sinks}))
82
82
  end
83
83
 
84
+ def self.mark_deleted_taps(project, options)
85
+ taps = project[:taps]
86
+ enriched_taps = Taps.get_deleted_records_info(taps, GoodData::Bam::Commands.get_sf_client(options))
87
+ Project.create(project.merge({:taps => enriched_taps}))
88
+ end
89
+
84
90
  def self.load_flows_definitions(project, path)
85
91
  p = Pathname(path)
86
92
  flows = Pathname.glob(p + "*.rb").map do |p|
@@ -96,6 +102,7 @@ module GoodData
96
102
  p = Project.load_taps(project, home + 'taps')
97
103
  p = Project.load_sinks(p, home + 'sinks')
98
104
  p = Project.set_graph_repos(p, paths)
105
+ p = Project.mark_deleted_taps(p, options)
99
106
  p = Project.load_flows_definitions(p, home + "flows")
100
107
  p = Compiler.compile_dsl(p)
101
108
  end
data/lib/base/tap.rb CHANGED
@@ -161,7 +161,9 @@ module GoodData
161
161
  def self.prepare_for_es_downloader(tap)
162
162
  tap = Tap.pull_id_from_output_to_input(tap)
163
163
  tap = Tap.remove_timestamp_field(Tap.pull_timestamp_from_output_to_input(tap))
164
- tap[:snapshots] == true ? Tap.add_field(tap, {:name => "Snapshot"}) : tap
164
+ tap = tap[:snapshots] == true ? Tap.add_field(tap, {:name => "Snapshot"}) : tap
165
+ tap = tap[:has_deleted_records] == true ? Tap.add_field(tap, {:name => "IsDeleted"}) : tap
166
+ tap = tap[:has_deleted_records] == true ? Tap.add_field(tap, {:name => "DeletedAt"}) : tap
165
167
  end
166
168
 
167
169
  def self.prepare_for_s3_backup(tap)
data/lib/base/taps.rb CHANGED
@@ -14,6 +14,17 @@ module GoodData
14
14
  taps.find_all {|t| [:web, :file].include?(t[:source_type]) }
15
15
  end
16
16
 
17
+ def self.get_deleted_records_info(taps, client)
18
+ deleted = client.modules.map {|i| {:name => i[:name], :flag => i[:replicateable]}}.reduce({}) {|memo, x| memo.merge({x[:name] => x[:flag]})}
19
+ taps.map do |t|
20
+ if t[:source_type] == :salesforce
21
+ t.merge({:has_deleted_records => deleted[t[:object]]})
22
+ else
23
+ t.merge({:has_deleted_records => false})
24
+ end
25
+ end
26
+ end
27
+
17
28
  end
18
29
  end
19
30
  end
@@ -17,6 +17,18 @@ module GoodData
17
17
  })
18
18
  end
19
19
 
20
+ def self.create_deleted_records_meta(builder)
21
+ builder.Metadata({:id => "deleted_records_metadata"}) do |builder|
22
+ csv_metadata(builder, {
23
+ :name => "deleted_records_metadata",
24
+ :fields => [
25
+ {:type => "string", :name => "Id"},
26
+ {:type => "string", :name => "Timestamp"}
27
+ ]
28
+ })
29
+ end
30
+ end
31
+
20
32
  def self.create_trash_meta(builder)
21
33
  builder.Metadata({:id => "trash_metadata"}) do |builder|
22
34
  csv_metadata(builder, {
@@ -8,6 +8,7 @@ module GoodData
8
8
  DEDUP = "DEDUP"
9
9
  READER = "DATA_READER"
10
10
  SF_READER = "SF_READER"
11
+ SF_DELETED_READER = "SF_DELETED_READER"
11
12
  REFORMAT = "REFORMAT"
12
13
  FILE_BACKUP = "FILE_BACKUP"
13
14
  PERSISTENT_LOOKUP = "persistentLookup"
@@ -189,7 +190,23 @@ HEREDOC
189
190
  :required => []
190
191
  })
191
192
  end
192
-
193
+
194
+
195
+ def self.sfdc_deleted_records(data, options={})
196
+ local_defaults = {
197
+ :type => SF_DELETED_READER,
198
+ :retryDelay => 100,
199
+ :startDateTime => "`date2str(dateadd(today(), -20, day), \"yyyy-MM-dd'T'00:00:00.000'Z'\")`"
200
+ }
201
+ defaults = local_defaults.merge(options[:defaults] || {})
202
+
203
+ base_node(defaults.merge(data), {
204
+ :allowed => [:entity, :sfdcConnection],
205
+ :defaults => defaults,
206
+ :required => [:entity, :sfdcConnection, :startDateTime]
207
+ })
208
+ end
209
+
193
210
 
194
211
  def self.sfdc_reader2(data, options={})
195
212
  local_defaults = {
@@ -55,7 +55,7 @@ long ten_mins_ago = now - (60 * 10) ;
55
55
 
56
56
  function integer transform(integer idx) {
57
57
  if (last_run == null) {
58
- last_run = $in.0.value;
58
+ last_run = jodaDate2str(jodaStr2date($in.0.value, ["yyyy-MM-dd'T'HH:mm:ss.SSSZZ"], 'en_US', 'UTC', 'UTC'), "yyyy-MM-dd'T'HH:mm:ss.SSSZZ", "en_US", 'UTC');
59
59
  last_run_ts = date2long(jodaStr2date(last_run, ["yyyy-MM-dd'T'HH:mm:ss.SSSZZ"], 'en_US', 'UTC', 'UTC'));
60
60
  }
61
61
 
@@ -203,6 +203,18 @@ HEREDOC
203
203
  Helpers::property_file(builder, {:id => "workspace_params", :fileURL => "workspace.prm"})
204
204
 
205
205
  Helpers::create_lookup_meta(builder)
206
+ Helpers::create_deleted_records_meta(builder)
207
+ builder.Metadata({:id => "reformat_deleted_records"}) do |builder|
208
+ Helpers::csv_metadata(builder, {
209
+ :name => "reformat_deleted_records",
210
+ :fields => [
211
+ {:type => "string", :name => "Id"},
212
+ {:type => "date", :name => "Timestamp"},
213
+ {:type => "string", :name => "DeletedAt"},
214
+ {:type => "string", :name => "IsDeleted"}]
215
+ })
216
+ end
217
+
206
218
  taps.each do |tap|
207
219
  module_name = tap[:object]
208
220
  file = tap[:id] || module_name
@@ -246,10 +258,52 @@ HEREDOC
246
258
  timestamp_field = Tap.find_output_field(tap, "Timestamp")
247
259
  id_field = Tap.find_output_field(tap, "Id")
248
260
  tap = Tap.prepare_for_sf_downloader(tap)
261
+ deleted_records_tap = Tap.create({
262
+ :source => "salesforce",
263
+ :object => module_name,
264
+ :id => dataset,
265
+ :fields => [
266
+ {:name => "Id"},
267
+ {:name => "Timestamp"},
268
+ {:name => "DeletedAt"},
269
+ {:name => "IsDeleted"}]
270
+ })
271
+
272
+ if tap[:has_deleted_records]
273
+ # binding.pry
274
+ builder.Phase(:number => phase += 1) do
275
+ ctl = "function integer generate() {$out.0.Id = \"GD_FAKE_DELETED_RECORD\";$out.0.Timestamp = $out.0.Timestamp = str2date(\"2038-01-01T00:00:00.000+0000\", \"yyyy-MM-dd'T'HH:mm:ss.SSSZZ\");$out.0.IsDeleted = \"true\";$out.0.DeletedAt = \"2038-01-01T00:00:00.000+0000\";return OK;}"
276
+ Core::build_node2(builder, Nodes.data_generator2({:name => "#{file}_fake_deleted_records_generator", :id => "#{file}_fake_deleted_records_generator", :generate => ctl}))
277
+ Core::build_node2(builder, Nodes.edge2({:toNode => "#{file}_fake_deleted_records_es:0", :fromNode => "#{file}_fake_deleted_records_generator:0", :metadata => "reformat_deleted_records"}))
278
+ Core::build_node2(builder, Nodes.es_writer2({:name => "#{file} es Writer", :id => "#{file}_fake_deleted_records_es", :store => store, :entityFieldsMapping => Helpers::create_es_write_json(deleted_records_tap).to_json}))
279
+ end
280
+ end
281
+
249
282
  builder.Phase(:number => phase += 1) do
250
283
  Core::build_node2(builder, Nodes.es_truncate2({:guiName => dataset, :store => store, :entity => dataset, :timestamp => "${#{dataset}_TRUNCATE_DATE}", :name => "#{module_name} es truncate", :id => "#{module_name}_es_truncate"}))
251
284
  end
252
285
 
286
+ if tap[:has_deleted_records]
287
+ builder.Phase(:number => phase += 1) do
288
+ Core::build_node2(builder, Nodes.sfdc_deleted_records({
289
+ :sfdcConnection => "SFDC",
290
+ :entity => module_name,
291
+ :id => "#{file}_deleted_records_downlader",
292
+ :startDateTime => "`iif((${GRAPH_STARTED_TIMESTAMP} - 3600 * 20 * 24 * 1000) > date2long(str2date(replace(\"${#{dataset}_START}\", \"\\\\+00:00\", \"\+0000\"), \"yyyy-MM-dd'T'HH:mm:ss.SSSZZ\")), date2str(long2date(${GRAPH_STARTED_TIMESTAMP} - 20 * 3600 * 24 * 1000), \"yyyy-MM-dd'T'HH:mm:ss.SSSZZ\"), date2str(str2date(replace(\"${#{dataset}_START}\", \"\\\\+00:00\", \"\+0000\"), \"yyyy-MM-dd'T'HH:mm:ss.SSSZZ\"), \"yyyy-MM-dd'T'HH:mm:ss.SSSZZ\"))`",
293
+ :endDateTime => "${#{dataset}_END}"
294
+ # "`str2date(replace(\"${#{dataset}_END}\", \"\\\\+00:00\", \"\+0900\"), \"yyyy-MM-dd'T'HH:mm:ss.SSSZZ\"))`"
295
+ }))
296
+
297
+ es_transformation_source = "function integer transform() {\n$out.0.* = $in.0.*;\n$out.0.Timestamp = str2date($in.0.Timestamp,\"joda:yyyy-MM-dd'T'HH:mm:ss.SSSZZ\");\n$out.0.DeletedAt = jodaDate2str(jodaStr2date($in.0.Timestamp, [\"yyyy-MM-dd'T'HH:mm:ss.SSSZZ\"], 'en_US', 'UTC', 'UTC'), \"yyyy-MM-dd'T'HH:mm:ss.SSSZZ\", \"en_US\", 'UTC');\n$out.0.IsDeleted = \"true\";\nreturn OK;\n}"
298
+ Core::build_node2(builder, Nodes.reformat2({:name => "#{file} Reformat", :id => "#{file}_deleted_records_reformat", :transformation => es_transformation_source}))
299
+ Core::build_node2(builder, Nodes.edge2({:toNode => "#{file}_deleted_records_reformat:0", :fromNode => "#{file}_deleted_records_downlader:0", :metadata => "deleted_records_metadata"}))
300
+ Core::build_node2(builder, Nodes.sort2({:sortKey => "Timestamp(a)",:name => "#{file} es Sort", :id => "#{file}_deleted_records_es_sort"}))
301
+ Core::build_node2(builder, Nodes.edge2({:toNode => "#{file}_deleted_records_es_sort:0", :fromNode => "#{file}_deleted_records_reformat:0", :metadata => "reformat_deleted_records"}))
302
+ Core::build_node2(builder, Nodes.es_writer2({:name => "#{file} es Writer", :id => "#{file}_deleted_records_es", :store => store, :entityFieldsMapping => Helpers::create_es_write_json(deleted_records_tap).to_json}))
303
+ Core::build_node2(builder, Nodes.edge2({:toNode => "#{file}_deleted_records_es:0", :fromNode => "#{file}_deleted_records_es_sort:0", :metadata => "reformat_deleted_records"}))
304
+ end
305
+ end
306
+
253
307
  builder.Phase(:number => phase += 1) do
254
308
  fields = tap[:fields]
255
309
  mapping = "{\"xmlFieldsMapping\":{\"xmlFields\":["
@@ -340,6 +394,18 @@ HEREDOC
340
394
  Helpers::property_file(builder, {:id => "params_params", :fileURL => "params.prm"})
341
395
  Helpers::property_file(builder, {:id => "workspace_params", :fileURL => "workspace.prm"})
342
396
 
397
+ Helpers::create_deleted_records_meta(builder)
398
+ builder.Metadata({:id => "reformat_deleted_records"}) do |builder|
399
+ Helpers::csv_metadata(builder, {
400
+ :name => "reformat_deleted_records",
401
+ :fields => [
402
+ {:type => "string", :name => "Id"},
403
+ {:type => "date", :name => "Timestamp"},
404
+ {:type => "string", :name => "DeletedAt"},
405
+ {:type => "string", :name => "IsDeleted"}]
406
+ })
407
+ end
408
+
343
409
  Helpers::create_lookup_meta(builder)
344
410
  builder.Metadata({:id => "data_metadata"}) do |builder|
345
411
  Helpers::csv_metadata(builder, {:name => "data_metadata",:fields => [{:name => "Id"}, {:name => "Timestamp"}, {:name => "Value"}]})
@@ -509,7 +575,43 @@ HEREDOC
509
575
  end
510
576
  end
511
577
  end
512
- taps_with_history.each do |tap|
578
+
579
+ taps_with_history.uniq_by {|x| x[:id]}.each do |tap|
580
+
581
+ # Download the Deleted records for these taps. since we will not have a chance to download them later
582
+
583
+ if tap[:has_deleted_records]
584
+ module_name = tap[:object]
585
+ dataset = file = tap[:id]
586
+ builder.Phase(:number => phase += 1) do
587
+ Core::build_node2(builder, Nodes.sfdc_deleted_records({
588
+ :sfdcConnection => "SFDC",
589
+ :entity => module_name,
590
+ :id => "#{file}_deleted_records_downlader",
591
+ :startDateTime => "`iif((${GRAPH_STARTED_TIMESTAMP} - 3600 * 20 * 24 * 1000) > date2long(str2date(replace(\"${#{dataset}_START}\", \"\\\\+00:00\", \"\+0000\"), \"yyyy-MM-dd'T'HH:mm:ss.SSSZZ\")), date2str(long2date(${GRAPH_STARTED_TIMESTAMP} - 20 * 3600 * 24 * 1000), \"yyyy-MM-dd'T'HH:mm:ss.SSSZZ\"), date2str(str2date(replace(\"${#{dataset}_START}\", \"\\\\+00:00\", \"\+0000\"), \"yyyy-MM-dd'T'HH:mm:ss.SSSZZ\"), \"yyyy-MM-dd'T'HH:mm:ss.SSSZZ\"))`",
592
+ :endDateTime => "${#{dataset}_END}"
593
+ # "`str2date(replace(\"${#{dataset}_END}\", \"\\\\+00:00\", \"\+0900\"), \"yyyy-MM-dd'T'HH:mm:ss.SSSZZ\"))`"
594
+ }))
595
+ deleted_records_tap = Tap.create({
596
+ :source => "salesforce",
597
+ :object => module_name,
598
+ :id => dataset,
599
+ :fields => [
600
+ {:name => "Id"},
601
+ {:name => "Timestamp"},
602
+ {:name => "DeletedAt"},
603
+ {:name => "IsDeleted"}]
604
+ })
605
+ es_transformation_source = "function integer transform() {\n$out.0.* = $in.0.*;\n$out.0.Timestamp = str2date($in.0.Timestamp,\"joda:yyyy-MM-dd'T'HH:mm:ss.SSSZZ\");\n$out.0.DeletedAt = jodaDate2str(jodaStr2date($in.0.Timestamp, [\"yyyy-MM-dd'T'HH:mm:ss.SSSZZ\"], 'en_US', 'UTC', 'UTC'), \"yyyy-MM-dd'T'HH:mm:ss.SSSZZ\", \"en_US\", 'UTC');\n$out.0.IsDeleted = \"true\";\nreturn OK;\n}"
606
+ Core::build_node2(builder, Nodes.reformat2({:name => "#{file} Reformat", :id => "#{file}_deleted_records_reformat", :transformation => es_transformation_source}))
607
+ Core::build_node2(builder, Nodes.edge2({:toNode => "#{file}_deleted_records_reformat:0", :fromNode => "#{file}_deleted_records_downlader:0", :metadata => "deleted_records_metadata"}))
608
+ Core::build_node2(builder, Nodes.sort2({:sortKey => "Timestamp(a)",:name => "#{file} es Sort", :id => "#{file}_deleted_records_es_sort"}))
609
+ Core::build_node2(builder, Nodes.edge2({:toNode => "#{file}_deleted_records_es_sort:0", :fromNode => "#{file}_deleted_records_reformat:0", :metadata => "reformat_deleted_records"}))
610
+ Core::build_node2(builder, Nodes.es_writer2({:name => "#{file} es Writer", :id => "#{file}_deleted_records_es", :store => store, :entityFieldsMapping => Helpers::create_es_write_json(deleted_records_tap).to_json}))
611
+ Core::build_node2(builder, Nodes.edge2({:toNode => "#{file}_deleted_records_es:0", :fromNode => "#{file}_deleted_records_es_sort:0", :metadata => "reformat_deleted_records"}))
612
+ end
613
+ end
614
+
513
615
  # puts "#{tap[:id]}_LAST_RUN"
514
616
  builder.Phase(:number => phase += 1) do
515
617
  generate_func = <<HEREDOC
@@ -221,7 +221,7 @@ HEREDOC
221
221
  }) do
222
222
  builder.Global do
223
223
 
224
- builder.Metadata({:id => "clover_metadata"}) do |builder|
224
+ builder.Metadata({:id => "clover_metadata"}) do |builder|
225
225
  Helpers::csv_metadata(builder, Metadata.get_target_metadata(tap))
226
226
  end
227
227
 
@@ -311,9 +311,17 @@ HEREDOC
311
311
  end
312
312
  Core::build_node2(builder, Nodes.reformat2({:name => "Reformat", :id => "reformat", :transformation => transformation_source}))
313
313
  Core::build_node2(builder, Nodes.edge2({:toNode => "reformat:0", :fromNode => "es:0", :metadata => "es_metadata"}))
314
+ if tap[:has_deleted_records] == true
315
+ filter_deleted_function = "function integer transform() {\nif ($in.0.IsDeleted == \"true\") {return SKIP;} else {$out.0.* = $in.0.*; return OK;};\n}"
316
+ Core::build_node2(builder, Nodes.reformat2({:name => "Reformat", :id => "filter_deleted", :transformation => filter_deleted_function}))
317
+ Core::build_node2(builder, Nodes.edge2({:toNode => "filter_deleted:0", :fromNode => "reformat:0", :metadata => "output_metadata"}))
318
+ Core::build_node2(builder, Nodes.edge2({:toNode => "copy:0", :fromNode => "filter_deleted:0", :metadata => "output_metadata"}))
319
+ else
320
+ Core::build_node2(builder, Nodes.edge2({:toNode => "copy:0", :fromNode => "reformat:0", :metadata => "output_metadata"}))
321
+ end
314
322
 
315
323
  Core::build_node2(builder, Nodes.copy2({:name => "Copy", :id => "copy"}))
316
- Core::build_node2(builder, Nodes.edge2({:toNode => "copy:0", :fromNode => "reformat:0", :metadata => "output_metadata"}))
324
+ # Core::build_node2(builder, Nodes.edge2({:toNode => "copy:0", :fromNode => "reformat:0", :metadata => "output_metadata"}))
317
325
  Core::build_node2(builder, Nodes.writer2({:name => "CSV Writer", :id => "csv", :fileURL => "${PROJECT}/data/#{tap[:id]}.csv", :outputFieldNames => "true", :makeDirs => "true"}))
318
326
  Core::build_node2(builder, Nodes.edge2({:toNode => "csv:0", :fromNode => "copy:0", :metadata => "output_metadata"}))
319
327
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gd_bam
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.28
4
+ version: 0.1.29
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-09-05 00:00:00.000000000 Z
12
+ date: 2013-09-12 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake