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 +4 -4
- data/Changelog.md +12 -0
- data/Gemfile.lock +3 -3
- data/README.md +32 -2
- data/lib/tartarus/archivable_collection_repository.rb +1 -1
- data/lib/tartarus/archivable_item/sidekiq_cron_job_serializer.rb +2 -2
- data/lib/tartarus/archivable_item.rb +5 -5
- data/lib/tartarus/archive_model_with_tenant.rb +6 -6
- data/lib/tartarus/archive_model_without_tenant.rb +6 -6
- data/lib/tartarus/rb/version.rb +1 -1
- data/lib/tartarus/registry.rb +2 -2
- data/lib/tartarus/remote_storage/glacier.rb +7 -0
- data/lib/tartarus/remote_storage.rb +2 -0
- data/lib/tartarus/schedule_archiving_model.rb +4 -4
- data/lib/tartarus/sidekiq/archive_model_with_tenant_job.rb +2 -2
- data/lib/tartarus/sidekiq/archive_model_without_tenant_job.rb +2 -2
- data/lib/tartarus/sidekiq/schedule_archiving_model_job.rb +2 -2
- data/lib/tartarus.rb +0 -8
- data/tartarus-rb.gemspec +2 -1
- metadata +17 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d964cd9b85733405512f08d58cea33e9f12f5b6d3fa05d8fb2d1c979463ffead
|
4
|
+
data.tar.gz: 955301decdf77128432413afb6dd40612bb5c279e2cb65129f740cf1c81c1373
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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.
|
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.
|
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.
|
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.
|
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(
|
11
|
-
archivable_item = registry.
|
12
|
-
collection = collection_to_archive(
|
13
|
-
archivable_item.remote_storage.store(collection,
|
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(
|
20
|
+
def collection_to_archive(archivable_item, tenant_id)
|
21
21
|
repository
|
22
22
|
.items_older_than_for_tenant(
|
23
|
-
|
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(
|
11
|
-
archivable_item = registry.
|
12
|
-
collection = collection_to_archive(
|
13
|
-
archivable_item.remote_storage.store(collection,
|
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(
|
19
|
+
def collection_to_archive(archivable_item)
|
20
20
|
repository
|
21
21
|
.items_older_than(
|
22
|
-
|
22
|
+
archivable_item.model,
|
23
23
|
archivable_item.timestamp_field, archivable_item.archive_items_older_than.call
|
24
24
|
)
|
25
25
|
end
|
data/lib/tartarus/rb/version.rb
CHANGED
data/lib/tartarus/registry.rb
CHANGED
@@ -16,8 +16,8 @@ class Tartarus::Registry
|
|
16
16
|
@storage << item
|
17
17
|
end
|
18
18
|
|
19
|
-
def
|
20
|
-
storage.find(->{ raise "#{
|
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
|
@@ -6,15 +6,15 @@ class Tartarus::ScheduleArchivingModel
|
|
6
6
|
@registry = registry
|
7
7
|
end
|
8
8
|
|
9
|
-
def schedule(
|
10
|
-
archivable_item = registry.
|
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,
|
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,
|
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(
|
8
|
-
Tartarus::ArchiveModelWithTenant.new.archive(
|
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(
|
8
|
-
Tartarus::ArchiveModelWithoutTenant.new.archive(
|
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(
|
8
|
-
Tartarus::ScheduleArchivingModel.new.schedule(
|
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
|
-
|
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
|
+
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:
|
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.
|
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
|