db_blaster 0.1.5 → 0.1.9

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: 2de00cf222282fde0e0a3e38078ccc398a80ff19c41ccf7b79ecd043450db6b1
4
- data.tar.gz: 66b93222044a44bcd7dd35a6233de5c4839a58d5106e527a7d540be2daee9821
3
+ metadata.gz: 7e58f97f7c15cb1bb2d1bf1d4235e68e5d256adaf48f72481cb3c754f1d85aae
4
+ data.tar.gz: ffa443a609d6d2b10b7e7e3b65bdc45da8abfc8485b7f3fb46fa638ea1b0cd98
5
5
  SHA512:
6
- metadata.gz: 7305baf42dff923be85d8105625bf3ccf8200988d7895c80202a32232b062a9c613863a002a7b8e57d7e57a3660725ab4ed6765d2b2d3ba49f3b216da2614dac
7
- data.tar.gz: 8652430ce86f2ee275997ec35e52bf2ba99befa4c3a8630b13e0ca57f309d4b0fb013974806e52882bc37bd95a6c4e9e9d4ea51fa5a2096d2767df0d3608b796
6
+ metadata.gz: fd27fea13565a8f90a3d0b4db4fcac631453fc9579b35f5ad7e4061e7f4cc7bea01e12307efd5a865583f781cb793ceb50f6646708912edcef8742b5a3551f53
7
+ data.tar.gz: ca998517216be98f3c3d47d9e0f393aa230dd04a08cf54a0dfeb1fb734246f7e1d388c00b698b92eab7bded131addded3ffc413b9d029e1aa2f5ac3aadf78928
@@ -9,8 +9,7 @@ module DbBlaster
9
9
  queue_as 'default'
10
10
 
11
11
  def perform
12
- SourceTable.sync(SourceTableConfigurationBuilder
13
- .build_all(DbBlaster.configuration))
12
+ SyncSourceTablesWithConfiguration.sync
14
13
 
15
14
  DbBlaster::SourceTable.pluck(:id).each do |source_table_id|
16
15
  PublishSourceTableJob.perform_later(source_table_id, batch_start_time)
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Adding last_published_id to avoid dupes in selecting sourcetables
4
+ class AddLastPublishedId < ActiveRecord::Migration[6.1]
5
+ def change
6
+ add_column :db_blaster_source_tables, :last_published_id, :string, default: '0'
7
+ end
8
+ end
@@ -8,6 +8,8 @@ module DbBlaster
8
8
  DEFAULT_MAX_MESSAGE_SIZE_IN_KILOBYTES = 256 # max size allowed by AWS SNS
9
9
  DEFAULT_S3_KEY = '<batch_date>/<batch_time>/db_blaster/<table_name>/<uuid>.json'
10
10
  DEFAULT_DATETIME_FORMAT = '%Y-%m-%dT%H:%M:%S.%LZ'
11
+ ATTRIBUTE_S3_META_FORMAT = 'attribute' # { meta: {your: :value}, records: [] }
12
+ INLINE_S3_META_FORMAT = 'inline' # records.collect{|record| record.merge(meta) }
11
13
 
12
14
  # The required configuration fields
13
15
  REQUIRED_FIELDS = %i[aws_access_key aws_access_secret aws_region].freeze
@@ -32,14 +34,22 @@ module DbBlaster
32
34
  # Applicable only when `s3_bucket' is set
33
35
  # The value set here will be included in every payload pushed to S3
34
36
  # example: config.s3_meta = {'infra_id' => '061', 'source_app' => 'kcp-api'}}
35
- # The resulting JSON will include the `meta` merged into every record
36
37
  attr_accessor :s3_meta
37
38
 
39
+ # Optional
40
+ # Options: ['attribute', 'inline']
41
+ # Defaults to 'attribute'
42
+ # 'attribute' payload: { meta: `s3_meta`, records: [source_table_records] }
43
+ # 'inline' payload: records.collect{|record| record.merge(meta) }
44
+ attr_accessor :s3_meta_format
45
+
38
46
  # Optional
