relaton 1.7.9 → 1.8.pre2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/rake.yml +1 -1
  3. data/.rubocop.yml +1 -1
  4. data/lib/relaton.rb +3 -0
  5. data/lib/relaton/config.rb +4 -2
  6. data/lib/relaton/db.rb +106 -52
  7. data/lib/relaton/db_cache.rb +38 -125
  8. data/lib/relaton/registry.rb +1 -0
  9. data/lib/relaton/storage.rb +186 -0
  10. data/lib/relaton/version.rb +1 -1
  11. data/relaton.gemspec +23 -19
  12. data/spec/relaton/db_cache_spec.rb +2 -2
  13. data/spec/relaton/db_spec.rb +17 -0
  14. data/spec/relaton/regirtry_spec.rb +9 -1
  15. data/spec/relaton/storage_spec.rb +130 -0
  16. data/spec/relaton_spec.rb +48 -7
  17. data/spec/spec_helper.rb +4 -0
  18. data/spec/vcr_cassetes/19133_2005.yml +17 -17
  19. data/spec/vcr_cassetes/api_relaton_org.yml +33 -0
  20. data/spec/vcr_cassetes/api_relaton_org_unavailable.yml +182 -0
  21. data/spec/vcr_cassetes/async_fetch.yml +2037 -1606
  22. data/spec/vcr_cassetes/bsi_bs_en_iso_8848.yml +17 -17
  23. data/spec/vcr_cassetes/cc_dir_10005_2019.yml +10 -10
  24. data/spec/vcr_cassetes/cen_en_10160_1999.yml +249 -0
  25. data/spec/vcr_cassetes/cie_001_1980.yml +7 -7
  26. data/spec/vcr_cassetes/ecma_6.yml +7 -7
  27. data/spec/vcr_cassetes/fisp_140.yml +4 -4
  28. data/spec/vcr_cassetes/gb_t_20223_2006.yml +9 -9
  29. data/spec/vcr_cassetes/iec_60050_102_2007.yml +23 -23
  30. data/spec/vcr_cassetes/iec_combined_included.yml +81 -79
  31. data/spec/vcr_cassetes/ieee_528_2019.yml +38 -38
  32. data/spec/vcr_cassetes/iho_b_11.yml +7 -7
  33. data/spec/vcr_cassetes/iso_111111119115_1.yml +3 -3
  34. data/spec/vcr_cassetes/iso_19115.yml +19 -19
  35. data/spec/vcr_cassetes/iso_19115_1.yml +18 -18
  36. data/spec/vcr_cassetes/iso_19115_1_2.yml +35 -35
  37. data/spec/vcr_cassetes/iso_awi_14093.yml +182 -0
  38. data/spec/vcr_cassetes/iso_combined_applied.yml +38 -38
  39. data/spec/vcr_cassetes/iso_combined_included.yml +34 -34
  40. data/spec/vcr_cassetes/itu_combined_included.yml +456 -459
  41. data/spec/vcr_cassetes/ogc_19_025r1.yml +1222 -1163
  42. data/spec/vcr_cassetes/omg_ami4ccm_1_0.yml +43 -0
  43. data/spec/vcr_cassetes/rfc_8341.yml +7 -7
  44. data/spec/vcr_cassetes/sp_800_38b.yml +4 -4
  45. data/spec/vcr_cassetes/un_rtade_cefact_2004_32.yml +29 -29
  46. data/spec/vcr_cassetes/w3c_json_ld11.yml +17 -17
  47. metadata +107 -46
  48. data/spec/vcr_cassetes/iso_awi_24229.yml +0 -182
  49. data/spec/vcr_cassetes/ogm_ami4ccm_1_0.yml +0 -43
@@ -9,6 +9,7 @@ module Relaton
9
9
  relaton_gb relaton_iec relaton_ietf relaton_iso relaton_itu relaton_nist
10
10
  relaton_ogc relaton_calconnect relaton_omg relaton_un relaton_w3c
11
11
  relaton_ieee relaton_iho relaton_bipm relaton_ecma relaton_cie relaton_bsi
