metanorma-plugin-lutaml 0.7.62 → 0.7.63
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/lib/metanorma/plugin/lutaml/express_repository_cache.rb +90 -0
- data/lib/metanorma/plugin/lutaml/lutaml_preprocessor.rb +8 -2
- data/lib/metanorma/plugin/lutaml/utils.rb +28 -6
- data/lib/metanorma/plugin/lutaml/version.rb +1 -1
- data/lib/metanorma-plugin-lutaml.rb +2 -0
- metadata +3 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 9087a3bdc384a47318affb8b8fc243d2bd7817d3c726b3b5cf27f9c229068a4a
|
|
4
|
+
data.tar.gz: 7685b187bbf7d47e771b2276d42f62b3a4ed849abdec9ddd2154ff48f393864d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: cc8c7e181551079b69bb24d41c6bacea72bfa7e64cb6bce41ea3c6bc676f3883f7372a40d97d032e9dbafa0e2fab92c4e3783f280b579eeb15dd1aa675f68067
|
|
7
|
+
data.tar.gz: 90a1af9e236cf1a855b4042e459951da82d477e9180f0e3192819ef60c9e157e0236e9fc96d2343e30fe70e053154b88ff53f436f0b79b59262d54b86bef513a
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "digest"
|
|
4
|
+
require "expressir"
|
|
5
|
+
|
|
6
|
+
module Metanorma
|
|
7
|
+
module Plugin
|
|
8
|
+
module Lutaml
|
|
9
|
+
# Process-wide, content-keyed store of parsed Expressir repositories.
|
|
10
|
+
#
|
|
11
|
+
# A Metanorma collection compiles many documents against the same
|
|
12
|
+
# schema set, and every document compile used to re-parse the whole
|
|
13
|
+
# EXPRESS corpus (measured on ISO 10303-104: 125 schemas, 8.29 MB,
|
|
14
|
+
# ~12.5 s wall and ~1.1 GB of allocations per document). This cache
|
|
15
|
+
# parses each distinct source once per process: the key is derived
|
|
16
|
+
# from the schema sources' content digests, so an edited source
|
|
17
|
+
# produces a new key and re-parses instead of serving a stale
|
|
18
|
+
# repository.
|
|
19
|
+
#
|
|
20
|
+
# Deliberately NOT registered in CacheRegistry: the metanorma
|
|
21
|
+
# toolchain flushes CacheRegistry after every document compile to
|
|
22
|
+
# release the render-time XMI/XSD graphs, and a flush here would
|
|
23
|
+
# restore the per-document re-parse this cache exists to remove
|
|
24
|
+
# (metanorma/metanorma-plugin-lutaml#341). The repositories are
|
|
25
|
+
# collection-lifetime state; the LRU bound below caps how many
|
|
26
|
+
# corpora stay resident.
|
|
27
|
+
class ExpressRepositoryCache
|
|
28
|
+
# Key digest version: bump when the key composition changes so
|
|
29
|
+
# keys from different compositions can never collide.
|
|
30
|
+
KEY_VERSION = "metanorma-plugin-lutaml/express-repository-cache/v1"
|
|
31
|
+
|
|
32
|
+
MAX_SIZE = 4
|
|
33
|
+
|
|
34
|
+
class << self
|
|
35
|
+
# Content key for a set of EXPRESS source files: the key version,
|
|
36
|
+
# the Expressir version, then every file's path and content
|
|
37
|
+
# digest, in the order given (the order shapes the repository,
|
|
38
|
+
# and the parsed model embeds file paths, so both belong in the
|
|
39
|
+
# key). A changed source yields a new key.
|
|
40
|
+
def source_key(paths)
|
|
41
|
+
digest = Digest::SHA256.new
|
|
42
|
+
digest.update(KEY_VERSION)
|
|
43
|
+
digest.update(Expressir::Version::VERSION.to_s)
|
|
44
|
+
paths.each do |path|
|
|
45
|
+
digest.update(path)
|
|
46
|
+
digest.update(Digest::SHA256.file(path).digest)
|
|
47
|
+
end
|
|
48
|
+
digest.hexdigest
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Identity key for one prebuilt file (a compiled-set artifact or
|
|
52
|
+
# an Expressir cache file): expanded path plus mtime and size.
|
|
53
|
+
# The file is not read for the key — compiled sets hydrate lazily
|
|
54
|
+
# and re-reading a whole artifact per document would defeat the
|
|
55
|
+
# sharing; path + mtime + size detects a rebuilt file.
|
|
56
|
+
def file_key(path)
|
|
57
|
+
[
|
|
58
|
+
KEY_VERSION,
|
|
59
|
+
File.expand_path(path),
|
|
60
|
+
File.mtime(path).to_f,
|
|
61
|
+
File.size(path),
|
|
62
|
+
]
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def fetch_or_store(key, &block)
|
|
66
|
+
store.fetch_or_store(key, &block)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def fetch(key)
|
|
70
|
+
store.fetch(key)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def clear
|
|
74
|
+
store.clear
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def size
|
|
78
|
+
store.size
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
private
|
|
82
|
+
|
|
83
|
+
def store
|
|
84
|
+
@store ||= CacheStore.new(max_size: MAX_SIZE)
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
@@ -27,10 +27,16 @@ module Metanorma
|
|
|
27
27
|
def load_lutaml_file(document, file_path, _options)
|
|
28
28
|
full_path = Utils.relative_file_path(document, file_path)
|
|
29
29
|
|
|
30
|
-
file = File.new(full_path, encoding: "UTF-8")
|
|
31
30
|
if full_path.end_with?(".exp")
|
|
32
|
-
|
|
31
|
+
# Shared per process (ExpressRepositoryCache): a collection's
|
|
32
|
+
# documents re-parse the same schema file otherwise.
|
|
33
|
+
ExpressRepositoryCache.fetch_or_store(
|
|
34
|
+
ExpressRepositoryCache.source_key([full_path]),
|
|
35
|
+
) do
|
|
36
|
+
::Expressir::Express::Parser.from_file(full_path)
|
|
37
|
+
end
|
|
33
38
|
else
|
|
39
|
+
file = File.new(full_path, encoding: "UTF-8")
|
|
34
40
|
::Lutaml::Lml::Parser.parse(file)
|
|
35
41
|
end
|
|
36
42
|
end
|
|
@@ -200,7 +200,11 @@ module Metanorma
|
|
|
200
200
|
end
|
|
201
201
|
|
|
202
202
|
def load_express_repo_from_cache(path)
|
|
203
|
-
|
|
203
|
+
ExpressRepositoryCache.fetch_or_store(
|
|
204
|
+
ExpressRepositoryCache.file_key(path),
|
|
205
|
+
) do
|
|
206
|
+
::Expressir::Express::Cache.from_file(path)
|
|
207
|
+
end
|
|
204
208
|
end
|
|
205
209
|
|
|
206
210
|
def save_express_repo_to_cache(path, repository, document)
|
|
@@ -225,14 +229,32 @@ module Metanorma
|
|
|
225
229
|
# Compiled-set artifacts (EXSCS1) hydrate per file on first
|
|
226
230
|
# touch: rendering one schema's page costs one hydration, not
|
|
227
231
|
# the whole repository. The artifact already carries content
|
|
228
|
-
# digests, so the expressir Cache layer does not apply.
|
|
232
|
+
# digests, so the expressir Cache layer does not apply. The
|
|
233
|
+
# repository handle itself is shared per process, so a second
|
|
234
|
+
# document compile reuses the first one's hydrated files.
|
|
229
235
|
def load_express_from_artifact(path)
|
|
230
|
-
|
|
236
|
+
ExpressRepositoryCache.fetch_or_store(
|
|
237
|
+
ExpressRepositoryCache.file_key(path),
|
|
238
|
+
) do
|
|
239
|
+
Expressir::Express::LazyRepository.new(path.to_s)
|
|
240
|
+
end
|
|
231
241
|
end
|
|
232
242
|
|
|
233
243
|
def load_express_from_folder(folder)
|
|
234
|
-
|
|
235
|
-
|
|
244
|
+
parse_express_files(Dir["#{folder}/*.exp"])
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
# Parse a set of EXPRESS sources once per process: the parsed
|
|
248
|
+
# repository is shared through ExpressRepositoryCache, keyed by
|
|
249
|
+
# the sources' content digests, so the documents of a collection
|
|
250
|
+
# reuse the first compile's parse instead of each re-parsing the
|
|
251
|
+
# whole schema set (#341).
|
|
252
|
+
def parse_express_files(file_paths)
|
|
253
|
+
ExpressRepositoryCache.fetch_or_store(
|
|
254
|
+
ExpressRepositoryCache.source_key(file_paths),
|
|
255
|
+
) do
|
|
256
|
+
::Expressir::Express::Parser.from_files(file_paths)
|
|
257
|
+
end
|
|
236
258
|
end
|
|
237
259
|
|
|
238
260
|
# TODO: Refactor this using Suma::SchemaConfig
|
|
@@ -252,7 +274,7 @@ module Metanorma
|
|
|
252
274
|
(schema_yaml_base_path + schema_path).cleanpath.to_s
|
|
253
275
|
end
|
|
254
276
|
|
|
255
|
-
|
|
277
|
+
parse_express_files(file_paths)
|
|
256
278
|
end
|
|
257
279
|
|
|
258
280
|
def parse_document_express_indexes(document, input_lines) # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/MethodLength,Metrics/PerceivedComplexity
|
|
@@ -24,6 +24,8 @@ module Metanorma
|
|
|
24
24
|
"metanorma/plugin/lutaml/express_remarks_decorator"
|
|
25
25
|
autoload :ExpressRemarkAdapter,
|
|
26
26
|
"metanorma/plugin/lutaml/express_remark_adapter"
|
|
27
|
+
autoload :ExpressRepositoryCache,
|
|
28
|
+
"metanorma/plugin/lutaml/express_repository_cache"
|
|
27
29
|
autoload :FileNotFoundError,
|
|
28
30
|
"metanorma/plugin/lutaml/file_not_found_error"
|
|
29
31
|
autoload :Json2TextPreprocessor,
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: metanorma-plugin-lutaml
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.7.
|
|
4
|
+
version: 0.7.63
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ribose Inc.
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-11-
|
|
11
|
+
date: 2026-11-05 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: asciidoctor
|
|
@@ -464,6 +464,7 @@ files:
|
|
|
464
464
|
- lib/metanorma/plugin/lutaml/data2_text_preprocessor.rb
|
|
465
465
|
- lib/metanorma/plugin/lutaml/express_remark_adapter.rb
|
|
466
466
|
- lib/metanorma/plugin/lutaml/express_remarks_decorator.rb
|
|
467
|
+
- lib/metanorma/plugin/lutaml/express_repository_cache.rb
|
|
467
468
|
- lib/metanorma/plugin/lutaml/file_not_found_error.rb
|
|
468
469
|
- lib/metanorma/plugin/lutaml/gc_budget.rb
|
|
469
470
|
- lib/metanorma/plugin/lutaml/json2_text_preprocessor.rb
|