tartarus-rb 0.4.0 → 0.6.0

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: ee9118a9365d2a74dd802218b0b0b36286c6494ecffe4f81cbf9bfed35597057
4
- data.tar.gz: f85ffe0e1f182667b5b9b522746a85b45cc9cd3452270f583549a0616d06337c
3
+ metadata.gz: d964cd9b85733405512f08d58cea33e9f12f5b6d3fa05d8fb2d1c979463ffead
4
+ data.tar.gz: 955301decdf77128432413afb6dd40612bb5c279e2cb65129f740cf1c81c1373
5
5
  SHA512:
6
- metadata.gz: '08e1ab969f1681fca948bdfb4ae98fb919e7caef4e95a1cf5a3a2dffc6fa79a59c73655927be759408f951ad0846ff5c1dea6b7396220801f31c179730e9d6e3'
7
- data.tar.gz: 72f485499631b46912293650672cd79e8df364ebbc7b18144731c1077e7fa8157be8b20e4078212b04dfb539a3de19af99abcca720163785c3132f51bf574968
6
+ metadata.gz: d455a12a6503b078c1b49e3902d840a017bfa50f99c6eee2ff17367d3398eb62b376503f84b260a90663e9c3f465ac59ba4509a1b3f9767835548853a24f3469
7
+ data.tar.gz: 2b4502ce62eb6bd831413d237e9b69535fbbe113c09e25e35f0ee680c902599bd0c52a210c0eb365ccde044c6a200da32c4b12798a6137e996a228f1192d8b10
data/Changelog.md CHANGED
@@ -2,6 +2,18 @@
2
2
 
3
3
  ## Master
4
4
 
5
+ ## 0.6.0
6
+
7
+ - Optimize query from `Tartarus::ArchivableCollectionRepository#items_older_than` by adding explicit ordering
8
+
9
+ ## 0.5.0
10
+
11
+ - Provide ability to explicitly set the name of archivable item to have multiple ways of archiving the same model
12
+
13
+ ## 0.4.1
14
+
15
+ - Do not make Glacier a required dependency if not used
16
+
5
17
  ## 0.4.0
6
18
 
7
19
  - Add Glacier remote storage support to upload data before deleting it
data/Gemfile.lock CHANGED
@@ -1,8 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- tartarus-rb (0.4.0)
5
- aws-sdk-glacier
4
+ tartarus-rb (0.6.0)
6
5
  sidekiq (>= 5)
7
6
  sidekiq-cron (~> 1)
8
7
 
@@ -58,7 +57,7 @@ GEM
58
57
  erubi (1.10.0)
59
58
  et-orbi (1.2.4)
60
59
  tzinfo
61
- fugit (1.4.2)
60
+ fugit (1.4.5)
62
61
  et-orbi (~> 1.1, >= 1.1.8)
63
62
  raabro (~> 1.4)
64
63
  hashdiff (1.0.0)
@@ -141,6 +140,7 @@ PLATFORMS
141
140
 
142
141
  DEPENDENCIES
143
142
  activerecord (~> 6)
143
+ aws-sdk-glacier
144
144
  dotenv
145
145
  pg
146
146
  postgres-copy
data/README.md CHANGED
@@ -64,6 +64,7 @@ if File.exist?(schedule_file) && Sidekiq.server?
64
64
  root_path: Rails.root.to_s,
65
65
  archive_registry_factory: ArchiveRegistry,
66
66
  )
67
+ # don't forget about installing `aws-sdk-glacier` gem
67
68
 
68
69
  tartarus.register do |item|
69
70
  item.model = YetAnotherModel
@@ -81,6 +82,31 @@ end
81
82
 
82
83
  You can use the following config params:
83
84
  - `model` - a name of the ActiveReord model you want to archive, required
