relaton 1.11.4 → 1.12.1

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.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/lib/relaton/db.rb +61 -31
  3. data/lib/relaton/db_cache.rb +7 -1
  4. data/lib/relaton/version.rb +1 -1
  5. data/relaton.gemspec +21 -21
  6. data/spec/relaton/db_spec.rb +51 -1
  7. data/spec/spec_helper.rb +1 -0
  8. data/spec/vcr_cassetes/3gpp_tr_00_01u_umts_3_0_0.yml +7 -7
  9. data/spec/vcr_cassetes/async_fetch.yml +1402 -1402
  10. data/spec/vcr_cassetes/bipm_i18n_async_fetch.yml +51 -259
  11. data/spec/vcr_cassetes/bsi_bs_en_iso_8848.yml +11 -11
  12. data/spec/vcr_cassetes/cc_dir_10005_2019.yml +10 -10
  13. data/spec/vcr_cassetes/cie_001_1980.yml +10 -9
  14. data/spec/vcr_cassetes/ecma_6.yml +47 -15
  15. data/spec/vcr_cassetes/en_10160_1999.yml +27 -27
  16. data/spec/vcr_cassetes/fisp_140.yml +6 -6
  17. data/spec/vcr_cassetes/gb_t_20223_2006.yml +6 -6
  18. data/spec/vcr_cassetes/iana_service_names_port_numbers.yml +10 -13
  19. data/spec/vcr_cassetes/iec_60050_102_2007.yml +28 -28
  20. data/spec/vcr_cassetes/iec_combined_included.yml +88 -88
  21. data/spec/vcr_cassetes/ieee_528_2019.yml +823 -1133
  22. data/spec/vcr_cassetes/iho_b_11.yml +7 -7
  23. data/spec/vcr_cassetes/iso_111111119115_1.yml +2 -2
  24. data/spec/vcr_cassetes/iso_19115_1.yml +16 -16
  25. data/spec/vcr_cassetes/iso_19115_1_2.yml +29 -29
  26. data/spec/vcr_cassetes/iso_19115_all_parts.yml +15 -15
  27. data/spec/vcr_cassetes/iso_19133_2005.yml +15 -15
  28. data/spec/vcr_cassetes/iso_combined_applied.yml +30 -30
  29. data/spec/vcr_cassetes/iso_combined_included.yml +31 -31
  30. data/spec/vcr_cassetes/iso_dis_14093.yml +14 -14
  31. data/spec/vcr_cassetes/itu_combined_included.yml +168 -168
  32. data/spec/vcr_cassetes/oasis_amqp_core_types_v1_0_pt1.yml +9 -9
  33. data/spec/vcr_cassetes/ogc_19_025r1.yml +7 -7
  34. data/spec/vcr_cassetes/omg_ami4ccm_1_0.yml +4 -4
  35. data/spec/vcr_cassetes/rfc_8341.yml +10 -10
  36. data/spec/vcr_cassetes/sp_800_38b.yml +6 -6
  37. data/spec/vcr_cassetes/threads_from_env.yml +56 -56
  38. data/spec/vcr_cassetes/un_rtade_cefact_2004_32.yml +31 -29
  39. data/spec/vcr_cassetes/w3c_json_ld11.yml +20 -20
  40. metadata +44 -44
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bd53313a7d35f6ed1adf7669962afc84282d15d232247d3facec910aaba05270
4
- data.tar.gz: 304a0e1c5a44731f0a4f9a30c063df920deb8694aca702044fd1ab03a10fe5e8
3
+ metadata.gz: 8299cf7ea6a28e344f438461d16233fe9acd733bc00441583ce9768c702b15fa
4
+ data.tar.gz: 28d87384bb3b763981ae98902b144236254b7cce20c3d608ef746be679b0661a
5
5
  SHA512:
6
- metadata.gz: 4cfb3d708769580fccb31ef09a408265a4b828e70082c7f44a2fe485c2982437cf4f8b8369ada51e7e2d9d3e05c05eada5eaca8126506ea5b9224b7575727501
7
- data.tar.gz: 2255f0695f06f0714e55b03d9a9ad7c2b7567d417ff184e598c462e299aeed145fb6fb143fc9e83aedf7223479addd9542a6ea3d16b17298f55621676100010f
6
+ metadata.gz: 5720aed26b5585b6673d92fd8c99fbae0883689c254344d5dbad5549a157388bd6422a2550942eb58a8d32f1c2d0aeafd6485de55274c0c02271ec5f87661405
7
+ data.tar.gz: 45fca34e30fe15699b9b3933f4060c877d54947ae31c5bc70ff05812b654c0876175eedda1d71ef16755a4db02a797c30199cd2128d081ae46b186a4939964f5
data/lib/relaton/db.rb CHANGED
@@ -95,9 +95,18 @@ module Relaton
95
95
  result
96
96
  end
97
97
 
98
+ #
98
99
  # Fetch asynchronously
99
- def fetch_async(code, year = nil, opts = {}, &block) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
100
- stdclass = @registry.class_by_ref code
100
+ #
101
+ # @param [String] ref reference
102
+ # @param [String] year document yer
103
+ # @param [Hash] opts options
104
+ #
105
+ # @return [RelatonBib::BibliographicItem, RelatonBib::RequestError, nil] bibitem if document is found,
106
+ # request error if server doesn't answer, nil if document not found
107
+ #
108
+ def fetch_async(ref, year = nil, opts = {}, &block) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
109
+ stdclass = @registry.class_by_ref ref
101
110
  if stdclass
102
111
  unless @queues[stdclass]
103
112
  processor = @registry.processors[stdclass]
@@ -106,11 +115,14 @@ module Relaton
106
115
  args[3].call fetch(*args[0..2])
107
116
  rescue RelatonBib::RequestError => e
108
117
  args[3].call e
118
+ rescue StandardError => e
119
+ Util.log "[relaton] ERROR: #{args[0]} -- #{e.message}", :error
120
+ args[3].call nil
109
121
  end
110
122
  @queues[stdclass] = { queue: Queue.new, workers_pool: wp }
111
123
  Thread.new { process_queue @queues[stdclass] }
112
124
  end
113
- @queues[stdclass][:queue] << [code, year, opts, block]
125
+ @queues[stdclass][:queue] << [ref, year, opts, block]
114
126
  else yield nil
115
127
  end
116
128
  end
@@ -196,7 +208,7 @@ module Relaton
196
208
  end
197
209
 
198
210
  # @param file [String] file path
199
- # @param content [String] content in XML or YAmL format
211
+ # @param content [String] content in XML or YAML format
200
212
  # @param edition [String, nil] edition to filter
201
213
  # @param year [Integer, nil] year to filter
202
214
  # @return [BibliographicItem, nil]
@@ -205,7 +217,7 @@ module Relaton
205
217
  item = if file.match?(/xml$/) then processor.from_xml(content)
206
218
  else processor.hash_to_bib(YAML.safe_load(content))
207
219
  end