12
+ relaton_cen
12
13
  ].freeze
13
14
 
14
15
  include Singleton
@@ -0,0 +1,186 @@
1
+ require "aws-sdk-s3"
2
+
3
+ module Relaton
4
+ #
5
+ # Man
6
+ #
7
+ class Storage
8
+ include Singleton
9
+
10
+ def initialize
11
+ if Relaton.configuration.api_mode
12
+ @s3 = Aws::S3::Client.new
13
+ end
14
+ end
15
+
16
+ #
17
+ # Save file to storage
18
+ #
19
+ # @param dir [String]
20
+ # @param key [String]
21
+ # @param value [String]
22
+ #
23
+ def save(dir, key, value)
24
+ set_version dir
25
+ if Relaton.configuration.api_mode then s3_write key, value
26
+ else file_safe_write key, value
27
+ end
28
+ end
29
+
30
+ #
31
+ # Returns all items
32
+ #
33
+ # @param dir [String]
34
+ #
35
+ # @return [Array<String>]
36
+ #
37
+ def all(dir, &block)
38
+ return all_s3 dir, &block if Relaton.configuration.api_mode
39
+
40
+ Dir.glob("#{dir}/**/*.{xml,yml,yaml}").sort.map do |f|
41
+ content = File.read(f, encoding: "utf-8")
42
+ block ? yield(f, content) : content
43
+ end
44
+ end
45
+
46
+ # Delete item
47
+ # @param key [String] path to file without extension
48
+ def delete(key)
49
+ f = search_ext(key)
50
+ if Relaton.configuration.api_mode && f
51
+ @s3.delete_object bucket: ENV["AWS_BUCKET"], key: f
52
+ elsif f then File.delete f
53
+ end
54
+ end
55
+
56
+ # Check if version of the DB match to the gem grammar hash.
57
+ # @param fdir [String] dir pathe to flavor cache
58
+ # @return [Boolean]
59
+ def check_version?(fdir)
60
+ file_version = "#{fdir}/version"
61
+ if Relaton.configuration.api_mode
62
+ check_version_s3? file_version, fdir
63
+ else
64
+ return false unless File.exist? fdir
65
+
66
+ v = File.read file_version, encoding: "utf-8"
67
+ v.strip == grammar_hash(fdir)
68
+ end
69
+ end
70
+
71
+ # Reads file by a key
72
+ #
73
+ # @param key [String]
74
+ # @return [String, NilClass]
75
+ def get(key, static: false)
76
+ return unless (f = search_ext(key, static: static))
77
+
78
+ if Relaton.configuration.api_mode && !static
79
+ s3_read f
80
+ else
81
+ File.read(f, encoding: "utf-8")
82
+ end
83
+ end
84
+
85
+ private
86
+
87
+ # Check if version of the DB match to the gem grammar hash.
88
+ # @param file_version [String] dir pathe to flover cache
89
+ # @param dir [String] fdir pathe to flavor cache
90
+ # @return [Boolean]
91
+ def check_version_s3?(file_version, fdir)
92
+ s3_read(file_version) == grammar_hash(fdir)
93
+ rescue Aws::S3::Errors::NoSuchKey
94
+ false
95
+ end
96
+
97
+ #
98
+ # Read file form AWS S#
99
+ #
100
+ # @param [String] key file name
101
+ #
102
+ # @return [String] content
103
+ #
104
+ def s3_read(key)
105
+ obj = @s3.get_object bucket: ENV["AWS_BUCKET"], key: key
106
+ obj.body.read
107
+ end
108
+
109
+ #
110
+ # Write file to AWS S3
111
+ #
112
+ # @param [String] key
113
+ # @param [String] value
114
+ #
115
+ def s3_write(key, value)
116
+ @s3.put_object(bucket: ENV["AWS_BUCKET"], key: key, body: value,
117
+ content_type: "text/plain; charset=utf-8")
118
+ end
119
+
120
+ #
121
+ # Returns all items
122
+ #
123
+ # @param dir [String]
124
+ #
125
+ # @return [Array<String>]
126
+ #
127
+ def all_s3(dir)
128
+ list = @s3.list_objects_v2 bucket: ENV["AWS_BUCKET"], prefix: dir
129
+ list.contents.select { |i| i.key.match?(/\.xml$/) }.sort_by(&:key).map do |item|
130
+ content = s3_read item.key
131
+ block_given? ? yield(item.key, content) : content
132
+ end
133
+ end
134
+
135
+ #
136
+ # Checks if there is file with xml or txt extension and return filename with
137
+ # the extension.
138
+ #
139
+ # @param file [String]
140
+ # @return [String, NilClass]
141
+ def search_ext(file, static: false)
142
+ if Relaton.configuration.api_mode && !static
143
+ fs = @s3.list_objects_v2 bucket: ENV["AWS_BUCKET"], prefix: "#{file}."
144
+ fs.contents.first&.key
145
+ else
146
+ Dir["#{file}.*"].first
147
+ end
148
+ end
149
+
150
+ # Set version of the DB to the gem grammar hash.
151
+ # @param fdir [String] dir pathe to flover cache
152
+ def set_version(fdir)
153
+ file_version = "#{fdir}/version"
154
+ return set_version_s3 file_version, fdir if Relaton.configuration.api_mode
155
+
156
+ FileUtils::mkdir_p fdir unless Dir.exist?(fdir)
157
+ unless File.exist? file_version
158
+ file_safe_write file_version, grammar_hash(fdir)
159
+ end
160
+ end
161
+
162
+ # Set version of the DB to the gem grammar hash.
163
+ # @param fdir [String] dir pathe to flover cache
164
+ def set_version_s3(fver, dir)
165
+ @s3.head_object bucket: ENV["AWS_BUCKET"], key: fver
166
+ rescue Aws::S3::Errors::NotFound
167
+ s3_write fver, grammar_hash(dir)
168
+ end
169
+
170
+ # @param file [String]
171
+ # @content [String]
172
+ def file_safe_write(file, content)
173
+ File.open file, File::RDWR | File::CREAT, encoding: "UTF-8" do |f|
174
+ Timeout.timeout(10) { f.flock File::LOCK_EX }
175
+ f.write content
176
+ end
177
+ end
178
+
179
+ # @param fdir [String] dir pathe to flover cache
180
+ # @return [String]
181
+ def grammar_hash(fdir)
182
+ type = fdir.split("/").last
183
+ Relaton::Registry.instance.by_type(type)&.grammar_hash
184
+ end
185
+ end
186
+ end
@@ -1,3 +1,3 @@
1
1
  module Relaton
