db_blaster 0.1.4 → 0.1.8

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9313d3abe0bd4dcaa756dab6b07b1d65eb6438b435c914d18f9d38964f08a29d
4
- data.tar.gz: c694940facb41fb3656d011baba720ffb5f66cf124472f945d7de45661ba90b5
3
+ metadata.gz: 548f2aefb696e0417a36de5169343570ca93d4d02fe04bdf13806f48be794d05
4
+ data.tar.gz: ac6a6829cfaa8523b7151b585a4037b602faeb87d6166f021679ab863a8c986b
5
5
  SHA512:
6
- metadata.gz: c045adce6f5a4fb70be59194f6f4630879761011be805dbed09c9be225a415a807ffe60a2b33ccf5361e49ce595b87250f8b0e67f370c29d867254928a36e41f
7
- data.tar.gz: 4b509898ced3205b588248700a75a375ddc6c614611298f0af347ef1a45b35f4c3d1adc9ae0a70d357c56050f47a7225d454564c22a350a21cec45da0effe322
6
+ metadata.gz: fff1f7224220a29d7318f8d9dd793a72e3696db4f61c7829de45d4e90ab431863893ac41abbf7f779cdcc5eab9e8ef17ab4128115ad4e327d8441fdb737035e3
7
+ data.tar.gz: c4bb757b9123e612ae42768a892b7a8cd2444f322ff3eb41d33b16ecd877fcdef9e33d3f7f6cd92fda72339207accb7f2ea2eb6d74f4d24a661cfe28c4c80343
@@ -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,15 +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:
36
- # {"meta" : {"infra_id" : "061", "src_app" : "kcp-api", "src_table" : "the-table"}, "records" : [] }
37
37
  attr_accessor :s3_meta
38
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
+
39
46
  # Optional
40
47
  # Applicable only when `s3_bucket` is set
41
48
  # The S3 key. The following values will get substituted:
42
- # <batch_timestamp> - a timestamp signifying the beginning of the batch processing
43
- # <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
44
53
  # <table_name> - the name of the table associated with the S3 body
45
54
  # <uuid> - a universal identifier
46
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,6 +14,8 @@ module DbBlaster
14
14
  end
15
15
 
16
16
  def content
17
+ return meta_records if DbBlaster.configuration.s3_meta_format == Configuration::INLINE_S3_META_FORMAT
18
+
17
19
  { meta: meta,
18
20
  records: records }
19
21
  end
@@ -28,7 +30,11 @@ module DbBlaster
28
30
  end
29
31
 
30
32
  def meta
31
- (DbBlaster.configuration.s3_meta.presence || {}).merge(source_table: source_table.name)
33
+ @meta ||= (DbBlaster.configuration.s3_meta.presence || {}).merge(source_table: source_table.name)
34
+ end
35
+
36
+ def meta_records
37
+ records.collect { |record| record.merge(meta) }
32
38
  end
33
39
 
34
40
  def client
@@ -0,0 +1,32 @@
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
+ ActiveRecord::Base.connection.tables.each_with_object({}) do |table_name, hash|
12
+ unless AvailableTables::SYSTEM_TABLES.include?(table_name)
13
+ hash[table_name] = build_columns_from_table_name(table_name)
14
+ end
15
+ end
16
+ end
17
+
18
+ def build_columns_from_table_name(table_name)
19
+ ActiveRecord::Base.connection.columns(table_name).collect do |column|
20
+ next if ignored_column?(column.name)
21
+
22
+ { name: column.name,
23
+ type: column.type,
24
+ limit: column.limit }
25
+ end.compact
26
+ end
27
+
28
+ def ignored_column?(column)
29
+ (DbBlaster.configuration.ignored_column_names || []).include?(column)
30
+ end
31
+ end
32
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module DbBlaster
4
- VERSION = '0.1.4'
4
+ VERSION = '0.1.8'
5
5
  end
data/lib/db_blaster.rb CHANGED
@@ -15,6 +15,7 @@ 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'
18
19
 
19
20
  # Top-level module that serves as an entry point
20
21
  # 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'
@@ -32,8 +31,7 @@ DbBlaster.configure do |config|
32
31
  # Applicable only when `s3_bucket' is set
33
32
  # Extra meta values sent along with each payload
34
33
  # example: config.s3_meta = {'infra_id' => '061'}
35
- # The resulting JSON:
36
- # {"meta" : {"infra_id" : "061", "source_app" : "kcp-api", "src_table" : "the-table"}, "records" : [] }
34
+ # The resulting JSON will include the `meta` merged into every record.
37
35
  # config.s3_meta = {'infra_id' => '061'}
38
36
 
39
37
  # Optional
@@ -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.4
4
+ version: 0.1.8
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-21 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,7 @@ 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
150
152
  - lib/db_blaster/version.rb
151
153
  - lib/generators/db_blaster/install/install_generator.rb
152
154
  - lib/generators/db_blaster/install/templates/db_blaster_config.rb
@@ -173,7 +175,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
173
175
  - !ruby/object:Gem::Version
174
176
  version: '0'
175
177
  requirements: []
176
- rubygems_version: 3.1.6
178
+ rubygems_version: 3.1.4
177
179
  signing_key:
178
180
  specification_version: 4
179
181
  summary: Push db changes to AWS SNS.