toccatore 0.3.9 → 0.4.15
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 +5 -5
- data/Gemfile.lock +76 -54
- data/README.md +1 -1
- data/lib/toccatore/base.rb +15 -4
- data/lib/toccatore/cli.rb +12 -0
- data/lib/toccatore/datacite_related.rb +18 -3
- data/lib/toccatore/orcid_update.rb +6 -2
- data/lib/toccatore/queue.rb +56 -0
- data/lib/toccatore/usage_update.rb +183 -0
- data/lib/toccatore/version.rb +1 -1
- data/lib/toccatore.rb +2 -0
- data/spec/base_spec.rb +4 -4
- data/spec/cli_spec.rb +36 -3
- data/spec/datacite_related_spec.rb +10 -10
- data/spec/factories/default.rb +22 -0
- data/spec/fixtures/event_data_resp_1 +2 -0
- data/spec/fixtures/event_data_resp_2 +4 -0
- data/spec/fixtures/events_empty.json +33 -0
- data/spec/fixtures/usage_event.json +1 -0
- data/spec/fixtures/usage_event_fail.json +17 -0
- data/spec/fixtures/usage_events.json +63 -0
- data/spec/fixtures/usage_update.json +101 -0
- data/spec/fixtures/usage_update_1.json +36738 -0
- data/spec/fixtures/usage_update_2.json +171 -0
- data/spec/fixtures/usage_update_3.json +176 -0
- data/spec/fixtures/usage_update_4.json +101 -0
- data/spec/fixtures/usage_update_nil.json +6 -0
- data/spec/fixtures/vcr_cassettes/Toccatore_Base/get_doi_ra/crossref.yml +21 -45
- data/spec/fixtures/vcr_cassettes/Toccatore_Base/get_doi_ra/datacite.yml +23 -47
- data/spec/fixtures/vcr_cassettes/Toccatore_Base/send_notification_to_slack/datacite_related.yml +14 -12
- data/spec/fixtures/vcr_cassettes/Toccatore_Base/send_notification_to_slack/datacite_related_no_works.yml +15 -13
- data/spec/fixtures/vcr_cassettes/Toccatore_Base/send_notification_to_slack/orcid_update.yml +14 -12
- data/spec/fixtures/vcr_cassettes/Toccatore_Base/send_notification_to_slack/orcid_update_no_works.yml +15 -13
- data/spec/fixtures/vcr_cassettes/Toccatore_CLI/datacite_related/should_fail.yml +345 -852
- data/spec/fixtures/vcr_cassettes/Toccatore_CLI/datacite_related/should_query_by_DOI.yml +327 -409
- data/spec/fixtures/vcr_cassettes/Toccatore_CLI/datacite_related/should_query_by_related_identifier.yml +140 -117
- data/spec/fixtures/vcr_cassettes/Toccatore_CLI/datacite_related/should_succeed.yml +1267 -2068
- data/spec/fixtures/vcr_cassettes/Toccatore_CLI/datacite_related/should_succeed_with_no_works.yml +31 -25
- data/spec/fixtures/vcr_cassettes/Toccatore_CLI/orcid_update/should_fail.yml +47 -39
- data/spec/fixtures/vcr_cassettes/Toccatore_CLI/orcid_update/should_query_by_DOI.yml +673 -855
- data/spec/fixtures/vcr_cassettes/Toccatore_CLI/orcid_update/should_query_by_ORCID_ID.yml +1885 -2419
- data/spec/fixtures/vcr_cassettes/Toccatore_CLI/orcid_update/should_succeed.yml +1555 -1991
- data/spec/fixtures/vcr_cassettes/Toccatore_CLI/orcid_update/should_succeed_with_no_works.yml +31 -27
- data/spec/fixtures/vcr_cassettes/Toccatore_CLI/usage_update/no_reports_in_the_queue/should_succeed_with_no_works.yml +196 -0
- data/spec/fixtures/vcr_cassettes/Toccatore_DataciteRelated/get_data/should_allow_queries_by_DOI_of_the_Datacite_Metadata_Search_API.yml +16 -12
- data/spec/fixtures/vcr_cassettes/Toccatore_DataciteRelated/get_data/should_allow_queries_by_related_identifier_of_the_Datacite_Metadata_Search_API.yml +17 -13
- data/spec/fixtures/vcr_cassettes/Toccatore_DataciteRelated/get_data/should_report_if_there_are_no_works_returned_by_the_Datacite_Metadata_Search_API.yml +16 -12
- data/spec/fixtures/vcr_cassettes/Toccatore_DataciteRelated/get_data/should_report_if_there_are_works_returned_by_the_Datacite_Metadata_Search_API.yml +16 -14
- data/spec/fixtures/vcr_cassettes/Toccatore_DataciteRelated/get_total/with_no_works.yml +15 -11
- data/spec/fixtures/vcr_cassettes/Toccatore_DataciteRelated/get_total/with_works.yml +16 -12
- data/spec/fixtures/vcr_cassettes/Toccatore_DataciteRelated/parse_data/should_report_if_there_are_works_returned_by_the_Datacite_Metadata_Search_API.yml +437 -869
- data/spec/fixtures/vcr_cassettes/Toccatore_DataciteRelated/push_data/should_report_if_there_are_works_returned_by_the_Datacite_Metadata_Search_API.yml +1240 -1662
- data/spec/fixtures/vcr_cassettes/Toccatore_DataciteRelated/push_data/should_work_with_DataCite_Event_Data.yml +4026 -6556
- data/spec/fixtures/vcr_cassettes/Toccatore_OrcidUpdate/get_data/should_allow_queries_by_DOI_of_the_Datacite_Metadata_Search_API.yml +15 -13
- data/spec/fixtures/vcr_cassettes/Toccatore_OrcidUpdate/get_data/should_allow_queries_by_ORCID_ID_of_the_Datacite_Metadata_Search_API.yml +15 -11
- data/spec/fixtures/vcr_cassettes/Toccatore_OrcidUpdate/get_data/should_report_if_there_are_no_works_returned_by_the_Datacite_Metadata_Search_API.yml +15 -11
- data/spec/fixtures/vcr_cassettes/Toccatore_OrcidUpdate/get_data/should_report_if_there_are_works_returned_by_the_Datacite_Metadata_Search_API.yml +15 -13
- data/spec/fixtures/vcr_cassettes/Toccatore_OrcidUpdate/get_total/with_no_works.yml +15 -13
- data/spec/fixtures/vcr_cassettes/Toccatore_OrcidUpdate/get_total/with_works.yml +15 -13
- data/spec/fixtures/vcr_cassettes/Toccatore_OrcidUpdate/push_data/should_delete_claims.yml +25 -32
- data/spec/fixtures/vcr_cassettes/Toccatore_OrcidUpdate/push_data/should_report_if_there_are_works_returned_by_the_Datacite_Metadata_Search_API.yml +1347 -1791
- data/spec/fixtures/vcr_cassettes/Toccatore_OrcidUpdate/queue_jobs/should_report_if_there_are_no_works_returned_by_the_Datacite_Metadata_Search_API.yml +14 -10
- data/spec/fixtures/vcr_cassettes/Toccatore_OrcidUpdate/queue_jobs/should_report_if_there_are_works_returned_by_the_Datacite_Metadata_Search_API.yml +29 -25
- data/spec/fixtures/vcr_cassettes/Toccatore_UsageUpdate/get_data/when_there_are_messages/should_return_the_data_for_one_message.yml +73 -0
- data/spec/fixtures/vcr_cassettes/Toccatore_UsageUpdate/get_data/when_there_is_ONE_message/should_return_the_data_for_one_message.yml +73 -0
- data/spec/fixtures/vcr_cassettes/Toccatore_UsageUpdate/get_message/should_return_no_meessage_when_the_queue_is_empty.yml +95 -0
- data/spec/fixtures/vcr_cassettes/Toccatore_UsageUpdate/get_message/should_return_one_message_when_there_are_multiple_messages.yml +95 -0
- data/spec/fixtures/vcr_cassettes/Toccatore_UsageUpdate/get_total/when_is_working_with_AWS.yml +187 -0
- data/spec/fixtures/vcr_cassettes/Toccatore_UsageUpdate/push_data/should_fail_if_format_of_the_event_is_empty.yml +169 -0
- data/spec/fixtures/vcr_cassettes/Toccatore_UsageUpdate/push_data/should_fail_if_format_of_the_event_is_wrong.yml +667 -0
- data/spec/fixtures/vcr_cassettes/Toccatore_UsageUpdate/push_data/should_work_with_a_single_item.yml +169 -0
- data/spec/fixtures/vcr_cassettes/Toccatore_UsageUpdate/queue_url/should_return_always_correct_queue_url.yml +49 -0
- data/spec/orcid_update_spec.rb +1 -1
- data/spec/queue_spec.rb +47 -0
- data/spec/spec_helper.rb +23 -1
- data/spec/usage_update_spec.rb +146 -0
- data/toccatore.gemspec +11 -5
- metadata +109 -26
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 56e3f7a50bedf097a157e0eab460c4131df5541a8ccb64c05a344ce90464060d
|
|
4
|
+
data.tar.gz: b01a010b2ac258c47c2cb705a4d122bb27f3a342dd838cdbab9c832dac66a563
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 43afaa44061b2488a5e5c0a9f243f8bd951d63f3742854c7c65522d78783b7dae2d2959bb33c818462f6e509d0da532686b9bbb1b807a7d989beeea2bbe558cf
|
|
7
|
+
data.tar.gz: 4ea332dd543c5b933a31dd3736cc87e54bf5dd967e010059e0b1975c4ad045b38536bfceef217f41a9d7db4d66602258405fae6219fbae83cb0c6eaedf2b21d9
|
data/Gemfile.lock
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
toccatore (0.
|
|
5
|
-
activesupport (
|
|
4
|
+
toccatore (0.4.15)
|
|
5
|
+
activesupport (>= 4.2.5, < 6)
|
|
6
|
+
aws-sdk-sqs
|
|
6
7
|
dotenv (~> 2.1, >= 2.1.1)
|
|
8
|
+
factory_bot
|
|
7
9
|
gender_detector (~> 1.0)
|
|
8
|
-
maremma (
|
|
10
|
+
maremma (>= 3.5.7, < 5)
|
|
9
11
|
namae (~> 0.11.0)
|
|
10
12
|
slack-notifier (~> 2.1)
|
|
11
13
|
thor (~> 0.19)
|
|
@@ -13,82 +15,100 @@ PATH
|
|
|
13
15
|
GEM
|
|
14
16
|
remote: https://rubygems.org/
|
|
15
17
|
specs:
|
|
16
|
-
activesupport (
|
|
17
|
-
|
|
18
|
+
activesupport (5.2.1)
|
|
19
|
+
concurrent-ruby (~> 1.0, >= 1.0.2)
|
|
20
|
+
i18n (>= 0.7, < 2)
|
|
18
21
|
minitest (~> 5.1)
|
|
19
|
-
thread_safe (~> 0.3, >= 0.3.4)
|
|
20
22
|
tzinfo (~> 1.1)
|
|
21
|
-
addressable (2.5.
|
|
22
|
-
public_suffix (
|
|
23
|
+
addressable (2.5.2)
|
|
24
|
+
public_suffix (>= 2.0.2, < 4.0)
|
|
25
|
+
aws-eventstream (1.0.1)
|
|
26
|
+
aws-partitions (1.97.0)
|
|
27
|
+
aws-sdk-core (3.24.0)
|
|
28
|
+
aws-eventstream (~> 1.0)
|
|
29
|
+
aws-partitions (~> 1.0)
|
|
30
|
+
aws-sigv4 (~> 1.0)
|
|
31
|
+
jmespath (~> 1.0)
|
|
32
|
+
aws-sdk-sqs (1.4.0)
|
|
33
|
+
aws-sdk-core (~> 3)
|
|
34
|
+
aws-sigv4 (~> 1.0)
|
|
35
|
+
aws-sigv4 (1.0.3)
|
|
23
36
|
builder (3.2.3)
|
|
24
37
|
codeclimate-test-reporter (1.0.8)
|
|
25
38
|
simplecov (<= 0.13)
|
|
39
|
+
concurrent-ruby (1.0.5)
|
|
26
40
|
crack (0.4.3)
|
|
27
41
|
safe_yaml (~> 1.0.0)
|
|
28
42
|
diff-lcs (1.3)
|
|
29
43
|
docile (1.1.5)
|
|
30
|
-
dotenv (2.
|
|
31
|
-
excon (0.
|
|
32
|
-
|
|
44
|
+
dotenv (2.5.0)
|
|
45
|
+
excon (0.62.0)
|
|
46
|
+
factory_bot (4.10.0)
|
|
47
|
+
activesupport (>= 3.0.0)
|
|
48
|
+
faker (1.9.1)
|
|
49
|
+
i18n (>= 0.7)
|
|
50
|
+
faraday (0.15.2)
|
|
33
51
|
multipart-post (>= 1.2, < 3)
|
|
34
52
|
faraday-encoding (0.0.4)
|
|
35
53
|
faraday
|
|
36
|
-
faraday_middleware (0.
|
|
54
|
+
faraday_middleware (0.12.2)
|
|
37
55
|
faraday (>= 0.7.4, < 1.0)
|
|
38
56
|
gender_detector (1.0.0)
|
|
39
|
-
hashdiff (0.3.
|
|
40
|
-
i18n (
|
|
57
|
+
hashdiff (0.3.7)
|
|
58
|
+
i18n (1.1.0)
|
|
59
|
+
concurrent-ruby (~> 1.0)
|
|
60
|
+
jmespath (1.4.0)
|
|
41
61
|
json (2.1.0)
|
|
42
|
-
maremma (
|
|
43
|
-
activesupport (>= 4.2.5)
|
|
62
|
+
maremma (4.1)
|
|
63
|
+
activesupport (>= 4.2.5, < 6)
|
|
44
64
|
addressable (>= 2.3.6)
|
|
45
65
|
builder (~> 3.2, >= 3.2.2)
|
|
46
|
-
excon (~> 0.
|
|
47
|
-
faraday (~> 0.
|
|
48
|
-
faraday-encoding (~> 0.0.
|
|
49
|
-
faraday_middleware (~> 0.
|
|
66
|
+
excon (~> 0.60)
|
|
67
|
+
faraday (~> 0.14)
|
|
68
|
+
faraday-encoding (~> 0.0.4)
|
|
69
|
+
faraday_middleware (~> 0.12.0)
|
|
50
70
|
multi_json (~> 1.12)
|
|
51
|
-
nokogiri (~> 1.
|
|
52
|
-
oj (
|
|
53
|
-
mini_portile2 (2.
|
|
54
|
-
minitest (5.
|
|
55
|
-
multi_json (1.
|
|
71
|
+
nokogiri (~> 1.8.1)
|
|
72
|
+
oj (>= 2.8.3)
|
|
73
|
+
mini_portile2 (2.3.0)
|
|
74
|
+
minitest (5.11.3)
|
|
75
|
+
multi_json (1.13.1)
|
|
56
76
|
multipart-post (2.0.0)
|
|
57
77
|
namae (0.11.3)
|
|
58
|
-
nokogiri (1.8.
|
|
59
|
-
mini_portile2 (~> 2.
|
|
60
|
-
oj (
|
|
61
|
-
public_suffix (
|
|
62
|
-
rack (2.0.
|
|
63
|
-
rack-test (0.
|
|
64
|
-
rack (>= 1.0)
|
|
65
|
-
rake (12.
|
|
66
|
-
rspec (3.
|
|
67
|
-
rspec-core (~> 3.
|
|
68
|
-
rspec-expectations (~> 3.
|
|
69
|
-
rspec-mocks (~> 3.
|
|
70
|
-
rspec-core (3.
|
|
71
|
-
rspec-support (~> 3.
|
|
72
|
-
rspec-expectations (3.
|
|
78
|
+
nokogiri (1.8.4)
|
|
79
|
+
mini_portile2 (~> 2.3.0)
|
|
80
|
+
oj (3.6.5)
|
|
81
|
+
public_suffix (3.0.2)
|
|
82
|
+
rack (2.0.5)
|
|
83
|
+
rack-test (0.8.3)
|
|
84
|
+
rack (>= 1.0, < 3)
|
|
85
|
+
rake (12.3.1)
|
|
86
|
+
rspec (3.8.0)
|
|
87
|
+
rspec-core (~> 3.8.0)
|
|
88
|
+
rspec-expectations (~> 3.8.0)
|
|
89
|
+
rspec-mocks (~> 3.8.0)
|
|
90
|
+
rspec-core (3.8.0)
|
|
91
|
+
rspec-support (~> 3.8.0)
|
|
92
|
+
rspec-expectations (3.8.1)
|
|
73
93
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
74
|
-
rspec-support (~> 3.
|
|
75
|
-
rspec-mocks (3.
|
|
94
|
+
rspec-support (~> 3.8.0)
|
|
95
|
+
rspec-mocks (3.8.0)
|
|
76
96
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
77
|
-
rspec-support (~> 3.
|
|
78
|
-
rspec-support (3.
|
|
97
|
+
rspec-support (~> 3.8.0)
|
|
98
|
+
rspec-support (3.8.0)
|
|
79
99
|
safe_yaml (1.0.4)
|
|
80
|
-
simplecov (0.
|
|
100
|
+
simplecov (0.13.0)
|
|
81
101
|
docile (~> 1.1.0)
|
|
82
102
|
json (>= 1.8, < 3)
|
|
83
103
|
simplecov-html (~> 0.10.0)
|
|
84
|
-
simplecov-html (0.10.
|
|
85
|
-
slack-notifier (2.
|
|
86
|
-
thor (0.
|
|
104
|
+
simplecov-html (0.10.2)
|
|
105
|
+
slack-notifier (2.3.2)
|
|
106
|
+
thor (0.20.0)
|
|
87
107
|
thread_safe (0.3.6)
|
|
88
|
-
tzinfo (1.2.
|
|
108
|
+
tzinfo (1.2.5)
|
|
89
109
|
thread_safe (~> 0.1)
|
|
90
110
|
vcr (3.0.3)
|
|
91
|
-
webmock (
|
|
111
|
+
webmock (3.4.2)
|
|
92
112
|
addressable (>= 2.3.6)
|
|
93
113
|
crack (>= 0.3.2)
|
|
94
114
|
hashdiff
|
|
@@ -98,14 +118,16 @@ PLATFORMS
|
|
|
98
118
|
|
|
99
119
|
DEPENDENCIES
|
|
100
120
|
bundler (~> 1.0)
|
|
101
|
-
codeclimate-test-reporter (~> 1.0
|
|
121
|
+
codeclimate-test-reporter (~> 1.0)
|
|
122
|
+
factory_bot
|
|
123
|
+
faker
|
|
102
124
|
rack-test (~> 0)
|
|
103
125
|
rake (~> 12.0)
|
|
104
126
|
rspec (~> 3.4)
|
|
105
|
-
simplecov
|
|
127
|
+
simplecov
|
|
106
128
|
toccatore!
|
|
107
129
|
vcr (~> 3.0, >= 3.0.3)
|
|
108
|
-
webmock (~>
|
|
130
|
+
webmock (~> 3.0, >= 3.0.1)
|
|
109
131
|
|
|
110
132
|
BUNDLED WITH
|
|
111
|
-
1.
|
|
133
|
+
1.16.1
|
data/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
[](https://codeclimate.com/github/datacite/toccatore)
|
|
5
5
|
[](https://codeclimate.com/github/datacite/toccatore/coverage)
|
|
6
6
|
|
|
7
|
-
Agent for Event Data service
|
|
7
|
+
Agent for Event Data service. Extracts links to ORCID IDs and DOIs not from DataCite from DataCite metadata, and pushes them to the other services.
|
|
8
8
|
|
|
9
9
|
## Installation and use
|
|
10
10
|
|
data/lib/toccatore/base.rb
CHANGED
|
@@ -72,7 +72,12 @@ module Toccatore
|
|
|
72
72
|
(0...total_pages).each do |page|
|
|
73
73
|
options[:offset] = page * job_batch_size
|
|
74
74
|
options[:total] = total
|
|
75
|
-
|
|
75
|
+
err = process_data(options)
|
|
76
|
+
if err.is_a?(Integer)
|
|
77
|
+
error_total += err
|
|
78
|
+
else
|
|
79
|
+
puts err.inspect
|
|
80
|
+
end
|
|
76
81
|
end
|
|
77
82
|
text = "#{total} works processed with #{error_total} errors for date range #{options[:from_date]} - #{options[:until_date]}."
|
|
78
83
|
else
|
|
@@ -82,7 +87,13 @@ module Toccatore
|
|
|
82
87
|
puts text
|
|
83
88
|
|
|
84
89
|
# send slack notification
|
|
85
|
-
|
|
90
|
+
if total == 0
|
|
91
|
+
options[:level] = "warning"
|
|
92
|
+
elsif error_total > 0
|
|
93
|
+
options[:level] = "danger"
|
|
94
|
+
else
|
|
95
|
+
options[:level] = "good"
|
|
96
|
+
end
|
|
86
97
|
options[:title] = "Report for #{source_id}"
|
|
87
98
|
send_notification_to_slack(text, options) if options[:slack_webhook_url].present?
|
|
88
99
|
|
|
@@ -145,8 +156,8 @@ module Toccatore
|
|
|
145
156
|
notifier = Slack::Notifier.new options[:slack_webhook_url],
|
|
146
157
|
username: "Event Data Agent",
|
|
147
158
|
icon_url: ICON_URL
|
|
148
|
-
response = notifier.
|
|
149
|
-
response.
|
|
159
|
+
response = notifier.post attachments: [attachment]
|
|
160
|
+
response.first
|
|
150
161
|
end
|
|
151
162
|
|
|
152
163
|
def get_doi_ra(prefix)
|
data/lib/toccatore/cli.rb
CHANGED
|
@@ -46,5 +46,17 @@ module Toccatore
|
|
|
46
46
|
datacite_related = Toccatore::DataciteRelated.new
|
|
47
47
|
datacite_related.queue_jobs(datacite_related.unfreeze(options))
|
|
48
48
|
end
|
|
49
|
+
|
|
50
|
+
desc "usage_update", "push DataCite DOIs usage from DLM Hub to Event Data"
|
|
51
|
+
method_option :access_token, type: :string, required: true
|
|
52
|
+
method_option :source_token, type: :string, required: true
|
|
53
|
+
method_option :push_url, type: :string
|
|
54
|
+
method_option :slack_webhook_url, type: :string
|
|
55
|
+
method_option :doi, type: :string
|
|
56
|
+
method_option :jsonapi, :type => :boolean, default: true
|
|
57
|
+
def usage_update
|
|
58
|
+
usage_update = Toccatore::UsageUpdate.new
|
|
59
|
+
usage_update.queue_jobs(usage_update.unfreeze(options))
|
|
60
|
+
end
|
|
49
61
|
end
|
|
50
62
|
end
|
|
@@ -45,7 +45,7 @@ module Toccatore
|
|
|
45
45
|
"relation_type_id" => raw_relation_type.underscore,
|
|
46
46
|
"source_id" => "datacite",
|
|
47
47
|
"source_token" => options[:source_token],
|
|
48
|
-
"occurred_at" => item.fetch("
|
|
48
|
+
"occurred_at" => item.fetch("updated"),
|
|
49
49
|
"license" => LICENSE }
|
|
50
50
|
else
|
|
51
51
|
ssum
|
|
@@ -58,7 +58,10 @@ module Toccatore
|
|
|
58
58
|
end
|
|
59
59
|
|
|
60
60
|
def push_item(item, options={})
|
|
61
|
-
|
|
61
|
+
if options[:access_token].blank?
|
|
62
|
+
puts "Access token missing."
|
|
63
|
+
return 1
|
|
64
|
+
end
|
|
62
65
|
|
|
63
66
|
host = options[:push_url].presence || "https://bus.eventdata.crossref.org"
|
|
64
67
|
push_url = host + "/events"
|
|
@@ -67,7 +70,16 @@ module Toccatore
|
|
|
67
70
|
data = { "data" => {
|
|
68
71
|
"id" => item["id"],
|
|
69
72
|
"type" => "events",
|
|
70
|
-
"attributes" =>
|
|
73
|
+
"attributes" => {
|
|
74
|
+
"message-action" => item["message_action"],
|
|
75
|
+
"subj-id" => item["subj_id"],
|
|
76
|
+
"obj-id" => item["obj_id"],
|
|
77
|
+
"relation-type-id" => item["relation_type_id"],
|
|
78
|
+
"source-id" => "datacite-crossref",
|
|
79
|
+
"source-token" => item["source_token"],
|
|
80
|
+
"occurred-at" => item["occurred_at"],
|
|
81
|
+
"license" => item["license"] } }}
|
|
82
|
+
|
|
71
83
|
response = Maremma.post(push_url, data: data.to_json,
|
|
72
84
|
bearer: options[:access_token],
|
|
73
85
|
content_type: 'json',
|
|
@@ -83,6 +95,9 @@ module Toccatore
|
|
|
83
95
|
if response.status == 201
|
|
84
96
|
puts "#{item['subj_id']} #{item['relation_type_id']} #{item['obj_id']} pushed to Event Data service."
|
|
85
97
|
0
|
|
98
|
+
elsif response.status == 409
|
|
99
|
+
puts "#{item['subj_id']} #{item['relation_type_id']} #{item['obj_id']} already pushed to Event Data service."
|
|
100
|
+
0
|
|
86
101
|
elsif response.body["errors"].present?
|
|
87
102
|
puts "#{item['subj_id']} #{item['relation_type_id']} #{item['obj_id']} had an error:"
|
|
88
103
|
puts "#{response.body['errors'].first['title']}"
|
|
@@ -44,9 +44,13 @@ module Toccatore
|
|
|
44
44
|
end
|
|
45
45
|
|
|
46
46
|
def push_item(item, options={})
|
|
47
|
-
|
|
47
|
+
if options[:access_token].blank?
|
|
48
|
+
puts "Access token missing."
|
|
49
|
+
return 1
|
|
50
|
+
end
|
|
48
51
|
|
|
49
|
-
|
|
52
|
+
host = options[:push_url].presence || "https://profiles.datacite.org/api"
|
|
53
|
+
push_url = host + "/claims"
|
|
50
54
|
|
|
51
55
|
response = Maremma.post(push_url, data: { "claim" => item }.to_json,
|
|
52
56
|
bearer: options[:access_token],
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
require 'aws-sdk-sqs'
|
|
2
|
+
|
|
3
|
+
module Toccatore
|
|
4
|
+
module Queue
|
|
5
|
+
|
|
6
|
+
def queue options={}
|
|
7
|
+
puts "Queue name has not been specified" unless ENV['ENVIRONMENT'].present?
|
|
8
|
+
puts "AWS_REGION has not been specified" unless ENV['AWS_REGION'].present?
|
|
9
|
+
region = ENV['AWS_REGION'] ||= 'eu-west-1'
|
|
10
|
+
Aws::SQS::Client.new(region: region.to_s, stub_responses: false)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def get_total options={}
|
|
14
|
+
req = @sqs.get_queue_attributes(
|
|
15
|
+
{
|
|
16
|
+
queue_url: queue_url, attribute_names:
|
|
17
|
+
[
|
|
18
|
+
'ApproximateNumberOfMessages',
|
|
19
|
+
'ApproximateNumberOfMessagesNotVisible'
|
|
20
|
+
]
|
|
21
|
+
}
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
msgs_available = req.attributes['ApproximateNumberOfMessages']
|
|
25
|
+
msgs_in_flight = req.attributes['ApproximateNumberOfMessagesNotVisible']
|
|
26
|
+
msgs_available.to_i
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def get_message options={}
|
|
30
|
+
@sqs.receive_message(queue_url: queue_url, max_number_of_messages: 1, wait_time_seconds: 1)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def delete_message options={}
|
|
34
|
+
return 1 if options.messages.size < 1
|
|
35
|
+
reponse = @sqs.delete_message({
|
|
36
|
+
queue_url: queue_url,
|
|
37
|
+
receipt_handle: options.messages[0][:receipt_handle]
|
|
38
|
+
})
|
|
39
|
+
if reponse.successful?
|
|
40
|
+
puts "Message #{options.messages[0][:receipt_handle]} deleted"
|
|
41
|
+
0
|
|
42
|
+
else
|
|
43
|
+
puts "Could NOT delete Message #{options.messages[0][:receipt_handle]}"
|
|
44
|
+
1
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def queue_url options={}
|
|
50
|
+
options[:queue_name] ||= "#{ENV['ENVIRONMENT']}_usage"
|
|
51
|
+
queue_name = options[:queue_name]
|
|
52
|
+
# puts "Using #{@sqs.get_queue_url(queue_name: queue_name).queue_url} queue"
|
|
53
|
+
@sqs.get_queue_url(queue_name: queue_name).queue_url
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
require_relative 'base'
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
module Toccatore
|
|
5
|
+
class UsageUpdate < Base
|
|
6
|
+
include Toccatore::Queue
|
|
7
|
+
LICENSE = "https://creativecommons.org/publicdomain/zero/1.0/"
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def initialize options={}
|
|
11
|
+
@sqs = queue options
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def queue_jobs(options={})
|
|
15
|
+
|
|
16
|
+
total = get_total(options)
|
|
17
|
+
|
|
18
|
+
if total < 1
|
|
19
|
+
text = "No works found for in the Usage Reports Queue."
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
error_total = 0
|
|
23
|
+
proccessed_messages = 0
|
|
24
|
+
num_messages = total
|
|
25
|
+
while num_messages != 0
|
|
26
|
+
processed = process_data(options)
|
|
27
|
+
error_total += processed
|
|
28
|
+
proccessed_messages += 1 if processed == 0
|
|
29
|
+
num_messages -= proccessed_messages
|
|
30
|
+
end
|
|
31
|
+
text = "#{proccessed_messages} works processed with #{error_total} errors for Usage Reports Queue #{queue_url}"
|
|
32
|
+
|
|
33
|
+
puts text
|
|
34
|
+
# send slack notification
|
|
35
|
+
options[:level] = total > 0 ? "good" : "warning"
|
|
36
|
+
options[:title] = "Report for #{source_id}"
|
|
37
|
+
send_notification_to_slack(text, options) if options[:slack_webhook_url].present?
|
|
38
|
+
|
|
39
|
+
# return number of works queued
|
|
40
|
+
proccessed_messages
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def process_data(options = {})
|
|
44
|
+
errors = 0
|
|
45
|
+
message = get_message
|
|
46
|
+
unless message.messages.empty?
|
|
47
|
+
data = get_data(message)
|
|
48
|
+
events = parse_data(data, options)
|
|
49
|
+
errors = push_data(events, options)
|
|
50
|
+
if errors < 1
|
|
51
|
+
delete_message message
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
errors
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def get_data reponse
|
|
58
|
+
body = JSON.parse(reponse.messages[0].body)
|
|
59
|
+
url = body["report_id"]
|
|
60
|
+
host = URI.parse(body["report_id"]).host.downcase
|
|
61
|
+
puts url
|
|
62
|
+
puts host
|
|
63
|
+
puts body
|
|
64
|
+
puts "%%%%%%%%%%"
|
|
65
|
+
Maremma.get(url, timeout: 120, host: host)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
# method returns number of errors
|
|
70
|
+
def push_data(items, options={})
|
|
71
|
+
if items.empty?
|
|
72
|
+
puts "No works found in the Queue."
|
|
73
|
+
0
|
|
74
|
+
elsif options[:access_token].blank?
|
|
75
|
+
puts "An error occured: Access token missing."
|
|
76
|
+
options[:total]
|
|
77
|
+
else
|
|
78
|
+
error_total = 0
|
|
79
|
+
Array(items).each do |item|
|
|
80
|
+
puts item
|
|
81
|
+
puts "*************"
|
|
82
|
+
error_total += push_item(item, options)
|
|
83
|
+
end
|
|
84
|
+
error_total
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def source_id
|
|
89
|
+
"usage_update"
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def format_event type, data, options
|
|
93
|
+
fail "Not type given. Report #{data[:report_id]} not proccessed" if type.blank?
|
|
94
|
+
fail "Access token missing." if options[:source_token].blank?
|
|
95
|
+
fail "Report_id is missing" if data[:report_id].blank?
|
|
96
|
+
|
|
97
|
+
{ "uuid" => SecureRandom.uuid,
|
|
98
|
+
"message-action" => "create",
|
|
99
|
+
"subj-id" => data[:report_id],
|
|
100
|
+
"subj"=> {
|
|
101
|
+
"pid"=> data[:report_id],
|
|
102
|
+
"issued"=> data[:created]
|
|
103
|
+
},
|
|
104
|
+
"total"=> data[:count],
|
|
105
|
+
"obj-id" => data[:pid],
|
|
106
|
+
"relation-type-id" => type,
|
|
107
|
+
"source-id" => "datacite-usage",
|
|
108
|
+
"source-token" => options[:source_token],
|
|
109
|
+
"occurred-at" => data[:created_at],
|
|
110
|
+
"license" => LICENSE
|
|
111
|
+
}
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def parse_data(result, options={})
|
|
115
|
+
puts result.status
|
|
116
|
+
puts "*************"
|
|
117
|
+
return result.body.fetch("errors") if result.body.fetch("errors", nil).present?
|
|
118
|
+
return [{ "errors" => { "title" => "The report is blank" }}] if result.body.blank?
|
|
119
|
+
|
|
120
|
+
items = result.body.dig("data","report","report-datasets")
|
|
121
|
+
header = result.body.dig("data","report","report-header")
|
|
122
|
+
report_id = result.url
|
|
123
|
+
|
|
124
|
+
created = header.fetch("created")
|
|
125
|
+
Array.wrap(items).reduce([]) do |x, item|
|
|
126
|
+
data = {}
|
|
127
|
+
data[:doi] = item.dig("dataset-id").first.dig("value")
|
|
128
|
+
data[:pid] = normalize_doi(data[:doi])
|
|
129
|
+
data[:created] = created
|
|
130
|
+
data[:report_id] = report_id
|
|
131
|
+
data[:created_at] = created
|
|
132
|
+
|
|
133
|
+
instances = item.dig("performance", 0, "instance")
|
|
134
|
+
|
|
135
|
+
return x += [OpenStruct.new(body: { "errors" => "There are too many instances in #{data[:doi]} for report #{report_id}. There can only be 4" })] if instances.size > 8
|
|
136
|
+
|
|
137
|
+
x += Array.wrap(instances).reduce([]) do |ssum, instance|
|
|
138
|
+
data[:count] = instance.dig("count")
|
|
139
|
+
event_type = "#{instance.dig("metric-type")}-#{instance.dig("access-method")}"
|
|
140
|
+
ssum << format_event(event_type, data, options)
|
|
141
|
+
ssum
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def push_item(item, options={})
|
|
147
|
+
if item["subj-id"].blank?
|
|
148
|
+
puts OpenStruct.new(body: { "errors" => [{ "title" => "There is no Subject" }] })
|
|
149
|
+
return 1
|
|
150
|
+
elsif options[:access_token].blank?
|
|
151
|
+
puts OpenStruct.new(body: { "errors" => [{ "title" => "Access token missing." }] })
|
|
152
|
+
return 1
|
|
153
|
+
elsif item["errors"].present?
|
|
154
|
+
puts OpenStruct.new(body: { "errors" => [{ "title" => "#{item["errors"]["title"]}" }] })
|
|
155
|
+
return 1
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
host = options[:push_url].presence || "https://api.test.datacite.org"
|
|
159
|
+
push_url = host + "/events/" + item["uuid"].to_s
|
|
160
|
+
data = { "data" => {
|
|
161
|
+
"id" => item["uuid"],
|
|
162
|
+
"type" => "events",
|
|
163
|
+
"attributes" => item.except("id") }}
|
|
164
|
+
|
|
165
|
+
response = Maremma.put(push_url, data: data.to_json,
|
|
166
|
+
bearer: options[:access_token],
|
|
167
|
+
content_type: 'json',
|
|
168
|
+
host: host)
|
|
169
|
+
|
|
170
|
+
if response.status == 201
|
|
171
|
+
puts "#{item['subj-id']} #{item['relation-type-id']} #{item['obj-id']} pushed to Event Data service."
|
|
172
|
+
0
|
|
173
|
+
elsif response.status == 200
|
|
174
|
+
puts "#{item['subj-id']} #{item['relation-type-id']} #{item['obj-id']} pushed to Event Data service for update."
|
|
175
|
+
0
|
|
176
|
+
elsif response.body["errors"].present?
|
|
177
|
+
puts "#{item['subj-id']} #{item['relation-type-id']} #{item['obj-id']} had an error:"
|
|
178
|
+
puts "#{response.body['errors'].first['title']}"
|
|
179
|
+
1
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
end
|
|
183
|
+
end
|
data/lib/toccatore/version.rb
CHANGED
data/lib/toccatore.rb
CHANGED
data/spec/base_spec.rb
CHANGED
|
@@ -35,7 +35,7 @@ describe Toccatore::Base, vcr: true do
|
|
|
35
35
|
it "datacite_related" do
|
|
36
36
|
text = "12 works processed for date range 2015-04-07 - 2015-04-08."
|
|
37
37
|
options = { title: "Report for datacite_related", slack_webhook_url: slack_webhook_url }
|
|
38
|
-
expect(subject.send_notification_to_slack(text, options)).to
|
|
38
|
+
expect(subject.send_notification_to_slack(text, options)).to be_kind_of(Net::HTTPOK)
|
|
39
39
|
end
|
|
40
40
|
|
|
41
41
|
it "datacite_related no works" do
|
|
@@ -43,13 +43,13 @@ describe Toccatore::Base, vcr: true do
|
|
|
43
43
|
options = { title: "Report for datacite_related",
|
|
44
44
|
slack_webhook_url: slack_webhook_url,
|
|
45
45
|
level: "warning" }
|
|
46
|
-
expect(subject.send_notification_to_slack(text, options)).to
|
|
46
|
+
expect(subject.send_notification_to_slack(text, options)).to be_kind_of(Net::HTTPOK)
|
|
47
47
|
end
|
|
48
48
|
|
|
49
49
|
it "orcid_update" do
|
|
50
50
|
text = "12 works processed for date range 2015-04-07 - 2015-04-08."
|
|
51
51
|
options = { title: "Report for orcid_update", slack_webhook_url: slack_webhook_url }
|
|
52
|
-
expect(subject.send_notification_to_slack(text, options)).to
|
|
52
|
+
expect(subject.send_notification_to_slack(text, options)).to be_kind_of(Net::HTTPOK)
|
|
53
53
|
end
|
|
54
54
|
|
|
55
55
|
it "orcid_update no works" do
|
|
@@ -57,7 +57,7 @@ describe Toccatore::Base, vcr: true do
|
|
|
57
57
|
options = { title: "Report for orcid_update",
|
|
58
58
|
slack_webhook_url: slack_webhook_url,
|
|
59
59
|
level: "warning" }
|
|
60
|
-
expect(subject.send_notification_to_slack(text, options)).to
|
|
60
|
+
expect(subject.send_notification_to_slack(text, options)).to be_kind_of(Net::HTTPOK)
|
|
61
61
|
end
|
|
62
62
|
end
|
|
63
63
|
|