fair_champion_harvester 0.1.16 → 0.1.17
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/CHANGELOG.md +6 -0
- data/lib/cache.rb +65 -2
- data/lib/fair_champion_harvester/version.rb +1 -1
- data/lib/harvester.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f36986c04c73a293f76a80e6415296024153b1c2c756bd8777f67d17c05e0a32
|
|
4
|
+
data.tar.gz: c2e22acdc3c74da575c380e9eb9f7be40b0594f6a78525ead0ff39d3fdf3149f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7e8075969817d032ca9e84dfe02260981eb78043390ddfdb415019ea102e1aa549b9828d68b13661e34f3c83f2da32f1b89a2e2091f4ab9dec6d98e47d68e389
|
|
7
|
+
data.tar.gz: 223e4cf7c16da80ba9b2756db342c2398e97cf7f05b31169add185c4a4f5e331663502a6fd0e1e89114b9ba8d42c9f8b9776b32b58aaff0b69a273790bf6396a
|
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [0.1.17] - 2026-08-11
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
|
|
9
|
+
- `Cache.checkCache` and `Cache.checkRDFCache` (`lib/cache.rb`) never expired anything — once a `/tmp/<md5>_*` entry was written, `harvester.rb#fetch` returned it forever, since `/tmp` inside the `communitytests` container is not a persistent volume and the only ways to clear a stale entry were a full container restart or manually deleting files over SSH. Added a `cached_at` timestamp file per entry (and per RDF graph cache entry) plus a TTL check on read, configurable via `CACHE_TTL` (default 300s / 5 minutes — short by design, since harvested DCAT/TTL records under test change frequently and testers need to see edits reflected quickly, unlike FDP-Index-Proxy's 24h `FDP_CACHE_TTL`). Also added `Cache.purge(uri, headers)` to force-evict a specific entry without waiting for TTL expiry.
|
|
10
|
+
|
|
5
11
|
## [0.1.16] - 2026-08-05
|
|
6
12
|
|
|
7
13
|
### Fixed
|
data/lib/cache.rb
CHANGED
|
@@ -4,14 +4,34 @@ module FAIRChampionHarvester
|
|
|
4
4
|
################### CACHE FUNCTIONS #####################
|
|
5
5
|
################### #####################################
|
|
6
6
|
|
|
7
|
+
# Cache time-to-live in seconds. Configurable via the +CACHE_TTL+ env
|
|
8
|
+
# var; defaults to 5 minutes (short by design, unlike FDP-Index-Proxy's
|
|
9
|
+
# 24h FDP_CACHE_TTL, since harvested DCAT/TTL records under test change
|
|
10
|
+
# frequently and testers need to see edits reflected quickly).
|
|
11
|
+
CACHE_TTL = (ENV.fetch("CACHE_TTL", 300)).to_i
|
|
12
|
+
|
|
13
|
+
def self.expired?(timestamp_file)
|
|
14
|
+
return true unless File.exist?(timestamp_file)
|
|
15
|
+
|
|
16
|
+
age = Time.now - Marshal.load(File.read(timestamp_file))
|
|
17
|
+
age > CACHE_TTL
|
|
18
|
+
end
|
|
19
|
+
|
|
7
20
|
def self.checkRDFCache(body)
|
|
8
21
|
g = RDF::Graph.new
|
|
9
22
|
key = Digest::MD5.hexdigest body
|
|
10
23
|
graph_file = "/tmp/#{key}_graph"
|
|
11
24
|
body_file = "/tmp/#{key}_graphbody"
|
|
25
|
+
time_file = "/tmp/#{key}_graphtime"
|
|
12
26
|
|
|
13
27
|
return g unless File.exist?(graph_file) && File.exist?(body_file)
|
|
14
28
|
|
|
29
|
+
if expired?(time_file)
|
|
30
|
+
warn "RDF Cache File #{key} EXPIRED"
|
|
31
|
+
purgeRDFFiles(key)
|
|
32
|
+
return g
|
|
33
|
+
end
|
|
34
|
+
|
|
15
35
|
warn "RDF Cache File #{key} FOUND"
|
|
16
36
|
graph = Marshal.load(File.read(graph_file))
|
|
17
37
|
graph.each { |statement| g << statement }
|
|
@@ -26,17 +46,33 @@ module FAIRChampionHarvester
|
|
|
26
46
|
warn "WRITING RDF TO CACHE #{filename}"
|
|
27
47
|
File.binwrite("/tmp/#{filename}_graph", Marshal.dump(graph))
|
|
28
48
|
File.binwrite("/tmp/#{filename}_graphbody", body)
|
|
49
|
+
File.binwrite("/tmp/#{filename}_graphtime", Marshal.dump(Time.now))
|
|
29
50
|
warn "wrote RDF filename: #{filename}"
|
|
30
51
|
end
|
|
31
52
|
|
|
32
53
|
def self.checkCache(uri, headers)
|
|
33
54
|
filename = Digest::MD5.hexdigest uri + headers.to_s
|
|
55
|
+
time_file = "/tmp/#{filename}_time"
|
|
34
56
|
warn "Checking Error cache for #{filename}"
|
|
57
|
+
|
|
35
58
|
if File.exist?("/tmp/#{filename}_error")
|
|
36
|
-
|
|
37
|
-
|
|
59
|
+
if expired?(time_file)
|
|
60
|
+
warn "Error cache file #{filename} EXPIRED"
|
|
61
|
+
purgeFiles(filename)
|
|
62
|
+
else
|
|
63
|
+
warn "Error file found in cache... returning"
|
|
64
|
+
return ["ERROR", nil, [uri]]
|
|
65
|
+
end
|
|
38
66
|
end
|
|
67
|
+
|
|
39
68
|
if File.exist?("/tmp/#{filename}_head") and File.exist?("/tmp/#{filename}_body")
|
|
69
|
+
if expired?(time_file)
|
|
70
|
+
warn "Cache #{filename} EXPIRED"
|
|
71
|
+
purgeFiles(filename)
|
|
72
|
+
warn "Not Found in Cache"
|
|
73
|
+
return
|
|
74
|
+
end
|
|
75
|
+
|
|
40
76
|
warn "FOUND data in cache"
|
|
41
77
|
head = Marshal.load(File.read("/tmp/#{filename}_head"))
|
|
42
78
|
body = Marshal.load(File.read("/tmp/#{filename}_body"))
|
|
@@ -54,15 +90,42 @@ module FAIRChampionHarvester
|
|
|
54
90
|
headfilename = filename + "_head"
|
|
55
91
|
bodyfilename = filename + "_body"
|
|
56
92
|
urifilename = filename + "_uri"
|
|
93
|
+
timefilename = filename + "_time"
|
|
57
94
|
File.binwrite("/tmp/#{headfilename}", Marshal.dump(head))
|
|
58
95
|
File.binwrite("/tmp/#{bodyfilename}", Marshal.dump(body))
|
|
59
96
|
File.binwrite("/tmp/#{urifilename}", Marshal.dump(finalURI))
|
|
97
|
+
File.binwrite("/tmp/#{timefilename}", Marshal.dump(Time.now))
|
|
60
98
|
end
|
|
61
99
|
|
|
62
100
|
def self.writeErrorToCache(uri, headers)
|
|
63
101
|
filename = Digest::MD5.hexdigest uri + headers.to_s
|
|
64
102
|
warn "in writeErrorToCache Writing error to cache for #{filename}"
|
|
65
103
|
File.binwrite("/tmp/#{filename}_error", "ERROR")
|
|
104
|
+
File.binwrite("/tmp/#{filename}_time", Marshal.dump(Time.now))
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# Force-evicts the cache entry (data and/or error) for a given uri+headers,
|
|
108
|
+
# regardless of TTL. Use this to bypass a stale or bad cached result
|
|
109
|
+
# without waiting for CACHE_TTL to elapse or restarting the container.
|
|
110
|
+
def self.purge(uri, headers)
|
|
111
|
+
filename = Digest::MD5.hexdigest uri + headers.to_s
|
|
112
|
+
purgeFiles(filename)
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def self.purgeFiles(filename)
|
|
116
|
+
%w[_head _body _uri _error _time].each do |suffix|
|
|
117
|
+
path = "/tmp/#{filename}#{suffix}"
|
|
118
|
+
File.delete(path) if File.exist?(path)
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
private_class_method :purgeFiles
|
|
122
|
+
|
|
123
|
+
def self.purgeRDFFiles(key)
|
|
124
|
+
%w[_graph _graphbody _graphtime].each do |suffix|
|
|
125
|
+
path = "/tmp/#{key}#{suffix}"
|
|
126
|
+
File.delete(path) if File.exist?(path)
|
|
127
|
+
end
|
|
66
128
|
end
|
|
129
|
+
private_class_method :purgeRDFFiles
|
|
67
130
|
end
|
|
68
131
|
end
|
data/lib/harvester.rb
CHANGED