85
+ - `name` - name of your strategy, optional. It fallbacks `model.to_s`. It's important to set in in cases when you have several strategies for the same model:
86
+ ```rb
87
+ tartarus.register do |item|
88
+ item.model = InternalEvent
89
+ item.name = "archive_account_and_user_internal_events"
90
+ item.cron = "5 5 * * *"
91
+ item.queue = "default"
92
+ item.tenants_range = -> { ["Account", "User"] }
93
+ item.tenant_id_field = :model_type
94
+ item.archive_items_older_than = -> { 30.days.ago }
95
+ item.timestamp_field = :created_at
96
+ end
97
+
98
+ tartarus.register do |item|
99
+ item.model = InternalEvent
100
+ item.name = "archive_post_and_comment_internal_events"
101
+ item.cron = "5 15 * * *"
102
+ item.queue = "default"
103
+ item.tenants_range = -> { ["Post", "Comment"] }
104
+ item.tenant_id_field = :model_type
105
+ item.archive_items_older_than = -> { 10.days.ago }
106
+ item.timestamp_field = :created_at
107
+ end
108
+ ```
109
+
84
110
  - `cron` - cron syntax, required
85
111
  - `queue` - name of the sidekiq queue you want to use for execution of the jobs, required
86
112
  - `tenants_range` - optional, use if you want to scope items by a tenant (or any field that can be used for partitioning). It doesn't have to be ActiveRecord collection, could be just an array. Must be a proc/lambda/object responding to `call` method. For ActvieRecord collection, `find_each` loop will be used for optimization.
@@ -90,7 +116,7 @@ You can use the following config params:
90
116
  - `timestamp_field` - required, used for performing a query using the value from `archive_items_older_than`
91
117
  - `archive_with` - optional (defaults to `delete_all`). Could be `delete_all`, `destroy_all`, `delete_all_without_batches`, `destroy_all_without_batches`, `delete_all_using_limit_in_batches`
92
118
  - `batch_size` - optional (defaults to `10_000`, used with `delete_all_using_limit_in_batches` strategy)
93
- - `remote_storage` - optional (defaults to `Tartarus::RemoteStorage::Null` which does nothing). Use this option if you want store the data somewhere before deleting it.
119
+ - `remote_storage` - optional (defaults to `Tartarus::RemoteStorage::Null` which does nothing). Use this option if you want store the data somewhere before deleting it.
94
120
 
95
121
  ### Remote Storage
96
122
 
@@ -99,6 +125,7 @@ Currently, only `Glacier` (for AWS Glacier) is supported. Also, it works only wi
99
125
  To take advantage of this feature you will need a couple of things:
100
126
  1. Apply `acts_as_copy_target` to the archivable model (from `postgres-copy` gem).
101
127
  2. Create a model that will be used as a registry for all uploads that happened.
128
+ 3. Install `aws-sdk-glacier` gem.
102
129
 
103
130
  If you want to make `Version` model archivable and use `ArchiveRegistry` as the registry, you will need the following models and tables:
104
131
 