39
47
  # Applicable only when `s3_bucket` is set
40
48
  # The S3 key. The following values will get substituted:
41
- # <batch_timestamp> - a timestamp signifying the beginning of the batch processing
42
- # <timestamp> - the current time
49
+ # <batch_date_time> - date time when batch started
50
+ # <batch_date> - date when batch started
51
+ # <batch_time - time when batch started
52
+ # <date_time> - the datetime just before pushing to S3
43
53
  # <table_name> - the name of the table associated with the S3 body
44
54
  # <uuid> - a universal identifier
45
55
  # '<batch_timestamp>/kcp-api/001/<table_name>/<uuid>.json'
@@ -17,16 +17,26 @@ module DbBlaster
17
17
  "SELECT * FROM #{source_table.name} #{where} ORDER BY updated_at ASC LIMIT #{source_table.batch_size}"
18
18
  end
19
19
 
20
+ # if we just use updated_at > from_updated_at, it's possible to miss records
21
+ # that share the same `updated_at`
22
+ # if we use updated_at >= from_updated_at, we'll get redundant records on every run
23
+ # settled on the approach below
20
24
  def where
21
25
  return '' unless from_updated_at
22
26
 
23
27
  ActiveRecord::Base.sanitize_sql_for_conditions(
24
- ['WHERE updated_at >= :updated_at', { updated_at: from_updated_at.to_s(:db) }]
28
+ ['WHERE updated_at > :updated_at OR (updated_at = :updated_at AND id <> :updated_id)',
29
+ { updated_at: from_updated_at,
30
+ updated_id: last_published_id }]
25
31
  )
26
32
  end
27
33
 
28
34
  def from_updated_at
29
35
  @from_updated_at ||= source_table.last_published_updated_at
30
36
  end
37
+
38
+ def last_published_id
39
+ @last_published_id ||= source_table.last_published_id
40
+ end
31
41
  end
32
42
  end
@@ -22,7 +22,8 @@ module DbBlaster
22
22
  source_table.with_lock do
23
23
  Finder.find(source_table) do |records|
24
24
  BasePublisher.publish(source_table: source_table, records: records, batch_start_time: batch_start_time)
25
- source_table.update(last_published_updated_at: records.last['updated_at'])
25
+ source_table.update(last_published_updated_at: records.last['updated_at'],
26
+ last_published_id: records.last['id'])
26
27
  end
27
28
  end
28
29
  self
@@ -23,10 +23,12 @@ module DbBlaster
23
23
  end
24
24
 
25
25
  def substitutions
26
+ date_time = DateTime.now.utc.strftime(DbBlaster::Configuration::DEFAULT_DATETIME_FORMAT)
26
27
  date, time = batch_start_time.split('T')
27
28
  { '<batch_date_time>' => batch_start_time,
28
29
  '<batch_date>' => date,
29
30
  '<batch_time>' => time,
31
+ '<date_time>' => date_time,
30
32
  '<uuid>' => SecureRandom.uuid,
31
33
  '<table_name>' => source_table_name }
32
34
  end
@@ -14,7 +14,10 @@ module DbBlaster
14
14
  end
15
15
 
16
16
  def content
17
- meta_records
17
+ return meta_records if DbBlaster.configuration.s3_meta_format == Configuration::INLINE_S3_META_FORMAT
18
+
19
+ { meta: meta,
20
+ records: records }
18
21
  end
19
22
 
