db_blaster 0.1.0 → 0.1.4
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/README.md +3 -3
- data/app/jobs/db_blaster/publish_all_job.rb +5 -1
- data/app/jobs/db_blaster/publish_source_table_job.rb +2 -2
- data/config/brakeman.ignore +6 -6
- data/lib/db_blaster/base_publisher.rb +29 -0
- data/lib/db_blaster/configuration.rb +58 -10
- data/lib/db_blaster/finder.rb +2 -13
- data/lib/db_blaster/finder_sql.rb +32 -0
- data/lib/db_blaster/publish_source_table.rb +6 -5
- data/lib/db_blaster/s3_key_builder.rb +38 -0
- data/lib/db_blaster/s3_publisher.rb +40 -0
- data/lib/db_blaster/{publisher.rb → sns_publisher.rb} +5 -13
- data/lib/db_blaster/source_table_configuration_builder.rb +6 -5
- data/lib/db_blaster/version.rb +1 -1
- data/lib/db_blaster.rb +5 -2
- data/lib/generators/db_blaster/install/templates/db_blaster_config.rb +35 -7
- metadata +21 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9313d3abe0bd4dcaa756dab6b07b1d65eb6438b435c914d18f9d38964f08a29d
|
4
|
+
data.tar.gz: c694940facb41fb3656d011baba720ffb5f66cf124472f945d7de45661ba90b5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c045adce6f5a4fb70be59194f6f4630879761011be805dbed09c9be225a415a807ffe60a2b33ccf5361e49ce595b87250f8b0e67f370c29d867254928a36e41f
|
7
|
+
data.tar.gz: 4b509898ced3205b588248700a75a375ddc6c614611298f0af347ef1a45b35f4c3d1adc9ae0a70d357c56050f47a7225d454564c22a350a21cec45da0effe322
|
data/README.md
CHANGED
@@ -2,15 +2,15 @@
|
|
2
2
|
# DbBlaster
|
3
3
|