@@ -155,6 +182,9 @@ glacier_configuration = Tartarus::RemoteStorage::Glacier::Configuration.build(
155
182
  Tartarus::RemoteStorage::Glacier.new(glacier_configuration)
156
183
  ```
157
184
 
185
+ **Important** - do not use Glacier Storage for large batches (> 4 GB) as multipart uploads are not supported yet.
186
+
187
+
158
188
  If you know what you are doing, you can add your own storage, as long as it complies with the following interface:
159
189
 
160
190
  ``` rb
@@ -166,7 +196,7 @@ class Glacier
166
196
  @configuration = configuration
167
197
  end
168
198
 
169
- def store(collection, archivable_model, tenant_id: nil, tenant_id_field: nil)
199
+ def store(collection, archivable_model, tenant_id: nil, tenant_id_field: nil)
170
200
  end
171
201
  end
172
202
  ```
@@ -20,7 +20,7 @@ class Tartarus
20
20
  collection = collection_for(model_name)
21
21
  ensure_column_exists(collection, model_name, timestamp_field)
22
22
 
23
- collection.where("#{timestamp_field} < ?", timestamp)
23
+ collection.where("#{timestamp_field} < ?", timestamp).order(timestamp_field)
24
24
  end
25
25
 
26
26
  private
@@ -7,7 +7,7 @@ class Tartarus
7
7
  description: description_for_item(archivable_item),
8
8
  cron: archivable_item.cron,
9
9
  class: Tartarus::Sidekiq::ScheduleArchivingModelJob,
10
- args: [archivable_item.model],
10
+ args: [archivable_item.name],
11
11
  queue: archivable_item.queue,
12
12
  active_job: archivable_item.active_job
13
13
  }
@@ -16,7 +16,7 @@ class Tartarus
16
16
  private
17
17
 
18
18
  def name_for_item(archivable_item)
19
- "TARTARUS_#{archivable_item.model}"
19
+ "TARTARUS_#{archivable_item.name}"
20
20
  end
21
21
 
22
22
  def description_for_item(archivable_item)
@@ -1,7 +1,7 @@
1
1
  class Tartarus::ArchivableItem
2
2
  REQUIRED_ATTRIBUTES_NAMES = %i(model cron queue archive_items_older_than timestamp_field active_job
3
3
  archive_with tenant_value_source).freeze
4
- OPTIONAL_ATTRIBUTES_NAMES = %i(tenants_range tenant_id_field batch_size remote_storage).freeze
4
+ OPTIONAL_ATTRIBUTES_NAMES = %i(tenants_range tenant_id_field batch_size remote_storage name).freeze
5
5
 
6
6
  attr_accessor *(REQUIRED_ATTRIBUTES_NAMES + OPTIONAL_ATTRIBUTES_NAMES)
7
7
 
@@ -51,6 +51,10 @@ class Tartarus::ArchivableItem
51
51
  @batch_size ||= 10_000
52
52
  end
53
53
 
54
+ def name
55
+ @name || @model.to_s
56
+ end
57
+
54
58
  def validate!
55
59
  validate_presence
56
60
  end
@@ -63,10 +67,6 @@ class Tartarus::ArchivableItem
63
67
  factory.for(archive_with, batch_size: batch_size)
64
68
  end
65
69
 
66
- def for_model?(provided_model_name)
67
- model.to_s == provided_model_name.to_s
68
- end
69
-
70
70
  def remote_storage
71
71
  @remote_storage || Tartarus::RemoteStorage::Null
72
72
  end
@@ -7,20 +7,20 @@ class Tartarus::ArchiveModelWithTenant
7
7
  @repository = repository
8
8
  end
9
9
 
10
- def archive(model_name, tenant_id)
11
- archivable_item = registry.find_by_model(model_name)
12
- collection = collection_to_archive(model_name, archivable_item, tenant_id)
13
- archivable_item.remote_storage.store(collection, model_name, tenant_id: tenant_id,
10
+ def archive(archivable_item_name, tenant_id)
11
+ archivable_item = registry.find_by_name(archivable_item_name)
12
+ collection = collection_to_archive(archivable_item, tenant_id)
13
+ archivable_item.remote_storage.store(collection, archivable_item.name, tenant_id: tenant_id,
14
14
  tenant_id_field: archivable_item.tenant_id_field)
15
15
  archivable_item.archive_strategy.call(collection)
16
16
  end
17
17
 
18
18
  private
19
19
 
20
- def collection_to_archive(model_name, archivable_item, tenant_id)
20
+ def collection_to_archive(archivable_item, tenant_id)
21
21
  repository
22
22
  .items_older_than_for_tenant(
23
- model_name,
23
+ archivable_item.model,
24
24
  archivable_item.timestamp_field, archivable_item.archive_items_older_than.call,
25
25
  archivable_item.tenant_id_field, tenant_id
26
26
  )
@@ -7,19 +7,19 @@ class Tartarus::ArchiveModelWithoutTenant
7
7
  @repository = repository
8
8
  end
9
9
 
10
- def archive(model_name)
11
- archivable_item = registry.find_by_model(model_name)
12
- collection = collection_to_archive(model_name, archivable_item)
13
- archivable_item.remote_storage.store(collection, model_name)
10
+ def archive(archivable_item_name)
11
+ archivable_item = registry.find_by_name(archivable_item_name)
12
+ collection = collection_to_archive(archivable_item)
13
+ archivable_item.remote_storage.store(collection, archivable_item.name)
14
14
  archivable_item.archive_strategy.call(collection)
15
15
  end
16
16
 
17
17
  private
18
18
 
19
- def collection_to_archive(model_name, archivable_item)
19
+ def collection_to_archive(archivable_item)
20
20
  repository
21
21
  .items_older_than(
22
- model_name,
22
+ archivable_item.model,
23
23
  archivable_item.timestamp_field, archivable_item.archive_items_older_than.call
24
24
  )
25
25
  end
@@ -1,5 +1,5 @@
1
1
  class Tartarus
2
2
  module Rb
3
- VERSION = "0.4.0"
3
+ VERSION = "0.6.0"
4
4
  end
5
5
  end
@@ -16,8 +16,8 @@ class Tartarus::Registry
16
16
  @storage << item
17
17
  end
18
18
 
19
- def find_by_model(model)
20
- storage.find(->{ raise "#{model} not found in registry" }) { |item| item.for_model?(model) }
19
+ def find_by_name(name)
20
+ storage.find(->{ raise "#{name} not found in registry" }) { |item| item.name == name }
21
21
  end
22
22
 
23
23
  def reset
@@ -1,3 +1,10 @@
1
+ require "aws-sdk-glacier"
2
+ require "tartarus/remote_storage/glacier/client"
3
+ require "tartarus/remote_storage/glacier/file"
4
+ require "tartarus/remote_storage/glacier/csv_export"
5
+ require "tartarus/remote_storage/glacier/register_upload"
6
+ require "tartarus/remote_storage/glacier/configuration"
7
+
1
8
  class Tartarus
2
9
  module RemoteStorage
3
10
  class Glacier
@@ -1,2 +1,4 @@
1
1
  module Tartarus::RemoteStorage
2
+ autoload :Glacier, "tartarus/remote_storage/glacier"
3
+ autoload :Null, "tartarus/remote_storage/null"
2
4
  end
@@ -6,15 +6,15 @@ class Tartarus::ScheduleArchivingModel
6
6
  @registry = registry
7
7
  end
8
8
 
9
- def schedule(model_name)
10
- archivable_item = registry.find_by_model(model_name)
9
+ def schedule(archivable_item_name)
10
+ archivable_item = registry.find_by_name(archivable_item_name)
11
11
 
12
12
  if archivable_item.scope_by_tenant?
13
13
  each_tenant(archivable_item) do |tenant|
14
- enqueue(Tartarus::Sidekiq::ArchiveModelWithTenantJob, archivable_item.queue, model_name, tenant)
14
+ enqueue(Tartarus::Sidekiq::ArchiveModelWithTenantJob, archivable_item.queue, archivable_item.name, tenant)
15
15
  end
16
16
  else
17
- enqueue(Tartarus::Sidekiq::ArchiveModelWithoutTenantJob, archivable_item.queue, model_name)
17
+ enqueue(Tartarus::Sidekiq::ArchiveModelWithoutTenantJob, archivable_item.queue, archivable_item.name)
18
18
  end
19
19
  end
20
20
 
@@ -4,8 +4,8 @@ class Tartarus
4
4
  class Sidekiq::ArchiveModelWithTenantJob
5
5
  include ::Sidekiq::Worker
6
6
 
7
- def perform(model_name, tenant_id)
8
- Tartarus::ArchiveModelWithTenant.new.archive(model_name, tenant_id)
7
+ def perform(archivable_item_name, tenant_id)
8
+ Tartarus::ArchiveModelWithTenant.new.archive(archivable_item_name, tenant_id)
9
9
  end
10
10
  end
11
11
  end
@@ -4,8 +4,8 @@ class Tartarus
4
4
  class Sidekiq::ArchiveModelWithoutTenantJob
5
5
  include ::Sidekiq::Worker
6
6
 
7
- def perform(model_name)
8
- Tartarus::ArchiveModelWithoutTenant.new.archive(model_name)
7
+ def perform(archivable_item_name)
8
+ Tartarus::ArchiveModelWithoutTenant.new.archive(archivable_item_name)
9
9
  end
10
10
  end
11
11
  end
@@ -4,8 +4,8 @@ class Tartarus
4
4
  class Sidekiq::ScheduleArchivingModelJob
5
5
  include ::Sidekiq::Worker
6
6
 
7
- def perform(model_name)
8
- Tartarus::ScheduleArchivingModel.new.schedule(model_name)
7
+ def perform(archivable_item_name)
8
+ Tartarus::ScheduleArchivingModel.new.schedule(archivable_item_name)
9
9
  end
10
10
  end
11
11
  end
data/lib/tartarus.rb CHANGED
@@ -19,15 +19,7 @@ require "tartarus/registry"
19
19
  require "tartarus/repository"
20
20
  require "tartarus/schedule_archiving_model"
21
21
  require "tartarus/remote_storage"
22
- require "tartarus/remote_storage/null"
23
- require "tartarus/remote_storage/glacier"
24
- require "tartarus/remote_storage/glacier/client"
25
- require "tartarus/remote_storage/glacier/file"
26
- require "tartarus/remote_storage/glacier/csv_export"
27
- require "tartarus/remote_storage/glacier/register_upload"
28
- require "tartarus/remote_storage/glacier/configuration"
29
22
  require "sidekiq/cron/job"
30
- require "aws-sdk-glacier"
31
23
  require "sidekiq"
32
24
 
33
25
  class Tartarus
data/tartarus-rb.gemspec CHANGED
@@ -29,11 +29,12 @@ Gem::Specification.new do |spec|
29
29
 
30
30
  spec.add_dependency "sidekiq", ">= 5"
31
31
  spec.add_dependency "sidekiq-cron", "~> 1"
32
- spec.add_dependency "aws-sdk-glacier"
32
+
33
33
 
34
34
  spec.add_development_dependency "rake", "~> 13.0"
35
35
  spec.add_development_dependency "rspec", "~> 3.0"
36
36
  spec.add_development_dependency "rspec-sidekiq"
37
+ spec.add_development_dependency "aws-sdk-glacier"
37
38
 
38
39
  spec.add_development_dependency "activerecord", "~> 6"
39
40
  spec.add_development_dependency "pg"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tartarus-rb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Karol Galanciak
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-02-08 00:00:00.000000000 Z
11
+ date: 2022-02-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sidekiq
@@ -38,20 +38,6 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '1'
41
- - !ruby/object:Gem::Dependency
42
- name: aws-sdk-glacier
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - ">="
46
- - !ruby/object:Gem::Version
47
- version: '0'
48
- type: :runtime
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - ">="
53
- - !ruby/object:Gem::Version
54
- version: '0'
55
41
  - !ruby/object:Gem::Dependency
56
42
  name: rake
57
43
  requirement: !ruby/object:Gem::Requirement
@@ -94,6 +80,20 @@ dependencies:
94
80
  - - ">="
95
81
  - !ruby/object:Gem::Version
96
82
  version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: aws-sdk-glacier
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: activerecord
99
99
  requirement: !ruby/object:Gem::Requirement
@@ -264,7 +264,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
264
264
  - !ruby/object:Gem::Version
265
265
  version: '0'
266
266
  requirements: []
267
- rubygems_version: 3.1.2
267
+ rubygems_version: 3.1.4
268
268
  signing_key:
269
269
  specification_version: 4
270
270
  summary: A gem for archving (deleting) old records you no longer need. Send them straight