activerecord-prunable 0.3.3 → 0.4.3
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/Gemfile.lock +26 -24
- data/README.md +11 -1
- data/activerecord-prunable.gemspec +1 -1
- data/lib/active_record/prunable.rb +48 -27
- data/lib/activerecord-prunable.rb +25 -7
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8dd903bc39672f786b325d8907bfba3b4ba1d47e
|
4
|
+
data.tar.gz: 6377d77ab1c31b4d8ee4c38cd104c8e091df35a9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 502ae14d858b2b7f0997b70e1a752d165a1e553d511772a3412cbece5ce18b0b2becbc40e0a44238e6955241fa85ca5c19527da7ba12270d355ee5be245d194f
|
7
|
+
data.tar.gz: 5776ff5903da67cbf0b55c2b36f6c5b4c8605e9aa5ba6570e5160541bb2322ea7d2487fb79650a4d0d006e9a36a53d3645efc826f97a0c88e00402a859a1ba70
|
data/Gemfile.lock
CHANGED
@@ -1,45 +1,47 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
activerecord-prunable (0.
|
4
|
+
activerecord-prunable (0.4.2)
|
5
5
|
activerecord (>= 3.0, < 6.0)
|
6
6
|
activesupport (>= 3.0, < 6.0)
|
7
7
|
|
8
8
|
GEM
|
9
9
|
remote: https://rubygems.org/
|
10
10
|
specs:
|
11
|
-
activemodel (4.2.
|
12
|
-
activesupport (= 4.2.
|
11
|
+
activemodel (4.2.7.1)
|
12
|
+
activesupport (= 4.2.7.1)
|
13
13
|
builder (~> 3.1)
|
14
|
-
activerecord (4.2.
|
15
|
-
activemodel (= 4.2.
|
16
|
-
activesupport (= 4.2.
|
14
|
+
activerecord (4.2.7.1)
|
15
|
+
activemodel (= 4.2.7.1)
|
16
|
+
activesupport (= 4.2.7.1)
|
17
17
|
arel (~> 6.0)
|
18
|
-
activesupport (4.2.
|
18
|
+
activesupport (4.2.7.1)
|
19
19
|
i18n (~> 0.7)
|
20
|
+
json (~> 1.7, >= 1.7.7)
|
20
21
|
minitest (~> 5.1)
|
21
22
|
thread_safe (~> 0.3, >= 0.3.4)
|
22
23
|
tzinfo (~> 1.1)
|
23
|
-
arel (6.0.
|
24
|
+
arel (6.0.3)
|
24
25
|
builder (3.2.3)
|
25
|
-
diff-lcs (1.
|
26
|
-
i18n (0.8.
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
rspec-
|
31
|
-
rspec-
|
32
|
-
|
33
|
-
|
34
|
-
|
26
|
+
diff-lcs (1.2.5)
|
27
|
+
i18n (0.8.1)
|
28
|
+
json (1.8.6)
|
29
|
+
minitest (5.10.1)
|
30
|
+
rspec (3.5.0)
|
31
|
+
rspec-core (~> 3.5.0)
|
32
|
+
rspec-expectations (~> 3.5.0)
|
33
|
+
rspec-mocks (~> 3.5.0)
|
34
|
+
rspec-core (3.5.4)
|
35
|
+
rspec-support (~> 3.5.0)
|
36
|
+
rspec-expectations (3.5.0)
|
35
37
|
diff-lcs (>= 1.2.0, < 2.0)
|
36
|
-
rspec-support (~> 3.
|
37
|
-
rspec-mocks (3.
|
38
|
+
rspec-support (~> 3.5.0)
|
39
|
+
rspec-mocks (3.5.0)
|
38
40
|
diff-lcs (>= 1.2.0, < 2.0)
|
39
|
-
rspec-support (~> 3.
|
40
|
-
rspec-support (3.
|
41
|
+
rspec-support (~> 3.5.0)
|
42
|
+
rspec-support (3.5.0)
|
41
43
|
thread_safe (0.3.6)
|
42
|
-
tzinfo (1.2.
|
44
|
+
tzinfo (1.2.2)
|
43
45
|
thread_safe (~> 0.1)
|
44
46
|
|
45
47
|
PLATFORMS
|
@@ -50,4 +52,4 @@ DEPENDENCIES
|
|
50
52
|
rspec (~> 3.0)
|
51
53
|
|
52
54
|
BUNDLED WITH
|
53
|
-
1.
|
55
|
+
1.16.1
|
data/README.md
CHANGED
@@ -34,6 +34,10 @@ __2. Define the `:prunable` scope which returns models to prune.__
|
|
34
34
|
# You can also set type of removing records (:destroy or :delete).
|
35
35
|
# By default it's :destroy
|
36
36
|
prune_method :delete
|
37
|
+
|
38
|
+
# Additional method to set removing in batches.
|
39
|
+
# You're also able to specify batch size with number
|
40
|
+
batch_removal
|
37
41
|
end
|
38
42
|
```
|
39
43
|
|
@@ -43,7 +47,7 @@ __2. Define the `:prunable` scope which returns models to prune.__
|
|
43
47
|
class Notification < ApplicationRecord
|
44
48
|
include ActiveRecord::Prunable
|
45
49
|
|
46
|
-
|
50
|
+
prune_after 7.days
|
47
51
|
end
|
48
52
|
```
|
49
53
|
|
@@ -84,6 +88,12 @@ __Set default method of pruning (:destroy or :delete):__
|
|
84
88
|
Prunable.prune!(prune_method: :delete)
|
85
89
|
```
|
86
90
|
|
91
|
+
__Batch removal:__
|
92
|
+
```ruby
|
93
|
+
Prunable.prune!(in_batches: true)
|
94
|
+
```
|
95
|
+
You're also able to specify the batch size: `Prunable.prune!(batch_size: 100)`
|
96
|
+
|
87
97
|
__Call `:prunable` scope with params:__
|
88
98
|
|
89
99
|
```ruby
|
@@ -21,7 +21,7 @@ module ActiveRecord
|
|
21
21
|
|
22
22
|
module ClassMethods
|
23
23
|
def prune_method(method)
|
24
|
-
unless
|
24
|
+
unless valid_prune_method?(method)
|
25
25
|
logger.info "Incorrect prune method #{method} has been ignored for #{self}"
|
26
26
|
return false
|
27
27
|
end
|
@@ -30,37 +30,41 @@ module ActiveRecord
|
|
30
30
|
class_variable_set(:@@prune_method, method)
|
31
31
|
end
|
32
32
|
|
33
|
-
def prune_after(duration)
|
34
|
-
prune_created_after(duration)
|
35
|
-
end
|
36
|
-
|
37
33
|
def prune_created_after(duration)
|
38
34
|
class_variable_set(:@@prune_created_after, duration)
|
39
35
|
end
|
40
36
|
|
37
|
+
alias prune_after prune_created_after
|
38
|
+
|
41
39
|
def prune_updated_after(duration)
|
42
40
|
class_variable_set(:@@prune_updated_after, duration)
|
43
41
|
end
|
44
42
|
|
45
|
-
def prune!(*params, prune_method: nil, current_time: nil)
|
43
|
+
def prune!(*params, prune_method: nil, current_time: nil, batch_size: nil, in_batches: false)
|
46
44
|
logger.info "Pruning old records of #{self}"
|
47
|
-
return false unless
|
45
|
+
return false unless prunable_model?
|
48
46
|
|
49
47
|
scope = resolve_scope(*params, current_time)
|
50
|
-
|
48
|
+
batch_size ||= class_variable_get(:@@prunable_batch_size) if class_variable_defined?(:@@prunable_batch_size)
|
49
|
+
batch_size ||= 1000 if in_batches
|
50
|
+
destroyed_records = prune(scope, prune_method, batch_size)
|
51
51
|
|
52
|
-
if destroyed_records
|
53
|
-
logger.info "#{destroyed_records} records have been removed."
|
54
|
-
else
|
52
|
+
if destroyed_records.zero?
|
55
53
|
logger.info 'Nothing to prune.'
|
54
|
+
else
|
55
|
+
logger.info "#{destroyed_records} records have been removed."
|
56
56
|
end
|
57
57
|
|
58
58
|
destroyed_records
|
59
59
|
end
|
60
60
|
|
61
|
+
def batch_removal(batch_size = 1000)
|
62
|
+
class_variable_set(:@@prunable_batch_size, batch_size)
|
63
|
+
end
|
64
|
+
|
61
65
|
private
|
62
66
|
|
63
|
-
def
|
67
|
+
def prunable_model?
|
64
68
|
pruning_means_count = [
|
65
69
|
respond_to?(:prunable),
|
66
70
|
class_variable_defined?(:@@prune_created_after),
|
@@ -83,33 +87,50 @@ module ActiveRecord
|
|
83
87
|
def resolve_scope(*params, current_time)
|
84
88
|
current_time ||= Time.current
|
85
89
|
|
86
|
-
|
87
|
-
when respond_to?(:prunable)
|
90
|
+
if respond_to?(:prunable)
|
88
91
|
prunable(*params)
|
89
|
-
|
92
|
+
elsif class_variable_defined?(:@@prune_created_after)
|
90
93
|
where('created_at < ?', current_time - class_variable_get(:@@prune_created_after))
|
91
|
-
|
94
|
+
elsif class_variable_defined?(:@@prune_updated_after)
|
92
95
|
where('updated_at < ?', current_time - class_variable_get(:@@prune_updated_after))
|
93
96
|
end
|
94
97
|
end
|
95
98
|
|
96
|
-
def
|
99
|
+
def valid_prune_method?(method)
|
97
100
|
%i[destroy delete].include?(method)
|
98
101
|
end
|
99
102
|
|
100
|
-
def
|
101
|
-
prune_method =
|
102
|
-
|
103
|
-
else
|
104
|
-
prune_method || :destroy
|
105
|
-
end
|
106
|
-
|
107
|
-
return false unless check_prune_method(prune_method)
|
103
|
+
def prune(scope, prune_method, batch_size)
|
104
|
+
prune_method = resolve_prune_method(prune_method)
|
105
|
+
return false unless valid_prune_method?(prune_method)
|
108
106
|
|
109
107
|
logger.info "Prune method is #{prune_method}"
|
110
108
|
|
111
|
-
|
112
|
-
scope
|
109
|
+
pruner = pruner_for(prune_method)
|
110
|
+
return pruner.call(scope) unless batch_size
|
111
|
+
|
112
|
+
logger.info "Removing in batches, batch_size: #{batch_size}"
|
113
|
+
|
114
|
+
batch_results = scope.find_in_batches(batch_size: batch_size) do |batch|
|
115
|
+
batch_ids = batch.map(&:id)
|
116
|
+
relation = scope.model.where(id: batch_ids)
|
117
|
+
pruner.call(relation)
|
118
|
+
end
|
119
|
+
|
120
|
+
batch_results.present? ? batch_results.sum : 0
|
121
|
+
end
|
122
|
+
|
123
|
+
def resolve_prune_method(prune_method)
|
124
|
+
return class_variable_get(:@@prune_method) if class_variable_defined?(:@@prune_method)
|
125
|
+
prune_method || :destroy
|
126
|
+
end
|
127
|
+
|
128
|
+
def pruner_for(prune_method)
|
129
|
+
if prune_method == :delete
|
130
|
+
:delete_all.to_proc
|
131
|
+
else
|
132
|
+
->(scope) { scope.destroy_all.size }
|
133
|
+
end
|
113
134
|
end
|
114
135
|
end
|
115
136
|
end
|
@@ -11,29 +11,47 @@ module Prunable
|
|
11
11
|
ActiveRecord::Prunable.includes
|
12
12
|
end
|
13
13
|
|
14
|
-
def prune!(*
|
15
|
-
models =
|
14
|
+
def prune!(*args)
|
15
|
+
models, params = resolve_args(args)
|
16
16
|
|
17
17
|
models.each_with_object({}) do |model, pruned|
|
18
|
-
pruned[model.table_name] =
|
18
|
+
pruned[model.table_name] = prune_model!(model, params)
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
22
|
-
def prune(*
|
23
|
-
models =
|
22
|
+
def prune(*args)
|
23
|
+
models, params = resolve_args(args)
|
24
24
|
|
25
25
|
pruned = {}
|
26
26
|
errors = []
|
27
27
|
|
28
28
|
models.each do |model|
|
29
29
|
begin
|
30
|
-
pruned[model.table_name] =
|
31
|
-
rescue => e
|
30
|
+
pruned[model.table_name] = prune_model!(model, params)
|
31
|
+
rescue StandardError => e
|
32
32
|
errors << e
|
33
33
|
end
|
34
34
|
end
|
35
35
|
|
36
36
|
[pruned, errors]
|
37
37
|
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def resolve_args(args)
|
42
|
+
params = args.last.is_a?(Hash) ? args.pop : {}
|
43
|
+
models = args.any? ? args : self.models
|
44
|
+
[models, params]
|
45
|
+
end
|
46
|
+
|
47
|
+
def prune_model!(model, prune_method: nil, current_time: nil, params: [], batch_size: nil, in_batches: false)
|
48
|
+
model.prune!(
|
49
|
+
*params,
|
50
|
+
prune_method: prune_method,
|
51
|
+
current_time: current_time,
|
52
|
+
batch_size: batch_size,
|
53
|
+
in_batches: in_batches
|
54
|
+
)
|
55
|
+
end
|
38
56
|
end
|
39
57
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: activerecord-prunable
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- dr2m
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2018-02-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|