|
4
4
|
|
5
|
-
DbBlaster
|
6
|
-
the entire database will be incrementally published
|
5
|
+
DbBlaster can either publish changed database rows to AWS SNS or push the changes to S#. The first time `DbBlaster::PublishAllJob.perform_later` is ran,
|
6
|
+
the entire database will be incrementally published. Subsequent runs will publish rows whose `updated_at` column
|
7
7
|
is more recent than the last run.
|
8
8
|
|
9
9
|
Consuming the published messages is functionality not provided by DbBlaster.
|
10
10
|
|
11
11
|
## Usage
|
12
12
|
|
13
|
-
Update `config/initializers/db_blaster_config.rb` with valid AWS credentials
|
13
|
+
Update `config/initializers/db_blaster_config.rb` with valid AWS credentials and options. Either `sns_topic` or `s3_bucket` must be set!
|
14
14
|
|
15
15
|
Schedule `DbBlaster::PublishAllJob.perform_later` to run periodically with something
|
16
16
|
like [sidekiq-cron](https://github.com/ondrejbartas/sidekiq-cron) or [whenever](https://github.com/javan/whenever)
|
@@ -13,8 +13,12 @@ module DbBlaster
|
|
13
13
|
.build_all(DbBlaster.configuration))
|
14
14
|
|
15
15
|
DbBlaster::SourceTable.pluck(:id).each do |source_table_id|
|
16
|
-
PublishSourceTableJob.perform_later(source_table_id)
|
16
|
+
PublishSourceTableJob.perform_later(source_table_id, batch_start_time)
|
17
17
|
end
|
18
18
|
end
|
19
|
+
|
20
|
+
def batch_start_time
|
21
|
+
@batch_start_time ||= DateTime.now.utc.strftime(DbBlaster::Configuration::DEFAULT_DATETIME_FORMAT)
|
22
|
+
end
|
19
23
|
end
|
20
24
|
end
|
@@ -6,11 +6,11 @@ module DbBlaster
|
|
6
6
|
class PublishSourceTableJob < ApplicationJob
|
7
7
|
queue_as 'default'
|
8
8
|
|
9
|
-
def perform(source_table_id)
|
9
|
+
def perform(source_table_id, batch_start_time)
|
10
10
|
source_table = SourceTable.find_by(id: source_table_id)
|
11
11
|
return unless source_table
|
12
12
|
|
13
|
-
PublishSourceTable.execute(source_table)
|
13
|
+
PublishSourceTable.execute(source_table: source_table, batch_start_time: batch_start_time)
|
14
14
|
end
|
15
15
|
end
|
16
16
|
end
|
data/config/brakeman.ignore
CHANGED
@@ -3,24 +3,24 @@
|
|
3
3
|
{
|
4
4
|
"warning_type": "SQL Injection",
|
5
5
|
"warning_code": 0,
|
6
|
-
"fingerprint": "
|
6
|
+
"fingerprint": "3fef6d99f896e29ef9346d81a1557bd3819fbc762b2aa91d44dfa25a5c095485",
|
7
7
|
"check_name": "SQL",
|
8
8
|
"message": "Possible SQL injection",
|
9
9
|
"file": "lib/db_blaster/finder.rb",
|
10
|
-
"line":
|
10
|
+
"line": 39,
|
11
11
|
"link": "https://brakemanscanner.org/docs/warning_types/sql_injection/",
|
12
|
-
"code": "ActiveRecord::Base.connection.execute(\"#{
|
12
|
+
"code": "ActiveRecord::Base.connection.execute(\"#{FinderSql.sql_for_source_table(source_table)} OFFSET #{offset}\")",
|
13
13
|
"render_path": null,
|
14
14
|
"location": {
|
15
15
|
"type": "method",
|
16
16
|
"class": "DbBlaster::Finder",
|
17
17
|
"method": "find_records_in_batches"
|
18
18
|
},
|
19
|
-
"user_input": "
|
19
|
+
"user_input": "FinderSql.sql_for_source_table(source_table)",
|
20
20
|
"confidence": "Medium",
|
21
|
-
"note": "
|
21
|
+
"note": "no sql injection"
|
22
22
|
}
|
23
23
|
],
|
24
|
-
"updated": "2021-08-
|
24
|
+
"updated": "2021-08-11 13:14:00 -0600",
|
25
25
|
"brakeman_version": "5.1.1"
|
26
26
|
}
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# publish records to SNS topic
|
4
|
+
module DbBlaster
|
5
|
+
# Base class for publishing
|
6
|
+
class BasePublisher
|
7
|
+
attr_reader :source_table, :records, :batch_start_time
|
8
|
+
|
9
|
+
def initialize(source_table, records, batch_start_time)
|
10
|
+
@source_table = source_table
|
11
|
+
@records = records
|
12
|
+
@batch_start_time = batch_start_time
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.publish(source_table:, records:, batch_start_time:)
|
16
|
+
publisher_class =
|
17
|
+
if DbBlaster.configuration.sns_topic
|
18
|
+
SnsPublisher
|
19
|
+
else
|
20
|
+
S3Publisher
|
21
|
+
end
|
22
|
+
publisher_class.new(source_table, records, batch_start_time).publish
|
23
|
+
end
|
24
|
+
|
25
|
+
def publish
|
26
|
+
raise NotImplementedError
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -2,17 +2,56 @@
|
|
2
2
|
|
3
3
|
module DbBlaster
|
4
4
|
# Configuration class for providing credentials, topics, and customizations.
|
5
|
+
# Either the `sns_topic` or `s3_bucket' must be set
|
5
6
|
class Configuration
|
6
7
|
DEFAULT_BATCH_SIZE = 100
|
7
8
|
DEFAULT_MAX_MESSAGE_SIZE_IN_KILOBYTES = 256 # max size allowed by AWS SNS
|
9
|
+
DEFAULT_S3_KEY = '<batch_date>/<batch_time>/db_blaster/<table_name>/<uuid>.json'
|
10
|
+
DEFAULT_DATETIME_FORMAT = '%Y-%m-%dT%H:%M:%S.%LZ'
|
8
11
|
|
9
12
|
# The required configuration fields
|
10
|
-
REQUIRED_FIELDS = %i[aws_access_key aws_access_secret aws_region
|
13
|
+
REQUIRED_FIELDS = %i[aws_access_key aws_access_secret aws_region].freeze
|
14
|
+
|
15
|
+
# exactly one of these fields needs to be set
|
16
|
+
EITHER_OR_FIELDS = %i[sns_topic s3_bucket].freeze
|
11
17
|
|
12
18
|
# The topic to which messages will be published
|
13
19
|
attr_accessor :sns_topic
|
20
|
+
# The s3 bucket name
|
21
|
+
attr_accessor :s3_bucket
|
14
22
|
attr_accessor :aws_access_key, :aws_access_secret, :aws_region
|
15
23
|
|
24
|
+
# Optional
|
25
|
+
# Applicable only when `sns_topic` is set
|
26
|
+
# Extra [SNS message_attributes](https://docs.aws.amazon.com/sns/latest/dg/sns-message-attributes.html)
|
27
|
+
# Attributes set here will be included in every published message
|
28
|
+
# example: config.extra_sns_message_attributes = {'infra_id' => {data_type: 'String', value: '061'}}
|
29
|
+
attr_accessor :extra_sns_message_attributes
|
30
|
+
|
31
|
+
# Optional
|
32
|
+
# Applicable only when `s3_bucket' is set
|
33
|
+
# The value set here will be included in every payload pushed to S3
|
34
|
+
# 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
|
+
attr_accessor :s3_meta
|
38
|
+
|
39
|
+
# Optional
|
40
|
+
# Applicable only when `s3_bucket` is set
|
41
|
+
# 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
|
44
|
+
# <table_name> - the name of the table associated with the S3 body
|
45
|
+
# <uuid> - a universal identifier
|
46
|
+
# '<batch_timestamp>/kcp-api/001/<table_name>/<uuid>.json'
|
47
|
+
attr_accessor :s3_key
|
48
|
+
|
49
|
+
# Optional
|
50
|
+
# Applicable only when `s3_bucket` is set
|
51
|
+
# S3 Tags
|
52
|
+
# example: config.s3_tags = { infra_id: '001', source_app: 'kcp-api', source_table: 'meetings' }
|
53
|
+
attr_accessor :s3_tags
|
54
|
+
|
16
55
|
# Global list of column names not to include in published SNS messages
|
17
56
|
# example: config.ignored_column_names = ['email', 'phone_number']
|
18
57
|
attr_accessor :ignored_column_names
|
@@ -22,6 +61,11 @@ module DbBlaster
|
|
22
61
|
# example: config.only_source_tables = ['posts', 'tags', 'comments']
|
23
62
|
attr_accessor :only_source_tables
|
24
63
|
|
64
|
+
# Optional
|
65
|
+
# If set, ignore source tables specified.
|
66
|
+
# example: config.ignore_source_tables = ['active_storage_blobs']
|
67
|
+
attr_accessor :ignore_source_tables
|
68
|
+
|
25
69
|
# Optional
|
26
70
|
# Customize batch_size and/or ignored_columns
|
27
71
|
# example:
|
@@ -29,12 +73,6 @@ module DbBlaster
|
|
29
73
|
# { source_table_name: 'comments', ignored_column_names: ['tags'] }]
|
30
74
|
attr_accessor :source_table_options
|
31
75
|
|
32
|
-
# Optional
|
33
|
-
# Extra [SNS message_attributes](https://docs.aws.amazon.com/sns/latest/dg/sns-message-attributes.html)
|
34
|
-
# Attributes set here will be included in every published message
|
35
|
-
# example: config.extra_sns_message_attributes = {'infra_id' => {data_type: 'String', value: '061'}}
|
36
|
-
attr_accessor :extra_sns_message_attributes
|
37
|
-
|
38
76
|
# Optional
|
39
77
|
# db_blaster will select and then publish `batch_size` rows at a time
|
40
78
|
# Default value is 100
|
@@ -47,12 +85,22 @@ module DbBlaster
|
|
47
85
|
|
48
86
|
# Raises error if a required field is not set
|
49
87
|
def verify!
|
50
|
-
|
88
|
+
verify_required
|
89
|
+
verify_either_or
|
90
|
+
end
|
91
|
+
|
92
|
+
def verify_either_or
|
93
|
+
either_or = EITHER_OR_FIELDS.select do |attribute|
|
51
94
|
send(attribute).nil? || send(attribute).strip.empty?
|
52
95
|
end
|
53
|
-
|
96
|
+
raise "only one of [#{either_or.join(', ')}] should be set" unless either_or.length == 1
|
97
|
+
end
|
54
98
|
|
55
|
-
|
99
|
+
def verify_required
|
100
|
+
no_values = REQUIRED_FIELDS.select do |attribute|
|
101
|
+
send(attribute).nil? || send(attribute).strip.empty?
|
102
|
+
end
|
103
|
+
raise "missing configuration values for [#{no_values.join(', ')}]" unless no_values.empty?
|
56
104
|
end
|
57
105
|
end
|
58
106
|
end
|
data/lib/db_blaster/finder.rb
CHANGED
@@ -12,7 +12,7 @@ module DbBlaster
|
|
12
12
|
@offset = 0
|
13
13
|
end
|
14
14
|
|
15
|
-
delegate :batch_size, :name,
|
15
|
+
delegate :batch_size, :name, to: :source_table, prefix: true
|
16
16
|
|
17
17
|
def self.find(source_table, &block)
|
18
18
|
new(source_table, &block).find
|
@@ -34,6 +34,7 @@ module DbBlaster
|
|
34
34
|
private
|
35
35
|
|
36
36
|
def find_records_in_batches
|
37
|
+
select_sql = FinderSql.sql_for_source_table(source_table)
|
37
38
|
loop do
|
38
39
|
result = ActiveRecord::Base.connection.execute("#{select_sql} OFFSET #{offset}")
|
39
40
|
yield(result)
|
@@ -54,17 +55,5 @@ module DbBlaster
|
|
54
55
|
def invalid_source_table_message
|
55
56
|
"source_table.name: '#{source_table_name}' does not exist!"
|
56
57
|
end
|
57
|
-
|
58
|
-
def select_sql
|
59
|
-
"SELECT * FROM #{source_table_name} #{where} ORDER BY updated_at ASC LIMIT #{source_table_batch_size}"
|
60
|
-
end
|
61
|
-
|
62
|
-
def where
|
63
|
-
return '' unless source_table_last_published_updated_at
|
64
|
-
|
65
|
-
ActiveRecord::Base.sanitize_sql_for_conditions(
|
66
|
-
['WHERE updated_at >= :updated_at', { updated_at: source_table_last_published_updated_at.to_s(:db) }]
|
67
|
-
)
|
68
|
-
end
|
69
58
|
end
|
70
59
|
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DbBlaster
|
4
|
+
# Creates the SQL needed to find records for the provided source_table
|
5
|
+
class FinderSql
|
6
|
+
attr_reader :source_table
|
7
|
+
|
8
|
+
def initialize(source_table)
|
9
|
+
@source_table = source_table
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.sql_for_source_table(source_table)
|
13
|
+
new(source_table).select_sql
|
14
|
+
end
|
15
|
+
|
16
|
+
def select_sql
|
17
|
+
"SELECT * FROM #{source_table.name} #{where} ORDER BY updated_at ASC LIMIT #{source_table.batch_size}"
|
18
|
+
end
|
19
|
+
|
20
|
+
def where
|
21
|
+
return '' unless from_updated_at
|
22
|
+
|
23
|
+
ActiveRecord::Base.sanitize_sql_for_conditions(
|
24
|
+
['WHERE updated_at >= :updated_at', { updated_at: from_updated_at.to_s(:db) }]
|
25
|
+
)
|
26
|
+
end
|
27
|
+
|
28
|
+
def from_updated_at
|
29
|
+
@from_updated_at ||= source_table.last_published_updated_at
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -4,14 +4,15 @@ module DbBlaster
|
|
4
4
|
# Given a `source_table` providing the table name,
|
5
5
|
# finds rows in `batch_size` chunks that are published to SNS
|
6
6
|
class PublishSourceTable
|
7
|
-
attr_reader :source_table
|
7
|
+
attr_reader :source_table, :batch_start_time
|
8
8
|
|
9
|
-
def initialize(source_table)
|
9
|
+
def initialize(source_table, batch_start_time)
|
10
10
|
@source_table = source_table
|
11
|
+
@batch_start_time = batch_start_time
|
11
12
|
end
|
12
13
|
|
13
|
-
def self.execute(source_table)
|
14
|
-
new(source_table).execute
|
14
|
+
def self.execute(source_table:, batch_start_time:)
|
15
|
+
new(source_table, batch_start_time).execute
|
15
16
|
end
|
16
17
|
|
17
18
|
def execute
|
@@ -20,7 +21,7 @@ module DbBlaster
|
|
20
21
|
# pessimistically lock row for the duration
|
21
22
|
source_table.with_lock do
|
22
23
|
Finder.find(source_table) do |records|
|
23
|
-
|
24
|
+
BasePublisher.publish(source_table: source_table, records: records, batch_start_time: batch_start_time)
|
24
25
|
source_table.update(last_published_updated_at: records.last['updated_at'])
|
25
26
|
end
|
26
27
|
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DbBlaster
|
4
|
+
# Builds the key to be used for the uploaded S3 Object
|
5
|
+
class S3KeyBuilder
|
6
|
+
attr_reader :source_table_name, :batch_start_time
|
7
|
+
|
8
|
+
def initialize(source_table_name, batch_start_time)
|
9
|
+
@source_table_name = source_table_name
|
10
|
+
@batch_start_time = batch_start_time
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.build(source_table_name:, batch_start_time:)
|
14
|
+
new(source_table_name, batch_start_time).build
|
15
|
+
end
|
16
|
+
|
17
|
+
def build
|
18
|
+
key = starting_key
|
19
|
+
substitutions.each do |replace, value|
|
20
|
+
key = key.gsub(replace, value)
|
21
|
+
end
|
22
|
+
key
|
23
|
+
end
|
24
|
+
|
25
|
+
def substitutions
|
26
|
+
date, time = batch_start_time.split('T')
|
27
|
+
{ '<batch_date_time>' => batch_start_time,
|
28
|
+
'<batch_date>' => date,
|
29
|
+
'<batch_time>' => time,
|
30
|
+
'<uuid>' => SecureRandom.uuid,
|
31
|
+
'<table_name>' => source_table_name }
|
32
|
+
end
|
33
|
+
|
34
|
+
def starting_key
|
35
|
+
DbBlaster.configuration.s3_key.presence || Configuration::DEFAULT_S3_KEY
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'aws-sdk-s3'
|
4
|
+
|
5
|
+
module DbBlaster
|
6
|
+
# Pushes records to S3
|
7
|
+
class S3Publisher < BasePublisher
|
8
|
+
def publish
|
9
|
+
client.put_object(bucket: DbBlaster.configuration.s3_bucket,
|
10
|
+
key: S3KeyBuilder.build(source_table_name: source_table.name,
|
11
|
+
batch_start_time: batch_start_time),
|
12
|
+
tagging: tagging,
|
13
|
+
body: content.to_json)
|
14
|
+
end
|
15
|
+
|
16
|
+
def content
|
17
|
+
{ meta: meta,
|
18
|
+
records: records }
|
19
|
+
end
|
20
|
+
|
21
|
+
def tagging
|
22
|
+
URI.encode_www_form(tags_hash)
|
23
|
+
end
|
24
|
+
|
25
|
+
def tags_hash
|
26
|
+
@tags_hash ||= { source_table: source_table.name }
|
27
|
+
.merge(DbBlaster.configuration.s3_tags.presence || {})
|
28
|
+
end
|
29
|
+
|
30
|
+
def meta
|
31
|
+
(DbBlaster.configuration.s3_meta.presence || {}).merge(source_table: source_table.name)
|
32
|
+
end
|
33
|
+
|
34
|
+
def client
|
35
|
+
@client ||= Aws::S3::Client.new(region: DbBlaster.configuration.aws_region,
|
36
|
+
credentials: Aws::Credentials.new(DbBlaster.configuration.aws_access_key,
|
37
|
+
DbBlaster.configuration.aws_access_secret))
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -1,20 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
module DbBlaster
|
5
|
-
# Publishes records to AWS SNS
|
6
|
-
class Publisher
|
7
|
-
attr_reader :source_table, :records
|
8
|
-
|
9
|
-
def initialize(source_table, records)
|
10
|
-
@source_table = source_table
|
11
|
-
@records = records
|
12
|
-
end
|
3
|
+
require 'aws-sdk-sns'
|
13
4
|
|
14
|
-
|
15
|
-
new(source_table, records).publish
|
16
|
-
end
|
5
|
+
# frozen_string_literal: true
|
17
6
|
|
7
|
+
module DbBlaster
|
8
|
+
# Publishes records to AWS SNS
|
9
|
+
class SnsPublisher < BasePublisher
|
18
10
|
def publish
|
19
11
|
topic.publish(message_attributes: message_attributes,
|
20
12
|
message: records.to_json)
|
@@ -45,11 +45,12 @@ module DbBlaster
|
|
45
45
|
end
|
46
46
|
|
47
47
|
def table_names_for_configuration
|
48
|
-
if configuration.only_source_tables&.length&.positive?
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
48
|
+
table_names = if configuration.only_source_tables&.length&.positive?
|
49
|
+
available_tables & configuration.only_source_tables
|
50
|
+
else
|
51
|
+
available_tables
|
52
|
+
end
|
53
|
+
table_names - (configuration.ignore_source_tables || [])
|
53
54
|
end
|
54
55
|
end
|
55
56
|
end
|
data/lib/db_blaster/version.rb
CHANGED
data/lib/db_blaster.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'aws-sdk-sns'
|
4
3
|
require 'db_blaster/version'
|
5
4
|
require 'db_blaster/engine'
|
6
5
|
require 'db_blaster/one_record_too_large_error'
|
@@ -8,9 +7,13 @@ require 'db_blaster/available_tables'
|
|
8
7
|
require 'db_blaster/configuration'
|
9
8
|
require 'db_blaster/source_table_configuration'
|
10
9
|
require 'db_blaster/source_table_configuration_builder'
|
11
|
-
require 'db_blaster/
|
10
|
+
require 'db_blaster/base_publisher'
|
11
|
+
require 'db_blaster/s3_key_builder'
|
12
|
+
require 'db_blaster/s3_publisher'
|
13
|
+
require 'db_blaster/sns_publisher'
|
12
14
|
require 'db_blaster/publish_source_table'
|
13
15
|
require 'db_blaster/chunker'
|
16
|
+
require 'db_blaster/finder_sql'
|
14
17
|
require 'db_blaster/finder'
|
15
18
|
|
16
19
|
# Top-level module that serves as an entry point
|
@@ -1,12 +1,41 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# Either `sns_topic` or `s3_bucket` must be set
|
3
4
|
DbBlaster.configure do |config|
|
4
|
-
# SNS topic to receive database changes
|
5
|
+
# SNS topic to receive database changes. Either `sns_topic` or `s3_bucket` must be set
|
5
6
|
config.sns_topic = 'the-topic'
|
6
7
|
config.aws_access_key = 'access-key'
|
7
8
|
config.aws_access_secret = 'secret'
|
8
9
|
config.aws_region = 'region'
|
9
10
|
|
11
|
+
# Optional
|
12
|
+
# Applicable only when `sns_topic` is set
|
13
|
+
# Extra [SNS message_attributes](https://docs.aws.amazon.com/sns/latest/dg/sns-message-attributes.html)
|
14
|
+
# Attributes set here will be included in every published message
|
15
|
+
# config.extra_sns_message_attributes = {'infra_id' => {data_type: 'String', value: '061'}}
|
16
|
+
|
17
|
+
# S3 bucket where JSON will be pushed. Either `sns_topic` or `s3_bucket` must be set
|
18
|
+
# config.s3_bucket = 'bucket-name'
|
19
|
+
|
20
|
+
# Optional
|
21
|
+
# Applicable only when `s3_bucket` is set
|
22
|
+
# The S3 key path. The following values will get substituted:
|
23
|
+
# <batch_date_time> - a timestamp signifying the beginning of the batch processing
|
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
|
27
|
+
# <table_name> - the name of the table associated with the S3 body
|
28
|
+
# <uuid> - a universal identifier
|
29
|
+
# config.s3_key = '<batch_timestamp>/kcp-api/001/<table_name>/<uuid>.json'
|
30
|
+
|
31
|
+
# Optional
|
32
|
+
# Applicable only when `s3_bucket' is set
|
33
|
+
# Extra meta values sent along with each payload
|
34
|
+
# 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" : [] }
|
37
|
+
# config.s3_meta = {'infra_id' => '061'}
|
38
|
+
|
10
39
|
# Optional
|
11
40
|
# db_blaster will select and then publish `batch_size` rows at a time
|
12
41
|
# config.batch_size = 100
|
@@ -14,12 +43,7 @@ DbBlaster.configure do |config|
|
|
14
43
|
# Optional
|
15
44
|
# db_blaster will publish no messages larger than this value
|
16
45
|
# Default value is 256
|
17
|
-
#
|
18
|
-
|
19
|
-
# Optional
|
20
|
-
# Extra [SNS message_attributes](https://docs.aws.amazon.com/sns/latest/dg/sns-message-attributes.html)
|
21
|
-
# Attributes set here will be included in every published message
|
22
|
-
# config.extra_sns_message_attributes = {'infra_id' => {data_type: 'String', value: '061'}}
|
46
|
+
# config.max_message_size_in_kilobytes = 256
|
23
47
|
|
24
48
|
# Global list of column names not to include in published SNS messages
|
25
49
|
# example: config.ignored_column_names = ['email', 'phone_number']
|
@@ -29,6 +53,10 @@ DbBlaster.configure do |config|
|
|
29
53
|
# If set, only publish tables specified.
|
30
54
|
# config.only_source_tables = ['posts', 'tags', 'comments']
|
31
55
|
|
56
|
+
# Optional
|
57
|
+
# If set, ignore source tables specified.
|
58
|
+
# config.ignore_source_tables = ['active_storage_blobs']
|
59
|
+
|
32
60
|
# Optional
|
33
61
|
# Customize batch_size and/or ignored_columns
|
34
62
|
# example:
|
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
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.4
|
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-
|
11
|
+
date: 2021-09-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: aws-sdk-s3
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: aws-sdk-sns
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -119,14 +133,18 @@ files:
|
|
119
133
|
- db/migrate/20210727222252_create_source_tables.rb
|
120
134
|
- lib/db_blaster.rb
|
121
135
|
- lib/db_blaster/available_tables.rb
|
136
|
+
- lib/db_blaster/base_publisher.rb
|
122
137
|
- lib/db_blaster/chunker.rb
|
123
138
|
- lib/db_blaster/configuration.rb
|
124
139
|
- lib/db_blaster/engine.rb
|
125
140
|
- lib/db_blaster/finder.rb
|
141
|
+
- lib/db_blaster/finder_sql.rb
|
126
142
|
- lib/db_blaster/one_record_too_large_error.rb
|
127
143
|
- lib/db_blaster/publish_source_table.rb
|
128
|
-
- lib/db_blaster/publisher.rb
|
129
144
|
- lib/db_blaster/rspec.rb
|
145
|
+
- lib/db_blaster/s3_key_builder.rb
|
146
|
+
- lib/db_blaster/s3_publisher.rb
|
147
|
+
- lib/db_blaster/sns_publisher.rb
|
130
148
|
- lib/db_blaster/source_table_configuration.rb
|
131
149
|
- lib/db_blaster/source_table_configuration_builder.rb
|
132
150
|
- lib/db_blaster/version.rb
|