2
- VERSION = "1.7.9".freeze
2
+ VERSION = "1.8.pre2".freeze
3
3
  end
data/relaton.gemspec CHANGED
@@ -27,26 +27,28 @@ Gem::Specification.new do |spec|
27
27
  spec.require_paths = ["lib"]
28
28
  spec.files = `git ls-files`.split("\n")
29
29
  spec.test_files = `git ls-files -- {spec}/*`.split("\n")
30
- spec.required_ruby_version = Gem::Requirement.new(">= 2.4.0")
30
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.5.0")
31
31
 
32
32
  # spec.add_dependency "algoliasearch"
33
- spec.add_dependency "relaton-bipm", "~> 1.7.0"
34
- spec.add_dependency "relaton-bsi", "~> 1.7.pre"
35
- spec.add_dependency "relaton-calconnect", "~> 1.7.0"
36
- spec.add_dependency "relaton-cie", "~> 1.7.pre1"
37
- spec.add_dependency "relaton-ecma", "~> 1.7.pre1"
38
- spec.add_dependency "relaton-gb", "~> 1.7.0"
39
- spec.add_dependency "relaton-iec", ">= 1.7.6"
40
- spec.add_dependency "relaton-ieee", "~> 1.7.0"
41
- spec.add_dependency "relaton-ietf", "~> 1.7.0"
42
- spec.add_dependency "relaton-iho", "~> 1.7.0"
43
- spec.add_dependency "relaton-iso", ">= 1.7.1"
44
- spec.add_dependency "relaton-itu", ">= 1.7.2"
45
- spec.add_dependency "relaton-nist", ">= 1.7.1"
46
- spec.add_dependency "relaton-ogc", "~> 1.7.0"
47
- spec.add_dependency "relaton-omg", "~> 1.7.0"
48
- spec.add_dependency "relaton-un", "~> 1.7.0"
49
- spec.add_dependency "relaton-w3c", "~> 1.7.0"
33
+ spec.add_dependency "aws-sdk-s3", "~> 1.96.0"
34
+ spec.add_dependency "relaton-bipm", "~> 1.8.0"
35
+ spec.add_dependency "relaton-bsi", "~> 1.8.0"
36
+ spec.add_dependency "relaton-calconnect", "~> 1.8.0"
37
+ spec.add_dependency "relaton-cen", "~> 1.8.pre1"
38
+ spec.add_dependency "relaton-cie", "~> 1.8.0"
39
+ spec.add_dependency "relaton-ecma", "~> 1.8.0"
40
+ spec.add_dependency "relaton-gb", "~> 1.8.0"
41
+ spec.add_dependency "relaton-iec", ">= 1.8.0"
42
+ spec.add_dependency "relaton-ieee", "~> 1.8.0"
43
+ spec.add_dependency "relaton-ietf", "~> 1.8.0"
44
+ spec.add_dependency "relaton-iho", "~> 1.8.0"
45
+ spec.add_dependency "relaton-iso", ">= 1.8.0"
46
+ spec.add_dependency "relaton-itu", ">= 1.8.0"
47
+ spec.add_dependency "relaton-nist", ">= 1.8.0"
48
+ spec.add_dependency "relaton-ogc", "~> 1.8.0"
49
+ spec.add_dependency "relaton-omg", "~> 1.8.0"
50
+ spec.add_dependency "relaton-un", "~> 1.8.0"
51
+ spec.add_dependency "relaton-w3c", "~> 1.8.0"
50
52
 