208
- item if (edition.nil? || item.edition == edition) && (year.nil? ||
220
+ item if (edition.nil? || item.edition.content == edition) && (year.nil? ||
209
221
  item.date.detect { |d| d.type == "published" && d.on(:year).to_s == year.to_s })
210
222
  end
211
223
 
@@ -293,8 +305,10 @@ module Relaton
293
305
  [prefix, code]
294
306
  end
295
307
 
308
+ #
296
309
  # @param entry [String] XML string
297
310
  # @param stdclass [Symbol]
311
+ #
298
312
  # @return [nil, RelatonBib::BibliographicItem,
299
313
  # RelatonIsoBib::IsoBibliographicItem, RelatonItu::ItuBibliographicItem,
300
314
  # RelatonIetf::IetfBibliographicItem, RelatonIec::IecBibliographicItem,
@@ -304,9 +318,7 @@ module Relaton
304
318
  # RelatonBipm::BipmBibliographicItem, RelatonIho::IhoBibliographicItem,
305
319
  # RelatonOmg::OmgBibliographicItem, RelatonW3c::W3cBibliographicItem]
306
320
  def bib_retval(entry, stdclass)
307
- if entry.nil? || entry.match?(/^not_found/) then nil
308
- else @registry.processors[stdclass].from_xml(entry)
309
- end
321
+ @registry.processors[stdclass].from_xml(entry) if entry
310
322
  end
311
323
 
312
324
  # @param code [String]
@@ -334,8 +346,7 @@ module Relaton
334
346
  if db.nil?
335
347
  return if opts[:fetch_db]
336
348
 
337
- bibentry = new_bib_entry(searchcode, year, opts, stdclass, db: db,
338
- id: id)
349
+ bibentry = new_bib_entry(searchcode, year, opts, stdclass)
339
350
  return bib_retval(bibentry, stdclass)
340
351
  end
341
352
 
@@ -348,45 +359,58 @@ module Relaton
348
359
  @semaphore.synchronize do
349
360
  db.clone_entry id, altdb if altdb.valid_entry? id, year
350
361
  end
351
- entry = new_bib_entry(searchcode, year, opts, stdclass, db: db, id: id) unless db[id]
362
+ new_bib_entry(searchcode, year, opts, stdclass, db: db, id: id)
352
363
  @semaphore.synchronize do
353
- db[id] ||= entry
354
364
  altdb.clone_entry(id, db) if !altdb.valid_entry?(id, year)
355
365
  end
356
366
  else
357
367
  return bib_retval(db[id], stdclass) if opts[:fetch_db]
358
368
 
359
- db[id] ||= new_bib_entry(searchcode, year, opts, stdclass, db: db,
360
- id: id)
369
+ new_bib_entry(searchcode, year, opts, stdclass, db: db, id: id)
361
370
  end
362
371
  bib_retval(db[id], stdclass)
363
372
  end
364
373
 
374
+ #
375
+ # Create new bibliographic entry if it doesn't exist in database
376
+ #
365
377
  # @param code [String]
366
378
  # @param year [String]
367
379
  #
368
380
  # @param opts [Hash]
369
- # @option opts [Boolean] :all_parts If all-parts reference is required
370
- # @option opts [Boolean] :keep_year If undated reference should return
371
- # actual reference with year
381
+ # @option opts [Boolean, nil] :all_parts If true then all-parts reference is
382
+ # requested
383
+ # @option opts [Boolean, nil] :keep_year If true then undated reference
384
+ # should return actual reference with year
372
385
  # @option opts [Integer] :retries (1) Number of network retries
373
386
  #
374
387
  # @param stdclass [Symbol]
375
- # @param db [Relaton::DbCache,`NilClass]
376
- # @param id [String] docid
377
- # @return [String]
378
- def new_bib_entry(code, year, opts, stdclass, **args) # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity
388
+ # @param db [Relaton::DbCache,`nil]
389
+ # @param id [String, nil] docid
390
+ #
391
+ # @return [String] bibliographic entry
392
+ # XML or "redirection ID" or "not_found YYYY-MM-DD" string
393
+ #
394
+ def new_bib_entry(code, year, opts, stdclass, **args) # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity,Metrics/MethodLength
395
+ entry = @semaphore.synchronize { args[:db] && args[:db][args[:id]] }
396
+ if entry
397
+ Util.log "[relaton] (#{code}) not found." if entry&.match?(/^not_found/)
398
+ return entry
399
+ end
400
+
379
401
  bib = net_retry(code, year, opts, stdclass, opts.fetch(:retries, 1))
380
402
  bib_id = bib&.docidentifier&.first&.id
381
403
 
382
404
  # when docid doesn't match bib's id then return a reference to bib's id
383
- if args[:db] && args[:id] &&
384
- bib_id && args[:id] !~ %r{#{Regexp.quote("(#{bib_id})")}}
385
- bid = std_id(bib.docidentifier.first.id, nil, {}, stdclass).first
386
- @semaphore.synchronize { args[:db][bid] ||= bib_entry bib }
387
- "redirection #{bid}"
388
- else bib_entry bib
389
- end
405
+ entry = if args[:db] && args[:id] && bib_id && args[:id] !~ %r{#{Regexp.quote("(#{bib_id})")}}
406
+ bid = std_id(bib.docidentifier.first.id, nil, {}, stdclass).first
407
+ @semaphore.synchronize { args[:db][bid] ||= bib_entry bib }
408
+ "redirection #{bid}"
409
+ else bib_entry bib
410
+ end
411
+ return entry if args[:db].nil? || args[:id].nil?
412
+
413
+ @semaphore.synchronize { args[:db][args[:id]] ||= entry }
390
414
  end
391
415
 
392
416
  # @raise [RelatonBib::RequestError]
@@ -442,10 +466,16 @@ module Relaton
442
466
  end
443
467
 
444
468
  class << self
469
+ #
445
470
  # Initialse and return relaton instance, with local and global cache names
446
- # local_cache: local cache name; none created if nil; "relaton" created
447
- # if empty global_cache: boolean to create global_cache
448
- # flush_caches: flush caches
471
+ #
472
+ # @param local_cache [String, nil] local cache name;
473
+ # "relaton" created if empty or nil
474
+ # @param global_cache [Boolean, nil] create global_cache if true
475
+ # @param flush_caches [Boolean, nil] flush caches if true
476
+ #
477
+ # @return [Relaton::Db] relaton DB instance
478
+ #
449
479
  def init_bib_caches(**opts) # rubocop:disable Metrics/CyclomaticComplexity
450
480
  globalname = global_bibliocache_name if opts[:global_cache]
451
481
  localname = local_bibliocache_name(opts[:local_cache])
@@ -45,7 +45,7 @@ module Relaton
45
45
  end
46
46
 
47
47
  prefix_dir = "#{@dir}/#{prefix(key)}"
48
- FileUtils::mkdir_p prefix_dir unless Dir.exist? prefix_dir
48
+ FileUtils::mkdir_p prefix_dir
49
49
  set_version prefix_dir
50
50
  file_safe_write "#{filename(key)}.#{ext(value)}", value
51
51
  end
@@ -72,6 +72,12 @@ module Relaton
72
72
  end
73
73
  end
74
74
 
75
+ #
76
+ # Save entry from cache of `db` to this cache.
77
+ #
78
+ # @param [String] key key of the entry
79
+ # @param [Relaton::Db] db database
80
+ #
75
81
  def clone_entry(key, db)
76
82
  self[key] ||= db.get(key)
77
83
  if (code = redirect? get(key))
@@ -1,3 +1,3 @@
1
1
  module Relaton
2
- VERSION = "1.11.4".freeze
2
+ VERSION = "1.12.1".freeze
3
3
  end
data/relaton.gemspec CHANGED
@@ -29,27 +29,27 @@ Gem::Specification.new do |spec|
29
29
  # spec.test_files = `git ls-files -- {spec}/*`.split("\n")
30
30
  spec.required_ruby_version = Gem::Requirement.new(">= 2.6.0")
31
31
 
32
- spec.add_dependency "relaton-3gpp", "~> 1.11.0"
33
- spec.add_dependency "relaton-bipm", "~> 1.11.0"
34
- spec.add_dependency "relaton-bsi", "~> 1.11.0"
35
- spec.add_dependency "relaton-calconnect", "~> 1.11.0"
36
- spec.add_dependency "relaton-cen", "~> 1.11.0"
37
- spec.add_dependency "relaton-cie", "~> 1.11.0"
38
- spec.add_dependency "relaton-ecma", "~> 1.11.0"
39
- spec.add_dependency "relaton-gb", "~> 1.11.0"
40
- spec.add_dependency "relaton-iana", "~> 1.11.0"
41
- spec.add_dependency "relaton-iec", "~> 1.11.0"
42
- spec.add_dependency "relaton-ieee", "~> 1.11.0"
43
- spec.add_dependency "relaton-ietf", "~> 1.11.0"
44
- spec.add_dependency "relaton-iho", "~> 1.11.0"
45
- spec.add_dependency "relaton-iso", "~> 1.11.0"
46
- spec.add_dependency "relaton-itu", "~> 1.11.0"
47
- spec.add_dependency "relaton-nist", "~> 1.11.0"
48
- spec.add_dependency "relaton-oasis", "~> 1.11.0"
49
- spec.add_dependency "relaton-ogc", "~> 1.11.0"
50
- spec.add_dependency "relaton-omg", "~> 1.11.0"
51
- spec.add_dependency "relaton-un", "~> 1.11.0"
52
- spec.add_dependency "relaton-w3c", "~> 1.11.0"
32
+ spec.add_dependency "relaton-3gpp", "~> 1.12.0"
33
+ spec.add_dependency "relaton-bipm", "~> 1.12.0"
34
+ spec.add_dependency "relaton-bsi", "~> 1.12.0"
35
+ spec.add_dependency "relaton-calconnect", "~> 1.12.0"
36
+ spec.add_dependency "relaton-cen", "~> 1.12.0"
37
+ spec.add_dependency "relaton-cie", "~> 1.12.0"
38
+ spec.add_dependency "relaton-ecma", "~> 1.12.0"
39
+ spec.add_dependency "relaton-gb", "~> 1.12.0"
40
+ spec.add_dependency "relaton-iana", "~> 1.12.0"
41
+ spec.add_dependency "relaton-iec", "~> 1.12.0"
42
+ spec.add_dependency "relaton-ieee", "~> 1.12.0"
43
+ spec.add_dependency "relaton-ietf", "~> 1.12.0"
44
+ spec.add_dependency "relaton-iho", "~> 1.12.0"
45
+ spec.add_dependency "relaton-iso", "~> 1.12.0"
46
+ spec.add_dependency "relaton-itu", "~> 1.12.0"
47
+ spec.add_dependency "relaton-nist", "~> 1.12.0"
48
+ spec.add_dependency "relaton-oasis", "~> 1.12.0"
49
+ spec.add_dependency "relaton-ogc", "~> 1.12.0"
50
+ spec.add_dependency "relaton-omg", "~> 1.12.0"
51
+ spec.add_dependency "relaton-un", "~> 1.12.0"
52
+ spec.add_dependency "relaton-w3c", "~> 1.12.0"
53
53
 
54
54
  spec.add_development_dependency "byebug", "~> 11.0"
55
55
  spec.add_development_dependency "equivalent-xml", "~> 0.6"
@@ -1,6 +1,40 @@
1
1
  RSpec.describe Relaton::Db do
2
2
  before(:each) { FileUtils.rm_rf %w[testcache testcache2] }
3
3
 
4
+ context "instance methods" do
5
+ subject { Relaton::Db.new nil, nil }
6
+
7
+ context "#search_edition_year" do
8
+ it "create bibitem from YAML content" do
9
+ h = { "docid" => [{ "id" => "ISO 123", type: "ISO", "primary" => true }] }
10
+ expect(YAML).to receive(:safe_load).with(:content).and_return h
11
+ item = subject.send :search_edition_year, "iso/item.yaml", :content, nil, nil
12
+ expect(item).to be_instance_of RelatonIsoBib::IsoBibliographicItem
13
+ end
14
+ end
15
+
16
+ context "#new_bib_entry" do
17
+ it "warn if cached entry is not_found" do
18
+ id = "ISO(ISO 123)"
19
+ db = double "db"
20
+ expect(db).to receive(:[]).with(id).and_return "not_found"
21
+ expect do
22
+ entry = subject.send :new_bib_entry, "ISO 123", nil, {}, :relaton_iso, db: db, id: id
23
+ expect(entry).to eq "not_found"
24
+ end.to output("[relaton] (ISO 123) not found.\n").to_stderr
25
+ end
26
+ end
27
+ end
28
+
29
+ context "class methods" do
30
+ it "::init_bib_caches" do
31
+ expect(FileUtils).to receive(:rm_rf).with(/\/\.relaton\/cache$/)
32
+ expect(FileUtils).to receive(:rm_rf).with(/testcache\/cache$/)
33
+ expect(Relaton::Db).to receive(:new).with(/\/\.relaton\/cache$/, /testcache\/cache$/)
34
+ Relaton::Db.init_bib_caches(global_cache: true, local_cache: "testcache", flush_caches: true)
35
+ end
36
+ end
37
+
4
38
  context "modifing database" do
5
39
  let(:db) { Relaton::Db.new "testcache", "testcache2" }
6
40
 
@@ -178,7 +212,7 @@ RSpec.describe Relaton::Db do
178
212
  refs = ["CGPM Resolution 1889-00", "CGPM Résolution 1889-00",
179
213
  "CGPM Réunion 9", "CGPM Meeting 9"]
180
214
  results = []
181
- VCR.use_cassette "bipm_i18n_async_fetch" do
215
+ VCR.use_cassette "bipm_i18n_async_fetch", match_requests_on: %i[method uri body] do
182
216
  refs.each do |ref|
183
217
  db.fetch_async(ref) { |r| queue << [r, ref] }
184
218
  end
@@ -198,6 +232,22 @@ RSpec.describe Relaton::Db do
198
232
  expect(result).to be_nil
199
233
  end
200
234
 
235
+ it "handle HTTP request error" do
236
+ expect(db).to receive(:fetch).and_raise RelatonBib::RequestError
237
+ db.fetch_async("ISO REF") { |r| queue << r }
238
+ result = Timeout.timeout(5) { queue.pop }
239
+ expect(result).to be_instance_of RelatonBib::RequestError
240
+ end
241
+
242
+ it "handle other errors" do
243
+ expect(db).to receive(:fetch).and_raise Errno::EACCES
244
+ expect do
245
+ db.fetch_async("ISO REF") { |r| queue << r }
246
+ result = Timeout.timeout(5) { queue.pop }
247
+ expect(result).to be_nil
248
+ end.to output("[relaton] ERROR: ISO REF -- Permission denied\n").to_stderr
249
+ end
250
+
201
251
  it "use threads number from RELATON_FETCH_PARALLEL" do
202
252
  expect(ENV).to receive(:[]).with("RELATON_FETCH_PARALLEL").and_return(1)
203
253
  allow(ENV).to receive(:[]).and_call_original
data/spec/spec_helper.rb CHANGED
@@ -13,6 +13,7 @@ VCR.configure do |c|
13
13
  clean_outdated_http_interactions: true,
14
14
  re_record_interval: 7 * 24 * 3600,
15
15
  record: :once,
16
+ allow_playback_repeats: true,
16
17
  }
17
18
  c.hook_into :webmock
18
19
  end
@@ -41,29 +41,29 @@ http_interactions:
41
41
  X-Xss-Protection:
42
42
  - 1; mode=block
43
43
  X-Github-Request-Id:
44
- - 7178:6974:A78BC:C192B:62AAF846
44
+ - 7D28:10C50:1BF854C:1DDFC0B:62BDDA6B
45
45
  Accept-Ranges:
46
46
  - bytes
47
47
  Date:
48
- - Thu, 16 Jun 2022 09:30:46 GMT
48
+ - Thu, 30 Jun 2022 17:16:27 GMT
49
49
  Via:
50
50
  - 1.1 varnish
51
51
  X-Served-By:
52
- - cache-vie6334-VIE
52
+ - cache-vie6348-VIE
53
53
  X-Cache:
54
54
  - MISS
55
55
  X-Cache-Hits:
56
56
  - '0'
57
57
  X-Timer:
58
- - S1655371847.568153,VS0,VE230
58
+ - S1656609387.047148,VS0,VE235
59
59
  Vary:
60
60
  - Authorization,Accept-Encoding,Origin
61
61
  Access-Control-Allow-Origin:
62
62
  - "*"
63
63
  X-Fastly-Request-Id:
64
- - da76509a3e570d0b83c3692633c0dfea81acef96
64
+ - 93a267346ed97c52087b05f16495084f70b848e8
65
65
  Expires:
66
- - Thu, 16 Jun 2022 09:35:46 GMT
66
+ - Thu, 30 Jun 2022 17:21:27 GMT
67
67
  Source-Age:
68
68
  - '0'
69
69
  body:
@@ -143,5 +143,5 @@ http_interactions:
143
143
  freeze_stage3_meeting: SMG-28
144
144
  close_meeting: SP-28
145
145
  project_end: '1999-02-12'
146
- recorded_at: Thu, 16 Jun 2022 09:30:46 GMT
146
+ recorded_at: Thu, 30 Jun 2022 17:16:27 GMT
147
147
  recorded_with: VCR 6.1.0