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 +4 -4
- data/db/migrate/20210908214439_add_last_published_id.rb +8 -0
- data/lib/db_blaster/configuration.rb +13 -4
- data/lib/db_blaster/finder_sql.rb +11 -1
- data/lib/db_blaster/publish_source_table.rb +2 -1
- data/lib/db_blaster/s3_key_builder.rb +2 -0
- data/lib/db_blaster/s3_publisher.rb +7 -1
- data/lib/db_blaster/source_tables_schema_builder.rb +32 -0
- data/lib/db_blaster/version.rb +1 -1
- data/lib/db_blaster.rb +1 -0
- data/lib/generators/db_blaster/install/templates/db_blaster_config.rb +2 -4
- data/lib/tasks/db_blaster_tasks.rake +13 -4
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 548f2aefb696e0417a36de5169343570ca93d4d02fe04bdf13806f48be794d05
|
4
|
+
data.tar.gz: ac6a6829cfaa8523b7151b585a4037b602faeb87d6166f021679ab863a8c986b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
# <
|
43
|
-
# <
|
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
|
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
|
data/lib/db_blaster/version.rb
CHANGED
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
|
-
# <
|
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
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
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
|
+
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-
|
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.
|
178
|
+
rubygems_version: 3.1.4
|
177
179
|
signing_key:
|
178
180
|
specification_version: 4
|
179
181
|
summary: Push db changes to AWS SNS.
|