51
53
  spec.add_development_dependency "byebug", "~> 11.0"
52
54
  # spec.add_development_dependency "debase"
@@ -56,7 +58,9 @@ Gem::Specification.new do |spec|
56
58
  spec.add_development_dependency "pry-byebug", "~> 3.9.0"
57
59
  spec.add_development_dependency "rake", "~> 13.0"
58
60
  spec.add_development_dependency "rspec", "~> 3.6"
59
- spec.add_development_dependency "rubocop", "= 0.54.0"
61
+ spec.add_development_dependency "rubocop", "~> 1.17.0"
62
+ spec.add_development_dependency "rubocop-performance", "~> 1.11.0"
63
+ spec.add_development_dependency "rubocop-rails", "~> 2.10.0"
60
64
  # spec.add_development_dependency "ruby-debug-ide"
61
65
  spec.add_development_dependency "simplecov", "~> 0.15"
62
66
  spec.add_development_dependency "timecop", "~> 0.9"
@@ -6,8 +6,8 @@ RSpec.describe Relaton::DbCache do
6
6
  cache_path = File.expand_path("~/.relaton/cache")
7
7
  FileUtils.mv cache_path, "relaton1/cache", force: true
8
8
  FileUtils.rm_rf %w(relaton)
9
- Relaton::DbCache.init_bib_caches(
10
- global_cache: true, local_cache: "", flush_caches: true
9
+ Relaton::Db.init_bib_caches(
10
+ global_cache: true, local_cache: "", flush_caches: true,
11
11
  )
12
12
  expect(File.exist?(cache_path)).to be true
13
13
  expect(File.exist?("relaton")).to be true
@@ -1,6 +1,23 @@
1
1
  RSpec.describe Relaton::Db do
2
2
  before(:each) { FileUtils.rm_rf %w[testcache testcache2] }
3
3
 
4
+ context "initialization in API mode" do
5
+ before(:each) { Relaton.configure { |c| c.api_mode = true } }
6
+ after(:each) { Relaton.configure { |c| c.api_mode = false } }
7
+
8
+ it do
9
+ db = Relaton::Db.new "cache", nil
10
+ cache = db.instance_variable_get :@db
11
+ expect(cache.dir).to eq "cache"
12
+ end
13
+
14
+ it "with default cache directory" do
15
+ db = Relaton::Db.init_bib_caches global_cache: true
16
+ cache = db.instance_variable_get :@db
17
+ expect(cache.dir).to eq "cache"
18
+ end
19
+ end
20
+
4
21
  context "modifing database" do
5
22
  let(:db) { Relaton::Db.new "testcache", "testcache2" }
6
23
 
@@ -2,7 +2,7 @@ RSpec.describe Relaton::Registry do
2
2
  it "outputs backend not present" do
3
3
  stub_const "Relaton::Registry::SUPPORTED_GEMS", ["not_supported_gem"]
4
4
  expect { Relaton::Registry.clone.instance }.to output(
5
- /backend not_supported_gem not present/
5
+ /backend not_supported_gem not present/,
6
6
  ).to_stderr
7
7
  end
8
8
 
@@ -79,5 +79,13 @@ RSpec.describe Relaton::Registry do
79
79
  it "CIE" do
80
80
  expect(Relaton::Registry.instance.by_type("CIE")).to be_instance_of RelatonCie::Processor
81
81
  end
82
+
83
+ it "BSI" do
84
+ expect(Relaton::Registry.instance.by_type("BSI")).to be_instance_of RelatonBsi::Processor
85
+ end
86
+
87
+ it "CEN" do
88
+ expect(Relaton::Registry.instance.by_type("CEN")).to be_instance_of RelatonCen::Processor
89
+ end
82
90
  end
83
91
  end
@@ -0,0 +1,130 @@
1
+ RSpec.describe Relaton::Storage do
2
+ context "API mode" do
3
+ before(:each) do
4
+ Relaton.configure do |config|
5
+ config.api_mode = true
6
+ end
7
+ Singleton.__init__ Relaton::Storage
8
+ end
9
+
10
+ after(:each) do
11
+ Relaton.configure do |config|
12
+ config.api_mode = false
13
+ end
14
+ Singleton.__init__ Relaton::Storage
15
+ end
16
+
17
+ let(:storage) { Relaton::Storage.instance }
18
+ let(:bucket) { "test-bucket" }
19
+
20
+ it "save document to S3" do
21
+ dir = "cahche/iso"
22
+ # file = "doc.xml"
23
+ body = "<doc>Test doc</doc>"
24
+ key = File.join dir, "doc.xml"
25
+ client = double "AwsClient"
26
+ expect(ENV).to receive(:[]).with("AWS_BUCKET").and_return(bucket).twice
27
+ expect(client).to receive(:head_object).with(bucket: bucket, key: "cahche/iso/version")
28
+ expect(client).to receive(:put_object).with(
29
+ bucket: bucket, key: key, body: body,
30
+ content_type: "text/plain; charset=utf-8"
31
+ )
32
+ expect(Aws::S3::Client).to receive(:new).and_return client
33
+ storage.save dir, key, body
34
+ end
35
+
36
+ it "read document from S3" do
37
+ dir = "cahche/iso"
38
+ # file = "doc.xml"
39
+ body = "<doc>Test doc</doc>"
40
+ key = File.join dir, "doc"
41
+ client = double "AwsClient"
42
+ item = double "Item", key: "#{key}.xml"
43
+ list = double "List", contents: [item]
44
+ obj_body = double "Body", read: body
45
+ obj = double "Object", body: obj_body
46
+ expect(ENV).to receive(:[]).with("AWS_BUCKET").and_return(bucket).twice
47
+ expect(client).to receive(:list_objects_v2).with(bucket: bucket, prefix: "#{key}.").and_return list
48
+ expect(client).to receive(:get_object).with(bucket: bucket, key: "#{key}.xml").and_return obj
49
+ expect(Aws::S3::Client).to receive(:new).and_return client
50
+ expect(storage.get(key)).to eq body
51
+ end
52
+
53
+ it "delete document from S3" do
54
+ key = "cache/iso/doc"
55
+ client = double "AwsClient"
56
+ item = double "Item", key: "#{key}.xml"
57
+ list = double "List", contents: [item]
58
+ expect(ENV).to receive(:[]).with("AWS_BUCKET").and_return(bucket).twice
59
+ expect(client).to receive(:list_objects_v2).with(bucket: bucket, prefix: "#{key}.").and_return list
60
+ expect(client).to receive(:delete_object).with(bucket: bucket, key: "#{key}.xml")
61
+ expect(Aws::S3::Client).to receive(:new).and_return client
62
+ storage.delete key
63
+ end
64
+
65
+ it "return all the documents from S3" do
66
+ dir = "cahche/iso"
67
+ # file = "doc.xml"
68
+ body = "<doc>Test doc</doc>"
69
+ key = File.join dir, "doc.xml"
70
+ client = double "AwsClient"
71
+ expect(ENV).to receive(:[]).with("AWS_BUCKET").and_return(bucket).twice
72
+ item = double "Item", key: key
73
+ list = double "List", contents: [item]
74
+ obj_body = double "Body", read: body
75
+ obj = double "Object", body: obj_body
76
+ expect(client).to receive(:list_objects_v2).with(bucket: bucket, prefix: dir).and_return list
77
+ expect(client).to receive(:get_object).with(bucket: bucket, key: key).and_return obj
78
+ expect(Aws::S3::Client).to receive(:new).and_return client
79
+ contents = storage.all dir
80
+ expect(contents).to eq [body]
81
+ end
82
+
83
+ it "set version" do
84
+ dir = "cahche/iso"
85
+ key = File.join dir, "version"
86
+ hash = Relaton::Registry.instance.by_type("iso").grammar_hash
87
+ client = double "AwsClient"
88
+ expect(ENV).to receive(:[]).with("AWS_BUCKET").and_return(bucket).twice
89
+ # expect(ENV).to receive(:[]).and_call_original
90
+ error = Aws::S3::Errors::NotFound.new Seahorse::Client::RequestContext.new, ""
91
+ expect(client).to receive(:head_object).with(bucket: bucket, key: key)
92
+ .and_raise error
93
+ expect(client).to receive(:put_object).with(
94
+ bucket: bucket, key: key, body: hash,
95
+ content_type: "text/plain; charset=utf-8"
96
+ )
97
+ expect(Aws::S3::Client).to receive(:new).and_return client
98
+ storage.send :set_version, dir
99
+ end
100
+
101
+ context "check version" do
102
+ it "valid" do
103
+ dir = "cahche/iso"
104
+ key = File.join dir, "version"
105
+ hash = Relaton::Registry.instance.by_type("iso").grammar_hash
106
+ client = double "AwsClient"
107
+ obj_body = double "Body", read: hash
108
+ obj = double "Object", body: obj_body
109
+ expect(client).to receive(:get_object).with(bucket: bucket, key: key).and_return obj
110
+ expect(Aws::S3::Client).to receive(:new).and_return client
111
+ expect(ENV).to receive(:[]).with("AWS_BUCKET").and_return(bucket)
112
+ expect(storage.check_version?(dir)).to be true
113
+ end
114
+
115
+ it "version file doesn't exist" do
116
+ dir = "cahche/iso"
117
+ key = File.join dir, "version"
118
+ # hash = "invalid"
119
+ client = double "AwsClient"
120
+ # obj_body = double "Body", read: hash
121
+ # obj = double "Object", body: obj_body
122
+ error = Aws::S3::Errors::NoSuchKey.new Seahorse::Client::RequestContext.new, ""
123
+ expect(client).to receive(:get_object).with(bucket: bucket, key: key).and_raise error
124
+ expect(Aws::S3::Client).to receive(:new).and_return client
125
+ expect(ENV).to receive(:[]).with("AWS_BUCKET").and_return(bucket)
126
+ expect(storage.check_version?(dir)).to be false
127
+ end
128
+ end
129
+ end
130
+ end