logidze 0.8.1 → 1.0.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +124 -5
- data/LICENSE.txt +1 -1
- data/README.md +310 -80
- data/lib/generators/logidze/fx_helper.rb +17 -0
- data/lib/generators/logidze/inject_sql.rb +18 -0
- data/lib/generators/logidze/install/USAGE +6 -1
- data/lib/generators/logidze/install/functions/logidze_compact_history.sql +38 -0
- data/lib/generators/logidze/install/functions/logidze_filter_keys.sql +27 -0
- data/lib/generators/logidze/install/functions/logidze_logger.sql +150 -0
- data/lib/generators/logidze/install/functions/logidze_snapshot.sql +24 -0
- data/lib/generators/logidze/install/functions/logidze_version.sql +20 -0
- data/lib/generators/logidze/install/install_generator.rb +61 -3
- data/lib/generators/logidze/install/templates/hstore.rb.erb +1 -1
- data/lib/generators/logidze/install/templates/migration.rb.erb +19 -232
- data/lib/generators/logidze/install/templates/migration_fx.rb.erb +41 -0
- data/lib/generators/logidze/model/model_generator.rb +56 -20
- data/lib/generators/logidze/model/templates/migration.rb.erb +57 -36
- data/lib/generators/logidze/model/triggers/logidze.sql +6 -0
- data/lib/logidze.rb +43 -20
- data/lib/logidze/engine.rb +4 -1
- data/lib/logidze/has_logidze.rb +12 -3
- data/lib/logidze/history.rb +7 -15
- data/lib/logidze/history/type.rb +1 -1
- data/lib/logidze/history/version.rb +6 -5
- data/lib/logidze/ignore_log_data.rb +22 -0
- data/lib/logidze/ignore_log_data/cast_attribute_patch.rb +17 -0
- data/lib/logidze/meta.rb +44 -17
- data/lib/logidze/model.rb +65 -37
- data/lib/logidze/version.rb +2 -1
- data/lib/logidze/versioned_association.rb +0 -1
- metadata +47 -103
- data/.gitignore +0 -40
- data/.hound.yml +0 -3
- data/.rubocop.yml +0 -94
- data/.travis.yml +0 -39
- data/Gemfile +0 -13
- data/Rakefile +0 -28
- data/bench/performance/README.md +0 -109
- data/bench/performance/diff_bench.rb +0 -36
- data/bench/performance/insert_bench.rb +0 -20
- data/bench/performance/memory_profile.rb +0 -53
- data/bench/performance/setup.rb +0 -308
- data/bench/performance/update_bench.rb +0 -36
- data/bench/triggers/Makefile +0 -56
- data/bench/triggers/Readme.md +0 -58
- data/bench/triggers/bench.sql +0 -6
- data/bench/triggers/hstore_trigger_setup.sql +0 -38
- data/bench/triggers/jsonb_minus_2_setup.sql +0 -47
- data/bench/triggers/jsonb_minus_setup.sql +0 -49
- data/bench/triggers/keys2_trigger_setup.sql +0 -44
- data/bench/triggers/keys_trigger_setup.sql +0 -50
- data/bin/console +0 -8
- data/bin/setup +0 -9
- data/gemfiles/rails42.gemfile +0 -5
- data/gemfiles/rails5.gemfile +0 -6
- data/gemfiles/rails52.gemfile +0 -6
- data/gemfiles/railsmaster.gemfile +0 -7
- data/lib/logidze/migration.rb +0 -19
- data/logidze.gemspec +0 -33
data/.gitignore
DELETED
@@ -1,40 +0,0 @@
|
|
1
|
-
# Numerous always-ignore extensions
|
2
|
-
*.diff
|
3
|
-
*.err
|
4
|
-
*.orig
|
5
|
-
*.log
|
6
|
-
*.rej
|
7
|
-
*.swo
|
8
|
-
*.swp
|
9
|
-
*.vi
|
10
|
-
*~
|
11
|
-
*.sass-cache
|
12
|
-
*.iml
|
13
|
-
.idea/
|
14
|
-
|
15
|
-
# Sublime
|
16
|
-
*.sublime-project
|
17
|
-
*.sublime-workspace
|
18
|
-
|
19
|
-
# OS or Editor folders
|
20
|
-
.DS_Store
|
21
|
-
.cache
|
22
|
-
.project
|
23
|
-
.settings
|
24
|
-
.tmproj
|
25
|
-
Thumbs.db
|
26
|
-
|
27
|
-
.bundle/
|
28
|
-
log/*.log
|
29
|
-
*.gz
|
30
|
-
pkg/
|
31
|
-
spec/dummy/db/*.sqlite3
|
32
|
-
spec/dummy/db/*.sqlite3-journal
|
33
|
-
spec/dummy/tmp/
|
34
|
-
|
35
|
-
Gemfile.lock
|
36
|
-
Gemfile.local
|
37
|
-
.rspec
|
38
|
-
*.gem
|
39
|
-
tmp/
|
40
|
-
coverage/
|
data/.hound.yml
DELETED
data/.rubocop.yml
DELETED
@@ -1,94 +0,0 @@
|
|
1
|
-
require:
|
2
|
-
- rubocop-md
|
3
|
-
|
4
|
-
AllCops:
|
5
|
-
# Include gemspec and Rakefile
|
6
|
-
Include:
|
7
|
-
- 'lib/**/*.rb'
|
8
|
-
- 'lib/**/*.rake'
|
9
|
-
- 'spec/**/*.rb'
|
10
|
-
Exclude:
|
11
|
-
- 'bin/**/*'
|
12
|
-
- 'spec/dummy/**/*'
|
13
|
-
- 'vendor/**/*'
|
14
|
-
- 'gemfiles/**/*'
|
15
|
-
- 'tmp/**/*'
|
16
|
-
- 'bench/**/*'
|
17
|
-
- 'Rakefile'
|
18
|
-
- 'Gemfile'
|
19
|
-
- '*.gemspec'
|
20
|
-
DisplayCopNames: true
|
21
|
-
StyleGuideCopsOnly: false
|
22
|
-
TargetRubyVersion: 2.3
|
23
|
-
|
24
|
-
Naming/AccessorMethodName:
|
25
|
-
Enabled: false
|
26
|
-
|
27
|
-
Naming/UncommunicativeMethodParamName:
|
28
|
-
Enabled: false
|
29
|
-
|
30
|
-
Style/TrivialAccessors:
|
31
|
-
Enabled: false
|
32
|
-
|
33
|
-
Style/Documentation:
|
34
|
-
Exclude:
|
35
|
-
- 'spec/**/*.rb'
|
36
|
-
|
37
|
-
Style/StringLiterals:
|
38
|
-
Enabled: false
|
39
|
-
|
40
|
-
Layout/SpaceInsideStringInterpolation:
|
41
|
-
EnforcedStyle: no_space
|
42
|
-
|
43
|
-
Style/BlockDelimiters:
|
44
|
-
Exclude:
|
45
|
-
- 'spec/**/*.rb'
|
46
|
-
|
47
|
-
Style/PercentLiteralDelimiters:
|
48
|
-
Enabled: false
|
49
|
-
|
50
|
-
Lint/AmbiguousRegexpLiteral:
|
51
|
-
Enabled: false
|
52
|
-
|
53
|
-
Lint/MissingCopEnableDirective:
|
54
|
-
Enabled: false
|
55
|
-
|
56
|
-
Lint/UselessAssignment:
|
57
|
-
Exclude:
|
58
|
-
- '**/*.md'
|
59
|
-
|
60
|
-
Metrics/MethodLength:
|
61
|
-
Exclude:
|
62
|
-
- 'spec/**/*.rb'
|
63
|
-
|
64
|
-
Metrics/BlockLength:
|
65
|
-
Exclude:
|
66
|
-
- 'spec/**/*.rb'
|
67
|
-
|
68
|
-
Metrics/LineLength:
|
69
|
-
Max: 100
|
70
|
-
Exclude:
|
71
|
-
- 'spec/**/*.rb'
|
72
|
-
|
73
|
-
Rails/Date:
|
74
|
-
Enabled: false
|
75
|
-
|
76
|
-
Rails/TimeZone:
|
77
|
-
Enabled: false
|
78
|
-
|
79
|
-
Style/NumericLiteralPrefix:
|
80
|
-
Enabled: false
|
81
|
-
|
82
|
-
Lint/HandleExceptions:
|
83
|
-
Enabled: true
|
84
|
-
Exclude:
|
85
|
-
- 'spec/**/*.rb'
|
86
|
-
|
87
|
-
Layout/DotPosition:
|
88
|
-
EnforcedStyle: leading
|
89
|
-
|
90
|
-
Layout/IndentHeredoc:
|
91
|
-
Enabled: false
|
92
|
-
|
93
|
-
Layout/EmptyLineAfterMagicComment:
|
94
|
-
Enabled: false
|
data/.travis.yml
DELETED
@@ -1,39 +0,0 @@
|
|
1
|
-
language: ruby
|
2
|
-
cache: bundler
|
3
|
-
|
4
|
-
dist: trusty
|
5
|
-
sudo: false
|
6
|
-
|
7
|
-
addons:
|
8
|
-
postgresql: "9.6"
|
9
|
-
|
10
|
-
env:
|
11
|
-
global:
|
12
|
-
- LOGIDZE_DB_USER=postgres
|
13
|
-
- LOGIDZE_DB_NAME=logidze
|
14
|
-
|
15
|
-
before_script:
|
16
|
-
- gem update --system
|
17
|
-
- bundle exec rake dummy:db:create
|
18
|
-
- psql -U postgres -d logidze -c 'CREATE EXTENSION IF NOT EXISTS hstore;'
|
19
|
-
- bundle exec rake dummy:db:test:prepare
|
20
|
-
|
21
|
-
matrix:
|
22
|
-
include:
|
23
|
-
- rvm: ruby-head
|
24
|
-
gemfile: gemfiles/railsmaster.gemfile
|
25
|
-
- rvm: 2.5.0
|
26
|
-
gemfile: gemfiles/railsmaster.gemfile
|
27
|
-
- rvm: 2.5.0
|
28
|
-
gemfile: gemfiles/rails5.gemfile
|
29
|
-
- rvm: 2.5.1
|
30
|
-
gemfile: gemfiles/rails52.gemfile
|
31
|
-
- rvm: 2.4.1
|
32
|
-
gemfile: gemfiles/rails5.gemfile
|
33
|
-
- rvm: 2.3.1
|
34
|
-
gemfile: gemfiles/rails42.gemfile
|
35
|
-
allow_failures:
|
36
|
-
- rvm: ruby-head
|
37
|
-
gemfile: gemfiles/railsmaster.gemfile
|
38
|
-
- rvm: 2.5.0
|
39
|
-
gemfile: gemfiles/railsmaster.gemfile
|
data/Gemfile
DELETED
@@ -1,13 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
source 'https://rubygems.org'
|
3
|
-
|
4
|
-
# Specify your gem's dependencies in logidze.gemspec
|
5
|
-
gemspec
|
6
|
-
|
7
|
-
local_gemfile = "#{File.dirname(__FILE__)}/Gemfile.local"
|
8
|
-
|
9
|
-
if File.exist?(local_gemfile)
|
10
|
-
eval(File.read(local_gemfile)) # rubocop:disable Lint/Eval
|
11
|
-
else
|
12
|
-
gem 'activerecord', '~> 5.1.1'
|
13
|
-
end
|
data/Rakefile
DELETED
@@ -1,28 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
require "bundler/gem_tasks"
|
3
|
-
require "rspec/core/rake_task"
|
4
|
-
require "rubocop/rake_task"
|
5
|
-
|
6
|
-
RuboCop::RakeTask.new
|
7
|
-
RSpec::Core::RakeTask.new(:spec)
|
8
|
-
|
9
|
-
namespace :dummy do
|
10
|
-
require_relative "spec/dummy/config/application"
|
11
|
-
Dummy::Application.load_tasks
|
12
|
-
end
|
13
|
-
|
14
|
-
task(:spec).clear
|
15
|
-
desc "Run specs other than spec/acceptance"
|
16
|
-
RSpec::Core::RakeTask.new("spec") do |task|
|
17
|
-
task.exclude_pattern = "spec/acceptance/**/*_spec.rb"
|
18
|
-
task.verbose = false
|
19
|
-
end
|
20
|
-
|
21
|
-
desc "Run acceptance specs in spec/acceptance"
|
22
|
-
RSpec::Core::RakeTask.new("spec:acceptance") do |task|
|
23
|
-
task.pattern = "spec/acceptance/**/*_spec.rb"
|
24
|
-
task.verbose = false
|
25
|
-
end
|
26
|
-
|
27
|
-
desc "Run the specs and acceptance tests"
|
28
|
-
task default: %w(rubocop spec spec:acceptance)
|
data/bench/performance/README.md
DELETED
@@ -1,109 +0,0 @@
|
|
1
|
-
# Performance benchmarks: PaperTail vs. Logidze
|
2
|
-
|
3
|
-
We want to compare Logidze with the most popular versioning library for Rails – PaperTrail.
|
4
|
-
|
5
|
-
|
6
|
-
## Insert ([source](insert_bench.rb))
|
7
|
-
|
8
|
-
```
|
9
|
-
PaperTrail INSERT 213.148 (± 8.9%) i/s - 1.060k in 5.018504s
|
10
|
-
Logidze INSERT 613.387 (±16.3%) i/s - 2.970k in 5.036127s
|
11
|
-
```
|
12
|
-
|
13
|
-
|
14
|
-
## Update ([source](update_bench.rb))
|
15
|
-
|
16
|
-
When changeset has 2 fields:
|
17
|
-
|
18
|
-
```
|
19
|
-
PaperTrail UPDATE #1 256.651 (±26.5%) i/s - 1.206k in 5.002300s
|
20
|
-
Logidze UPDATE #1 356.932 (±12.6%) i/s - 1.764k in 5.030560s
|
21
|
-
```
|
22
|
-
|
23
|
-
When changeset has 5 fields:
|
24
|
-
|
25
|
-
```
|
26
|
-
PaperTrail UPDATE #2 246.281 (±24.0%) i/s - 1.168k in 5.008234s
|
27
|
-
Logidze UPDATE #2 331.942 (±16.6%) i/s - 1.593k in 5.028135s
|
28
|
-
```
|
29
|
-
|
30
|
-
## Getting diff ([source](diff_bench.rb))
|
31
|
-
|
32
|
-
PaperTrail doesn't have built-in method to calculate diff between not adjacent versions.
|
33
|
-
We add `diff_from(ts)` and `diff_from_joined(ts)` (which uses SQL JOIN) methods to calculate diff from specified version using changesets.
|
34
|
-
|
35
|
-
When each record has 10 versions:
|
36
|
-
|
37
|
-
```
|
38
|
-
PT DIFF 20.874 (± 4.8%) i/s - 106.000 in 5.091402s
|
39
|
-
PT (join) DIFF 20.619 (± 4.8%) i/s - 104.000 in 5.070160s
|
40
|
-
Logidze DIFF 109.482 (±24.7%) i/s - 500.000 in 5.103534s
|
41
|
-
```
|
42
|
-
|
43
|
-
When each record has 100 versions:
|
44
|
-
|
45
|
-
```
|
46
|
-
PT DIFF 2.998 (± 0.0%) i/s - 15.000 in 5.019494s
|
47
|
-
PT (join) DIFF 3.193 (± 0.0%) i/s - 16.000 in 5.030155s
|
48
|
-
Logidze DIFF 19.627 (±25.5%) i/s - 88.000 in 5.035555s
|
49
|
-
```
|
50
|
-
|
51
|
-
And, finally, when each record has 1000 versions:
|
52
|
-
|
53
|
-
```
|
54
|
-
PT DIFF 0.270 (± 0.0%) i/s - 17.000 in 63.038374s
|
55
|
-
PT (join) DIFF 0.235 (± 0.0%) i/s - 14.000 in 60.350886s
|
56
|
-
Logidze DIFF 2.022 (± 0.0%) i/s - 120.000 in 60.142965s
|
57
|
-
```
|
58
|
-
|
59
|
-
## Select memory usage ([source](memory_profile.rb))
|
60
|
-
|
61
|
-
Logidze loads more data (because it stores log in-place). But how much more?
|
62
|
-
We consider two cases for PaperTrail: when we want to calculate diff (and thus loading versions) and when we don't need any history related data.
|
63
|
-
|
64
|
-
When each record has 10 versions:
|
65
|
-
|
66
|
-
```
|
67
|
-
PT records
|
68
|
-
Total Allocated: 27.8 KB
|
69
|
-
Total Retained: 16.59 KB
|
70
|
-
Retained memory (per record): 2.14 KB
|
71
|
-
|
72
|
-
PT with versions
|
73
|
-
Total Allocated: 228.01 KB
|
74
|
-
Total Retained: 170.78 KB
|
75
|
-
Retained memory (per record): 143.13 KB
|
76
|
-
|
77
|
-
Logidze records
|
78
|
-
Total Allocated: 46.45 KB
|
79
|
-
Total Retained: 34.73 KB
|
80
|
-
Retained memory (per record): 4.11 KB
|
81
|
-
```
|
82
|
-
|
83
|
-
When each record has 100 versions:
|
84
|
-
|
85
|
-
```
|
86
|
-
PT with versions
|
87
|
-
Total Allocated: 1.92 MB
|
88
|
-
Total Retained: 1.56 MB
|
89
|
-
Retained memory (per record): 1.53 MB
|
90
|
-
|
91
|
-
Logidze records
|
92
|
-
Total Allocated: 162.48 KB
|
93
|
-
Total Retained: 150.76 KB
|
94
|
-
Retained memory (per record): 15.4 KB
|
95
|
-
```
|
96
|
-
|
97
|
-
When each record has 1000 versions:
|
98
|
-
|
99
|
-
```
|
100
|
-
PT with versions
|
101
|
-
Total Allocated: 18.23 MB
|
102
|
-
Total Retained: 14.86 MB
|
103
|
-
Retained memory (per record): 14.83 MB
|
104
|
-
|
105
|
-
Logidze records
|
106
|
-
Total Allocated: 1.32 MB
|
107
|
-
Total Retained: 1.31 MB
|
108
|
-
Retained memory (per record): 131.59 KB
|
109
|
-
```
|
@@ -1,36 +0,0 @@
|
|
1
|
-
require 'benchmark/ips'
|
2
|
-
require './setup'
|
3
|
-
|
4
|
-
# How many records do you want?
|
5
|
-
N = (ENV['N'] || '100').to_i
|
6
|
-
|
7
|
-
# How many version each record has?
|
8
|
-
V = (ENV['V'] || '10').to_i
|
9
|
-
|
10
|
-
# Benchmark run time
|
11
|
-
BM_TIME = (ENV['BM_TIME'] || 5).to_i
|
12
|
-
|
13
|
-
BM_WARMUP = [(BM_TIME / 10), 2].max
|
14
|
-
|
15
|
-
LogidzeBench.cleanup
|
16
|
-
LogidzeBench.populate(N)
|
17
|
-
|
18
|
-
ts1 = LogidzeBench.generate_versions(V/2)
|
19
|
-
|
20
|
-
LogidzeBench.generate_versions(V/2)
|
21
|
-
|
22
|
-
Benchmark.ips do |x|
|
23
|
-
x.config(time: BM_TIME, warmup: BM_WARMUP)
|
24
|
-
|
25
|
-
x.report('PT DIFF') do
|
26
|
-
User.random(N/2).diff_from(ts1)
|
27
|
-
end
|
28
|
-
|
29
|
-
x.report('PT (join) DIFF') do
|
30
|
-
User.random(N/2).diff_from_joined(ts1)
|
31
|
-
end
|
32
|
-
|
33
|
-
x.report('Logidze DIFF') do
|
34
|
-
LogidzeUser.random(N/2).diff_from(ts1)
|
35
|
-
end
|
36
|
-
end
|
@@ -1,20 +0,0 @@
|
|
1
|
-
require 'benchmark/ips'
|
2
|
-
require './setup'
|
3
|
-
|
4
|
-
params = {
|
5
|
-
email: Faker::Internet.email,
|
6
|
-
position: Faker::Number.number(3),
|
7
|
-
name: Faker::Name.name,
|
8
|
-
age: Faker::Number.number(2),
|
9
|
-
bio: Faker::Lorem.paragraph
|
10
|
-
}
|
11
|
-
|
12
|
-
Benchmark.ips do |x|
|
13
|
-
x.report('PaperTrail INSERT') do
|
14
|
-
User.create!(params)
|
15
|
-
end
|
16
|
-
|
17
|
-
x.report('Logidze INSERT') do
|
18
|
-
LogidzeUser.create!(params)
|
19
|
-
end
|
20
|
-
end
|
@@ -1,53 +0,0 @@
|
|
1
|
-
require './setup'
|
2
|
-
require 'active_support/core_ext'
|
3
|
-
require 'memory_profiler'
|
4
|
-
|
5
|
-
# How many records do you want?
|
6
|
-
N = (ENV['N'] || '10').to_i
|
7
|
-
|
8
|
-
# How many version each record has?
|
9
|
-
V = (ENV['V'] || '10').to_i
|
10
|
-
|
11
|
-
LogidzeBench.cleanup
|
12
|
-
LogidzeBench.populate(N)
|
13
|
-
LogidzeBench.generate_versions(V)
|
14
|
-
|
15
|
-
module MemoryReport
|
16
|
-
KILO_BYTE = 1024
|
17
|
-
MEGA_BYTE = 1024 * 1024
|
18
|
-
|
19
|
-
module_function
|
20
|
-
def call(msg, relation)
|
21
|
-
buffer = nil
|
22
|
-
delta = N / 10
|
23
|
-
r0 = MemoryProfiler.report do
|
24
|
-
buffer = relation.random(N - delta).to_a
|
25
|
-
end
|
26
|
-
|
27
|
-
buffer = nil
|
28
|
-
r1 = MemoryProfiler.report do
|
29
|
-
buffer = relation.to_a
|
30
|
-
end
|
31
|
-
|
32
|
-
$stdout.puts msg
|
33
|
-
$stdout.puts "Total Allocated:\t\t\t\t#{to_human_size(r1.total_allocated_memsize)}"
|
34
|
-
$stdout.puts "Total Retained:\t\t\t\t\t#{to_human_size(r1.total_retained_memsize)}"
|
35
|
-
$stdout.puts "Retained_memsize memory (per record):\t\t#{to_human_size((r1.total_retained_memsize - r0.total_retained_memsize) / delta)}"
|
36
|
-
end
|
37
|
-
|
38
|
-
module_function
|
39
|
-
def to_human_size(size)
|
40
|
-
if size > MEGA_BYTE
|
41
|
-
"#{(size.to_f / MEGA_BYTE).round(2)} MB"
|
42
|
-
elsif size > KILO_BYTE
|
43
|
-
"#{(size.to_f / KILO_BYTE).round(2)} KB"
|
44
|
-
else
|
45
|
-
"#{size} B"
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
|
51
|
-
MemoryReport.("PT records", User.all)
|
52
|
-
MemoryReport.("PT with versions", User.joins(:versions).all)
|
53
|
-
MemoryReport.("Logidze records", LogidzeUser.all)
|