oai_schedules 0.6.0 → 0.8.0
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 +16 -0
- data/examples/dir_schedules/schedule_495607cf-f773-463f-8ee1-77d0f53e0c29.json +38 -0
- data/examples/dir_schedules/schedule_5e344861-806b-4361-98f7-a0be6a5984de.json +38 -0
- data/examples/dir_schedules/schedule_712f46ab-f87f-4db8-b69e-7101d9e2ae61.json +41 -0
- data/examples/dir_schedules/schedule_99922363-5b37-4438-a274-5a4a5167f811.json +62 -0
- data/examples/dir_schedules/schedule_dc34623d-2ae2-4e90-91d8-26f4ba29a056.json +1 -2
- data/examples/dir_schedules/schedule_sample.json +4 -3
- data/examples/example_01.rb +2 -1
- data/examples/example_02.rb +2 -1
- data/lib/oai_schedules/manager.rb +131 -48
- data/lib/oai_schedules/version.rb +1 -1
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 86d2572fbf72c1d75ab9b83efcbb739726962127953458f438cf5ac20278997d
|
4
|
+
data.tar.gz: b4fe62d6a8280e9bd55c2337d10615768808d0d5ccbeef469a8ad4a7a55b0b05
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1294b5a37cf3d9ef098c5d1484d1853e5c5990148348b735c7a22809cbab963c1d22e1fae8b3ab525107a21368483ac8eb600f954293dde41a6039db4fed6097
|
7
|
+
data.tar.gz: bc8a60e47cd6f1778483556e644362e976b97456b5c30ae6c320b526b55958e2852011c002c3268afd15c003f835a03b847d0a9173f4590e418ccfece198f447
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,19 @@
|
|
1
|
+
## [0.8.0] - 2025-07-10
|
2
|
+
|
3
|
+
- Complete harvesting is now within a single thread tick
|
4
|
+
- Added more info in the schedule state
|
5
|
+
|
6
|
+
## [0.7.0] - 2025-07-09
|
7
|
+
|
8
|
+
- Partial harvest policy changed: avoid using resumption tokens
|
9
|
+
(adds complication due to expiration time), and change "from" query param
|
10
|
+
as datestamp of the most recent record fetched + eps (from granularity)
|
11
|
+
- Bugfix: "from" and "to" query params now have correct format based on granularity
|
12
|
+
- Better exceptions management
|
13
|
+
- Some cleanup and sparse bugfixes
|
14
|
+
- Added more sample schedules
|
15
|
+
- Added more info in the schedule state
|
16
|
+
|
1
17
|
## [0.4.0] - 2025-03-28
|
2
18
|
|
3
19
|
- Added logger to digestion function
|
@@ -0,0 +1,38 @@
|
|
1
|
+
{
|
2
|
+
"interval": "PT5S",
|
3
|
+
"repository": {
|
4
|
+
"uri": "https://opac.amsab.be/OAI/Server",
|
5
|
+
"repository_name": "Amsab Online Catalog",
|
6
|
+
"protocol_version": "2.0",
|
7
|
+
"admin_email": [
|
8
|
+
"help@amsab.be"
|
9
|
+
],
|
10
|
+
"earliest_datestamp": "2000-01-01T00:00:00+00:00",
|
11
|
+
"deleted_records": "transient",
|
12
|
+
"granularity": "YYYY-MM-DDThh:mm:ssZ",
|
13
|
+
"metadata_format": [
|
14
|
+
"oai_dc",
|
15
|
+
"marc21"
|
16
|
+
],
|
17
|
+
"set": [
|
18
|
+
"collection"
|
19
|
+
],
|
20
|
+
"id": "490cac7921d1801e6d398aa09bca3ef8f51d07e7dae7cc25676d1ea94126483f"
|
21
|
+
},
|
22
|
+
"active": true,
|
23
|
+
"transformer": {
|
24
|
+
"transformer_name": [
|
25
|
+
"dummy_transformer"
|
26
|
+
],
|
27
|
+
"type": {
|
28
|
+
"id": "bb8bfd5d-d914-41ae-b9f1-b5065299d9b9",
|
29
|
+
"value": "dummy_type"
|
30
|
+
},
|
31
|
+
"uri": "http://dummy-uri.org/",
|
32
|
+
"id": "dd377ec0-c890-4635-b6d8-553ddf609c01"
|
33
|
+
},
|
34
|
+
"format": "oai_dc",
|
35
|
+
"set": "collection",
|
36
|
+
"from": "2000-01-01T00:00:00+00:00",
|
37
|
+
"id": "495607cf-f773-463f-8ee1-77d0f53e0c29"
|
38
|
+
}
|
@@ -0,0 +1,38 @@
|
|
1
|
+
{
|
2
|
+
"interval": "PT5S",
|
3
|
+
"repository": {
|
4
|
+
"uri": "https://heron.libis.be/ca_veb_q/admin/service.php/OAI/cw_organisaties/request",
|
5
|
+
"repository_name": "VEB",
|
6
|
+
"protocol_version": "2.0",
|
7
|
+
"admin_email": [
|
8
|
+
"collectiveaccess@vlaamse-erfgoedbibliotheken.be"
|
9
|
+
],
|
10
|
+
"earliest_datestamp": "2020-08-17T12:55:02+00:00",
|
11
|
+
"deleted_records": "transient",
|
12
|
+
"granularity": "YYYY-MM-DDThh:mm:ssZ",
|
13
|
+
"metadata_format": [
|
14
|
+
"oai_dc",
|
15
|
+
"oai_veb"
|
16
|
+
],
|
17
|
+
"set": [
|
18
|
+
"1"
|
19
|
+
],
|
20
|
+
"id": "4886e3793003d2b1dffbbdb41ca13024c7c809892314ab301ded0d7ecfd7b469"
|
21
|
+
},
|
22
|
+
"active": true,
|
23
|
+
"transformer": {
|
24
|
+
"transformer_name": [
|
25
|
+
"dummy_transformer"
|
26
|
+
],
|
27
|
+
"type": {
|
28
|
+
"id": "bb8bfd5d-d914-41ae-b9f1-b5065299d9b9",
|
29
|
+
"value": "dummy_type"
|
30
|
+
},
|
31
|
+
"uri": "http://dummy-uri.org/",
|
32
|
+
"id": "dd377ec0-c890-4635-b6d8-553ddf609c01"
|
33
|
+
},
|
34
|
+
"format": "oai_dc",
|
35
|
+
"set": "1",
|
36
|
+
"from": "2025-06-10T12:39:00+00:00",
|
37
|
+
"id": "5e344861-806b-4361-98f7-a0be6a5984de"
|
38
|
+
}
|
@@ -0,0 +1,41 @@
|
|
1
|
+
{
|
2
|
+
"interval": "PT5S",
|
3
|
+
"repository": {
|
4
|
+
"uri": "http://lag.hosting.deventit.net/atlantispubliek/oai.axd",
|
5
|
+
"repository_name": "Liberas",
|
6
|
+
"protocol_version": "2.0",
|
7
|
+
"admin_email": [
|
8
|
+
"support@deventit.nl"
|
9
|
+
],
|
10
|
+
"earliest_datestamp": "1900-01-01T01:01:01+00:00",
|
11
|
+
"deleted_records": "persistent",
|
12
|
+
"granularity": "YYYY-MM-DDThh:mm:ssZ",
|
13
|
+
"metadata_format": [
|
14
|
+
"APEX",
|
15
|
+
"EAC",
|
16
|
+
"EAD"
|
17
|
+
],
|
18
|
+
"set": [
|
19
|
+
"APEX",
|
20
|
+
"APEXAO",
|
21
|
+
"EAC",
|
22
|
+
"EAD"
|
23
|
+
],
|
24
|
+
"id": "93b6d240ac9b782664f18823b761a128fc19116506dd228763b52ba8fb64e1b9"
|
25
|
+
},
|
26
|
+
"active": true,
|
27
|
+
"transformer": {
|
28
|
+
"transformer_name": [
|
29
|
+
"dummy_transformer"
|
30
|
+
],
|
31
|
+
"type": {
|
32
|
+
"id": "bb8bfd5d-d914-41ae-b9f1-b5065299d9b9",
|
33
|
+
"value": "dummy_type"
|
34
|
+
},
|
35
|
+
"uri": "http://dummy-uri.org/",
|
36
|
+
"id": "dd377ec0-c890-4635-b6d8-553ddf609c01"
|
37
|
+
},
|
38
|
+
"format": "EAD",
|
39
|
+
"set": "EAD",
|
40
|
+
"id": "712f46ab-f87f-4db8-b69e-7101d9e2ae61"
|
41
|
+
}
|
@@ -0,0 +1,62 @@
|
|
1
|
+
{
|
2
|
+
"interval": "PT5S",
|
3
|
+
"repository": {
|
4
|
+
"uri": "https://eudml.org/oai/OAIHandler",
|
5
|
+
"repository_name": "REPOX Repository",
|
6
|
+
"protocol_version": "2.0",
|
7
|
+
"admin_email": [
|
8
|
+
"mailto:gilberto.pedrosa@ist.utl.pt"
|
9
|
+
],
|
10
|
+
"earliest_datestamp": "1970-01-01T00:00:00+00:00",
|
11
|
+
"deleted_records": "persistent",
|
12
|
+
"granularity": "YYYY-MM-DD",
|
13
|
+
"metadata_format": [
|
14
|
+
"oai_dc",
|
15
|
+
"ese",
|
16
|
+
"eudml-article2",
|
17
|
+
"eudml-book2"
|
18
|
+
],
|
19
|
+
"set": [
|
20
|
+
"BDIM",
|
21
|
+
"BulDML",
|
22
|
+
"CEDRAM",
|
23
|
+
"DMLE",
|
24
|
+
"DML_CZ_Monograph",
|
25
|
+
"DML_CZ_Proceeding",
|
26
|
+
"DML_CZ_Serial",
|
27
|
+
"EDPS",
|
28
|
+
"ELibM",
|
29
|
+
"GALLICA",
|
30
|
+
"GDZ_Band",
|
31
|
+
"GDZ_Mathematica",
|
32
|
+
"GDZ_Monographs",
|
33
|
+
"GDZ_RusDML",
|
34
|
+
"HDML_Books",
|
35
|
+
"HDML_Conferences",
|
36
|
+
"HDML_Journals",
|
37
|
+
"MISANU",
|
38
|
+
"NUMDAM",
|
39
|
+
"NUMDAM_book",
|
40
|
+
"PLDML",
|
41
|
+
"PLDML_book",
|
42
|
+
"PMath"
|
43
|
+
],
|
44
|
+
"id": "02df523af427deb93b7cb4600ca347f9297d0e31d51c2783c634459dac457bd0"
|
45
|
+
},
|
46
|
+
"active": true,
|
47
|
+
"transformer": {
|
48
|
+
"transformer_name": [
|
49
|
+
"dummy_transformer"
|
50
|
+
],
|
51
|
+
"type": {
|
52
|
+
"id": "b1671aad-e825-4b5a-b50b-d8591b425e2a",
|
53
|
+
"value": "dummy_type"
|
54
|
+
},
|
55
|
+
"uri": "http://dummy-uri.org/",
|
56
|
+
"id": "7889ce03-28d9-479d-bb9a-b239f179453a"
|
57
|
+
},
|
58
|
+
"format": "oai_dc",
|
59
|
+
"set": "CEDRAM",
|
60
|
+
"from": "1970-01-01T00:00:00+00:00",
|
61
|
+
"id": "99922363-5b37-4438-a274-5a4a5167f811"
|
62
|
+
}
|
@@ -1,5 +1,5 @@
|
|
1
1
|
{
|
2
|
-
"interval": "
|
2
|
+
"interval": "PT5S",
|
3
3
|
"repository": {
|
4
4
|
"uri": "https://eudml.org/oai/OAIHandler",
|
5
5
|
"repository_name": "REPOX Repository",
|
@@ -58,6 +58,5 @@
|
|
58
58
|
"format": "oai_dc",
|
59
59
|
"set": "CEDRAM",
|
60
60
|
"from": "1970-01-01T00:00:00+00:00",
|
61
|
-
"until": "1999-01-12T09:43:02+00:00",
|
62
61
|
"id": "dc34623d-2ae2-4e90-91d8-26f4ba29a056"
|
63
62
|
}
|
@@ -1,10 +1,11 @@
|
|
1
1
|
{
|
2
|
-
"interval": "
|
2
|
+
"interval": "PT5S",
|
3
3
|
"active": true,
|
4
4
|
"repository": {
|
5
|
-
"uri": "https://eu.alma.exlibrisgroup.com/view/oai/32KUL_KUL/request"
|
5
|
+
"uri": "https://eu.alma.exlibrisgroup.com/view/oai/32KUL_KUL/request",
|
6
|
+
"granularity": "YYYY-MM-DDThh:mm:ssZ"
|
6
7
|
},
|
7
8
|
"format": "marc21",
|
8
9
|
"set": "KUL_Rapid_Journals_Print_LendableInternational",
|
9
|
-
"from": "
|
10
|
+
"from": "2024-03-01T00:00:00Z"
|
10
11
|
}
|
data/examples/example_01.rb
CHANGED
@@ -9,8 +9,9 @@ f_show = lambda do |name, content, records, done, error, state, logger|
|
|
9
9
|
# ... do your stuff with records ...
|
10
10
|
else
|
11
11
|
puts error.message
|
12
|
+
puts error.backtrace
|
12
13
|
end
|
13
|
-
puts state
|
14
|
+
puts JSON.pretty_generate(state)
|
14
15
|
if done
|
15
16
|
puts "done full harvesting"
|
16
17
|
end
|
data/examples/example_02.rb
CHANGED
@@ -9,8 +9,9 @@ f_show = lambda do |name, content, records, done, error, state, logger|
|
|
9
9
|
# ... do your stuff with records ...
|
10
10
|
else
|
11
11
|
puts error.message
|
12
|
+
puts error.backtrace
|
12
13
|
end
|
13
|
-
puts state
|
14
|
+
puts JSON.pretty_generate(state)
|
14
15
|
if done
|
15
16
|
puts "done full harvesting"
|
16
17
|
end
|
@@ -7,7 +7,7 @@ require 'concurrent-ruby'
|
|
7
7
|
require 'logger'
|
8
8
|
require 'data_collector'
|
9
9
|
require 'iso8601'
|
10
|
-
|
10
|
+
require 'date'
|
11
11
|
|
12
12
|
|
13
13
|
|
@@ -229,19 +229,25 @@ module OAISchedules
|
|
229
229
|
|
230
230
|
def init_schedule_state(state)
|
231
231
|
state["resumption_token"] = nil
|
232
|
+
state["expiration_date_resumption_token"] = nil
|
233
|
+
state["datetime_now"] = get_datetime_now
|
234
|
+
state["datetime_next_harvesting"] = nil
|
232
235
|
state["count_success"] = 0
|
233
236
|
state["count_fails"] = 0
|
234
237
|
state["done"] = false
|
235
238
|
state["count_harvested_records"] = 0
|
236
|
-
state["latest_harvested_records_datestamp"] =
|
239
|
+
state["latest_harvested_records_datestamp"] = nil
|
240
|
+
state["harvesting"] = false
|
241
|
+
state["error"] = nil
|
237
242
|
end
|
238
243
|
|
239
244
|
|
240
245
|
def handle_schedule_state_at_schedule_change(name, content)
|
241
|
-
# invalidate resumption token if either schedule format or set changes
|
242
246
|
state = @schedules[name][:state]
|
243
247
|
if (content["format"] != @schedules[name][:content]["format"]) \
|
244
|
-
|| (content["set"] != @schedules[name][:content]["set"])
|
248
|
+
|| (content["set"] != @schedules[name][:content]["set"]) \
|
249
|
+
|| (content["from"] != @schedules[name][:content]["from"]) \
|
250
|
+
|| (content["until"] != @schedules[name][:content]["until"])
|
245
251
|
init_schedule_state(state)
|
246
252
|
end
|
247
253
|
end
|
@@ -256,8 +262,7 @@ module OAISchedules
|
|
256
262
|
task = @schedules[name][:task]
|
257
263
|
interval_s_safe = 60
|
258
264
|
begin
|
259
|
-
|
260
|
-
interval_s = duration.to_seconds
|
265
|
+
interval_s = interval_iso8601_to_seconds(@schedules[name][:content]["interval"])
|
261
266
|
@logger.info("#{name}: task interval (s): #{interval_s}")
|
262
267
|
th_interval_s = 0.1 # protects from negative, 0 or small time intervals
|
263
268
|
if interval_s < th_interval_s
|
@@ -335,7 +340,9 @@ module OAISchedules
|
|
335
340
|
|
336
341
|
|
337
342
|
def logic(name, content, state_machine, state)
|
343
|
+
state["datetime_next_harvesting"] = get_datetime_next_schedule_tick_from_now(content["interval"])
|
338
344
|
loop do
|
345
|
+
# sleep(3)
|
339
346
|
@logger.info("#{name}: handling state: #{state_machine.state}")
|
340
347
|
case state_machine.state
|
341
348
|
when StateHarvesting::NOT_IDENTIFIED
|
@@ -347,40 +354,31 @@ module OAISchedules
|
|
347
354
|
)
|
348
355
|
state["identify"] = data
|
349
356
|
state_machine.add_event(EventHarvesting::DONE_IDENTIFY)
|
350
|
-
break
|
351
357
|
when StateHarvesting::IDLE
|
352
358
|
state_machine.add_event(EventHarvesting::REQUEST_HARVEST)
|
353
359
|
when StateHarvesting::HARVESTING
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
format = ""
|
371
|
-
from = ""
|
372
|
-
to = ""
|
373
|
-
set = ""
|
374
|
-
resumption_token = state["resumption_token"]
|
360
|
+
use_resumption_token = false # don't change
|
361
|
+
state["harvesting"] = true
|
362
|
+
format = content["format"] || ""
|
363
|
+
fmt_dt = content.dig("repository", "granularity")
|
364
|
+
from = convert_datetime(content["from"], fmt_dt) || ""
|
365
|
+
to = convert_datetime(content["until"], fmt_dt) || ""
|
366
|
+
set = content["set"] || ""
|
367
|
+
resumption_token = ""
|
368
|
+
if use_resumption_token
|
369
|
+
if !state["resumption_token"].nil?
|
370
|
+
format = ""
|
371
|
+
from = ""
|
372
|
+
to = ""
|
373
|
+
set = ""
|
374
|
+
resumption_token = state["resumption_token"]
|
375
|
+
end
|
375
376
|
else
|
376
|
-
|
377
|
-
from = content["from"] || ""
|
378
|
-
to = content["until"] || ""
|
379
|
-
set = content["set"] || ""
|
380
|
-
resumption_token = ""
|
377
|
+
from = add_eps_to_datetime(state["latest_harvested_records_datestamp"], fmt_dt) || from
|
381
378
|
end
|
382
379
|
data = nil
|
383
380
|
error = nil
|
381
|
+
to_pause = true
|
384
382
|
done = false
|
385
383
|
if state["done"]
|
386
384
|
state_machine.add_event(EventHarvesting::DONE_FULL_HARVEST)
|
@@ -396,36 +394,60 @@ module OAISchedules
|
|
396
394
|
set,
|
397
395
|
resumption_token
|
398
396
|
)
|
399
|
-
state["resumption_token"] =
|
400
|
-
state["
|
397
|
+
state["resumption_token"] = nil
|
398
|
+
state["expiration_date_resumption_token"] = nil
|
399
|
+
if use_resumption_token
|
400
|
+
if data["resumptionToken"].is_a?(String)
|
401
|
+
state["resumption_token"] = data["resumptionToken"]
|
402
|
+
elsif data["resumptionToken"].is_a?(Hash)
|
403
|
+
data_token = data["resumptionToken"]
|
404
|
+
state["resumption_token"] = data_token["$text"]
|
405
|
+
state["expiration_date_resumption_token"] = data_token["_expirationDate"]
|
406
|
+
end
|
407
|
+
end
|
401
408
|
n_records = data["record"].size
|
402
409
|
state["count_harvested_records"] += n_records
|
403
410
|
if n_records > 0
|
404
411
|
timestamps = data["record"].map do |record|
|
405
412
|
record["header"]["datestamp"]
|
406
413
|
end.sort
|
407
|
-
|
414
|
+
timestamp_latest = timestamps[-1].strftime('%FT%TZ')
|
415
|
+
state["latest_harvested_records_datestamp"] = convert_datetime(timestamp_latest, fmt_dt)
|
408
416
|
end
|
417
|
+
state["count_success"] += 1
|
409
418
|
rescue StandardError => e
|
410
419
|
state["count_fails"] += 1
|
411
420
|
error = e
|
412
421
|
end
|
413
422
|
if error.nil?
|
414
|
-
|
415
|
-
|
416
|
-
|
423
|
+
state["error"] = nil
|
424
|
+
if use_resumption_token
|
425
|
+
if state["resumption_token"].nil?
|
426
|
+
state_machine.add_event(EventHarvesting::DONE_HARVEST)
|
427
|
+
to_pause = true
|
428
|
+
else
|
429
|
+
to_pause = false
|
430
|
+
end
|
417
431
|
else
|
418
|
-
|
419
|
-
done = true
|
432
|
+
to_pause = false
|
420
433
|
end
|
434
|
+
else
|
435
|
+
state["error"] = {
|
436
|
+
"message" => error.message,
|
437
|
+
"backtrace" => error.backtrace
|
438
|
+
}
|
439
|
+
state_machine.add_event(EventHarvesting::DONE_HARVEST)
|
440
|
+
to_pause = true
|
421
441
|
end
|
422
442
|
state["done"] = done
|
443
|
+
state["harvesting"] = !to_pause
|
444
|
+
state["datetime_now"] = get_datetime_now
|
423
445
|
end
|
424
446
|
path_file_state = get_path_state_file_from_schedule_name(name)
|
425
447
|
@logger.info("#{name}: writing to state file #{path_file_state}")
|
426
448
|
write_state_file(path_file_state, state)
|
427
449
|
@f_digest&.call(name, content, data, done, error, state, @logger)
|
428
|
-
break
|
450
|
+
break if to_pause
|
429
451
|
when StateHarvesting::COMPLETE
|
430
452
|
@logger.warn("#{name}: full harvesting complete")
|
431
453
|
content["active"] = false
|
@@ -443,11 +465,19 @@ module OAISchedules
|
|
443
465
|
verb = "Identify"
|
444
466
|
url_query = "#{url_base}?verb=#{verb}"
|
445
467
|
@logger.info("#{name}: fetching from #{url_query}")
|
446
|
-
|
468
|
+
input = DataCollector::Input.new.from_uri(url_query)
|
469
|
+
if input.nil?
|
470
|
+
raise StandardError, "#{url_query}, service not found"
|
471
|
+
end
|
472
|
+
data = DataCollector::Core.filter(input, "$..#{verb}")
|
447
473
|
if data.empty?
|
448
|
-
|
474
|
+
error = DataCollector::Core.filter(input, "$..error")
|
475
|
+
error = error[0]
|
476
|
+
name_error = error['_code']
|
477
|
+
text_error = error['$text']
|
478
|
+
raise StandardError, "#{name}: #{url_query}: #{name_error}, #{text_error}"
|
449
479
|
end
|
450
|
-
data
|
480
|
+
data[0]
|
451
481
|
rescue DataCollector::InputError => e
|
452
482
|
raise RuntimeError, "#{name}: #{url_query} not found, or server error"
|
453
483
|
rescue StandardError => e
|
@@ -474,11 +504,22 @@ module OAISchedules
|
|
474
504
|
url_query += "&resumptionToken=#{resumption_token}"
|
475
505
|
end
|
476
506
|
@logger.info("#{name}: fetching from #{url_query}")
|
477
|
-
|
507
|
+
input = DataCollector::Input.new.from_uri(url_query)
|
508
|
+
if input.nil?
|
509
|
+
raise StandardError, "#{url_query}, service not found"
|
510
|
+
end
|
511
|
+
data = DataCollector::Core.filter(input, "$..#{verb}")
|
478
512
|
if data.empty?
|
479
|
-
|
513
|
+
error = DataCollector::Core.filter(input, "$..error")
|
514
|
+
error = error[0]
|
515
|
+
name_error = error['_code']
|
516
|
+
text_error = error['$text']
|
517
|
+
raise StandardError, "#{name}: #{url_query}: #{name_error}, #{text_error}"
|
480
518
|
end
|
481
|
-
|
519
|
+
if data.compact.empty?
|
520
|
+
raise StandardError, "#{name}: #{url_query}: no records found"
|
521
|
+
end
|
522
|
+
data[0]
|
482
523
|
rescue DataCollector::InputError => e
|
483
524
|
raise RuntimeError, "#{name}: #{url_query} not found, or server error"
|
484
525
|
rescue StandardError => e
|
@@ -511,6 +552,48 @@ module OAISchedules
|
|
511
552
|
modify_schedule(name_schedule, content_schedule)
|
512
553
|
end
|
513
554
|
|
555
|
+
def convert_datetime(str_dt, fmt_dt)
|
556
|
+
return nil unless str_dt
|
557
|
+
return str_dt unless fmt_dt
|
558
|
+
dt = DateTime.parse(str_dt)
|
559
|
+
case fmt_dt
|
560
|
+
when 'YYYY-MM-DD'
|
561
|
+
dt.strftime('%F')
|
562
|
+
when 'YYYY-MM-DDThh:mm:ssZ'
|
563
|
+
dt.strftime('%FT%TZ')
|
564
|
+
else
|
565
|
+
str_dt
|
566
|
+
end
|
567
|
+
end
|
568
|
+
|
569
|
+
def add_eps_to_datetime(str_dt, fmt_dt)
|
570
|
+
return nil unless str_dt
|
571
|
+
dt = DateTime.parse(str_dt)
|
572
|
+
case fmt_dt
|
573
|
+
when 'YYYY-MM-DD'
|
574
|
+
dt += 1.0
|
575
|
+
dt.strftime('%F')
|
576
|
+
when 'YYYY-MM-DDThh:mm:ssZ'
|
577
|
+
dt += 1.0/(24*60*60)
|
578
|
+
dt.strftime('%FT%TZ')
|
579
|
+
end
|
580
|
+
end
|
581
|
+
|
582
|
+
def get_datetime_now
|
583
|
+
DateTime.now.strftime('%FT%TZ')
|
584
|
+
end
|
585
|
+
|
586
|
+
def interval_iso8601_to_seconds(str_interval)
|
587
|
+
ISO8601::Duration.new(str_interval).to_seconds
|
588
|
+
end
|
589
|
+
|
590
|
+
def get_datetime_next_schedule_tick_from_now(str_interval)
|
591
|
+
interval_s = interval_iso8601_to_seconds(str_interval)
|
592
|
+
dt = DateTime.now
|
593
|
+
dt += 1.0*interval_s/(24*60*60)
|
594
|
+
dt.strftime('%FT%TZ')
|
595
|
+
end
|
596
|
+
|
514
597
|
end
|
515
598
|
|
516
599
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: oai_schedules
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.8.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Davide Monari
|
8
8
|
bindir: exe
|
9
9
|
cert_chain: []
|
10
|
-
date: 2025-
|
10
|
+
date: 2025-07-10 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
13
|
name: concurrent-ruby
|
@@ -78,6 +78,10 @@ files:
|
|
78
78
|
- LICENSE.txt
|
79
79
|
- README.md
|
80
80
|
- Rakefile
|
81
|
+
- examples/dir_schedules/schedule_495607cf-f773-463f-8ee1-77d0f53e0c29.json
|
82
|
+
- examples/dir_schedules/schedule_5e344861-806b-4361-98f7-a0be6a5984de.json
|
83
|
+
- examples/dir_schedules/schedule_712f46ab-f87f-4db8-b69e-7101d9e2ae61.json
|
84
|
+
- examples/dir_schedules/schedule_99922363-5b37-4438-a274-5a4a5167f811.json
|
81
85
|
- examples/dir_schedules/schedule_dc34623d-2ae2-4e90-91d8-26f4ba29a056.json
|
82
86
|
- examples/dir_schedules/schedule_sample.json
|
83
87
|
- examples/dir_state/.gitkeep
|