20
23
  def tagging
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DbBlaster
4
+ # Builds an array of tables and their columns
5
+ class SourceTablesSchemaBuilder
6
+ def self.build_schema
7
+ new.build_schema
8
+ end
9
+
10
+ def build_schema
11
+ SyncSourceTablesWithConfiguration.sync
12
+
13
+ DbBlaster::SourceTable.all.each_with_object({}) do |source_table, hash|
14
+ hash[source_table.name] = build_columns_from_source_table(source_table)
15
+ end
16
+ end
17
+
18
+ def build_columns_from_source_table(source_table)
19
+ ActiveRecord::Base.connection.columns(source_table.name).collect do |column|
20
+ next if source_table.ignored_columns.include?(column.name)
21
+
22
+ { name: column.name,
23
+ type: column.type,
24
+ limit: column.limit }
25
+ end.compact
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DbBlaster
4
+ # Update the db-blaster source tables based on provided configuration
5
+ module SyncSourceTablesWithConfiguration
6
+ def self.sync
7
+ SourceTable.sync(SourceTableConfigurationBuilder
8
+ .build_all(DbBlaster.configuration))
9
+ end
10
+ end
11
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module DbBlaster
4
- VERSION = '0.1.5'
4
+ VERSION = '0.1.9'
5
5
  end
data/lib/db_blaster.rb CHANGED
@@ -15,6 +15,8 @@ require 'db_blaster/publish_source_table'
15
15
  require 'db_blaster/chunker'
16
16
  require 'db_blaster/finder_sql'
17
17
  require 'db_blaster/finder'
18
+ require 'db_blaster/source_tables_schema_builder'
19
+ require 'db_blaster/sync_source_tables_with_configuration'
18
20
 
19
21
  # Top-level module that serves as an entry point
20
22
  # into the engine gem
@@ -22,8 +22,7 @@ DbBlaster.configure do |config|
22
22
  # The S3 key path. The following values will get substituted:
23
23
  # <batch_date_time> - a timestamp signifying the beginning of the batch processing
24
24
  # <batch_date> - a date signifying the beginning of the batch processing
25
- # <batch_time> - a time signifying the beginning of the batch processing
26
- # <timestamp> - the current time
25
+ # <date_time> - the datetime just before pushing to S3
27
26
  # <table_name> - the name of the table associated with the S3 body
28
27
  # <uuid> - a universal identifier
29
28
  # config.s3_key = '<batch_timestamp>/kcp-api/001/<table_name>/<uuid>.json'
@@ -1,5 +1,14 @@
1
1
  # frozen_string_literal: true
2
- # desc "Explaining what the task does"
3
- # task :db_blaster do
4
- # # Task goes here
5
- # end
2
+
3
+ require 'db_blaster'
4
+
5
+ namespace :db_blaster do
6
+ desc 'generate table schema'
7
+ task generate_table_schema: :environment do
8
+ schema_name = 'kcp-api-schema.json'
9
+ puts "Generating #{schema_name}......."
10
+ built = DbBlaster::SourceTablesSchemaBuilder.build_schema
11
+ File.open(schema_name, 'w') { |f| f << built.to_json }
12
+ puts 'Success!'
13
+ end
14
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: db_blaster
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.5
4
+ version: 0.1.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Perry Hertler
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-09-02 00:00:00.000000000 Z
11
+ date: 2021-09-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: aws-sdk-s3
@@ -131,6 +131,7 @@ files:
131
131
  - config/brakeman.ignore
132
132
  - config/routes.rb
133
133
  - db/migrate/20210727222252_create_source_tables.rb
134
+ - db/migrate/20210908214439_add_last_published_id.rb
134
135
  - lib/db_blaster.rb
135
136
  - lib/db_blaster/available_tables.rb
136
137
  - lib/db_blaster/base_publisher.rb
@@ -147,6 +148,8 @@ files:
147
148
  - lib/db_blaster/sns_publisher.rb
148
149
  - lib/db_blaster/source_table_configuration.rb
149
150
  - lib/db_blaster/source_table_configuration_builder.rb
151
+ - lib/db_blaster/source_tables_schema_builder.rb
152
+ - lib/db_blaster/sync_source_tables_with_configuration.rb
150
153
  - lib/db_blaster/version.rb
151
154
  - lib/generators/db_blaster/install/install_generator.rb
152
155
  - lib/generators/db_blaster/install/templates/db_blaster_config.rb