dor-workflow-client 3.0.0.rc1
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 +7 -0
- data/.gitignore +21 -0
- data/.rspec +1 -0
- data/.rubocop.yml +11 -0
- data/.rubocop_todo.yml +21 -0
- data/.travis.yml +10 -0
- data/.yardopts +1 -0
- data/Gemfile +13 -0
- data/LICENSE.txt +22 -0
- data/README.md +35 -0
- data/Rakefile +16 -0
- data/bin/console +14 -0
- data/dor-workflow-client.gemspec +36 -0
- data/lib/dor/models/response/process.rb +55 -0
- data/lib/dor/models/response/update.rb +20 -0
- data/lib/dor/models/response/workflow.rb +54 -0
- data/lib/dor/workflow/client/connection_factory.rb +75 -0
- data/lib/dor/workflow/client/lifecycle_routes.rb +71 -0
- data/lib/dor/workflow/client/queues.rb +208 -0
- data/lib/dor/workflow/client/requestor.rb +48 -0
- data/lib/dor/workflow/client/version.rb +9 -0
- data/lib/dor/workflow/client/version_routes.rb +33 -0
- data/lib/dor/workflow/client/workflow_routes.rb +192 -0
- data/lib/dor/workflow/client.rb +77 -0
- data/lib/dor/workflow_exception.rb +6 -0
- data/spec/models/response/workflow_spec.rb +142 -0
- data/spec/spec_helper.rb +18 -0
- data/spec/workflow/client/connection_factory_spec.rb +25 -0
- data/spec/workflow/client/lifecycle_routes_spec.rb +27 -0
- data/spec/workflow/client/requestor_spec.rb +33 -0
- data/spec/workflow/client/workflow_routes_spec.rb +53 -0
- data/spec/workflow/client_spec.rb +633 -0
- metadata +309 -0
@@ -0,0 +1,142 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
RSpec.describe Dor::Workflow::Response::Workflow do
|
6
|
+
subject(:instance) { described_class.new(xml: xml) }
|
7
|
+
|
8
|
+
describe '#pid' do
|
9
|
+
subject { instance.pid }
|
10
|
+
|
11
|
+
let(:xml) do
|
12
|
+
<<~XML
|
13
|
+
<workflow repository="dor" objectId="druid:mw971zk1113" id="assemblyWF">
|
14
|
+
</workflow>
|
15
|
+
XML
|
16
|
+
end
|
17
|
+
it { is_expected.to eq 'druid:mw971zk1113' }
|
18
|
+
end
|
19
|
+
|
20
|
+
describe '#workflow_name' do
|
21
|
+
subject { instance.workflow_name }
|
22
|
+
|
23
|
+
let(:xml) do
|
24
|
+
<<~XML
|
25
|
+
<workflow repository="dor" objectId="druid:mw971zk1113" id="assemblyWF">
|
26
|
+
</workflow>
|
27
|
+
XML
|
28
|
+
end
|
29
|
+
it { is_expected.to eq 'assemblyWF' }
|
30
|
+
end
|
31
|
+
|
32
|
+
describe '#active?' do
|
33
|
+
subject { instance.active_for?(version: 2) }
|
34
|
+
|
35
|
+
context 'when the workflow has not been instantiated for the given version' do
|
36
|
+
let(:xml) do
|
37
|
+
<<~XML
|
38
|
+
<workflow repository="dor" objectId="druid:mw971zk1113" id="assemblyWF">
|
39
|
+
<process version="1" laneId="default" elapsed="0.0" attempts="1" datetime="2013-02-18T14:40:25-0800" status="completed" name="start-assembly"/>
|
40
|
+
<process version="1" laneId="default" elapsed="0.509" attempts="1" datetime="2013-02-18T14:42:24-0800" status="completed" name="jp2-create"/>
|
41
|
+
</workflow>
|
42
|
+
XML
|
43
|
+
end
|
44
|
+
it { is_expected.to be false }
|
45
|
+
end
|
46
|
+
|
47
|
+
context 'when the workflow has been instantiated for the given version' do
|
48
|
+
let(:xml) do
|
49
|
+
<<~XML
|
50
|
+
<workflow repository="dor" objectId="druid:mw971zk1113" id="assemblyWF">
|
51
|
+
<process version="1" laneId="default" elapsed="0.0" attempts="1" datetime="2013-02-18T14:40:25-0800" status="completed" name="start-assembly"/>
|
52
|
+
<process version="1" laneId="default" elapsed="0.509" attempts="1" datetime="2013-02-18T14:42:24-0800" status="completed" name="jp2-create"/>
|
53
|
+
<process version="2" laneId="default" elapsed="0.509" attempts="1" datetime="2013-02-18T14:42:24-0800" status="waiting" name="jp2-create"/>
|
54
|
+
</workflow>
|
55
|
+
XML
|
56
|
+
end
|
57
|
+
it { is_expected.to be true }
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
describe '#empty?' do
|
62
|
+
subject { instance.empty? }
|
63
|
+
|
64
|
+
context 'when there is xml' do
|
65
|
+
let(:xml) do
|
66
|
+
'<?xml version="1.0" encoding="UTF-8"?>
|
67
|
+
<workflow repository="dor" objectId="druid:oo201oo0001" id="accessionWF">
|
68
|
+
<process version="2" lifecycle="submitted" elapsed="0.0" archived="true" attempts="1"
|
69
|
+
datetime="2012-11-06T16:18:24-0800" status="completed" name="start-accession"/>
|
70
|
+
<process version="2" elapsed="0.0" archived="true" attempts="1"
|
71
|
+
datetime="2012-11-06T16:18:58-0800" status="completed" name="technical-metadata"/>
|
72
|
+
<process version="2" elapsed="0.0" archived="true" attempts="1"
|
73
|
+
datetime="2012-11-06T16:19:02-0800" status="completed" name="provenance-metadata"/>
|
74
|
+
<process version="2" elapsed="0.0" archived="true" attempts="1"
|
75
|
+
datetime="2012-11-06T16:19:05-0800" status="completed" name="remediate-object"/>
|
76
|
+
<process version="2" elapsed="0.0" archived="true" attempts="1"
|
77
|
+
datetime="2012-11-06T16:19:06-0800" status="completed" name="shelve"/>
|
78
|
+
<process version="2" lifecycle="published" elapsed="0.0" archived="true" attempts="1"
|
79
|
+
datetime="2012-11-06T16:19:07-0800" status="completed" name="publish"/>
|
80
|
+
<process version="2" elapsed="0.0" archived="true" attempts="1"
|
81
|
+
datetime="2012-11-06T16:19:09-0800" status="completed" name="sdr-ingest-transfer"/>
|
82
|
+
<process version="2" lifecycle="accessioned" elapsed="0.0" archived="true" attempts="1"
|
83
|
+
datetime="2012-11-06T16:19:10-0800" status="completed" name="cleanup"/>
|
84
|
+
<process version="2" elapsed="0.0" archived="true" attempts="1"
|
85
|
+
datetime="2012-11-06T16:19:13-0800" status="completed" name="rights-metadata"/>
|
86
|
+
<process version="2" lifecycle="described" elapsed="0.0" archived="true" attempts="1"
|
87
|
+
datetime="2012-11-06T16:19:15-0800" status="completed" name="descriptive-metadata"/>
|
88
|
+
<process version="2" elapsed="0.0" archived="true" attempts="2"
|
89
|
+
datetime="2012-11-06T16:19:16-0800" status="completed" name="content-metadata"/>
|
90
|
+
</workflow>'
|
91
|
+
end
|
92
|
+
|
93
|
+
it { is_expected.to be false }
|
94
|
+
end
|
95
|
+
|
96
|
+
context 'when the xml is empty' do
|
97
|
+
let(:xml) { '' }
|
98
|
+
|
99
|
+
it { is_expected.to be true }
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
describe '#process_for_recent_version' do
|
104
|
+
subject(:process) { instance.process_for_recent_version(name: 'jp2-create') }
|
105
|
+
|
106
|
+
context 'when the workflow has not been instantiated for the given version' do
|
107
|
+
let(:xml) do
|
108
|
+
<<~XML
|
109
|
+
<workflow repository="dor" objectId="druid:mw971zk1113" id="assemblyWF">
|
110
|
+
<process version="1" laneId="default" elapsed="0.0" attempts="1" datetime="2013-02-18T14:40:25-0800" status="completed" name="start-assembly"/>
|
111
|
+
<process version="1" laneId="default" elapsed="0.509" attempts="1" datetime="2013-02-18T14:42:24-0800" status="completed" name="jp2-create"/>
|
112
|
+
</workflow>
|
113
|
+
XML
|
114
|
+
end
|
115
|
+
|
116
|
+
it 'returns a process' do
|
117
|
+
expect(process).to be_kind_of Dor::Workflow::Response::Process
|
118
|
+
expect(process.status).to eq 'completed'
|
119
|
+
expect(process.name).to eq 'jp2-create'
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
context 'when the workflow has been instantiated for the given version' do
|
124
|
+
let(:xml) do
|
125
|
+
<<~XML
|
126
|
+
<workflow repository="dor" objectId="druid:mw971zk1113" id="assemblyWF">
|
127
|
+
<process version="1" laneId="default" elapsed="0.0" attempts="1" datetime="2013-02-18T14:40:25-0800" status="completed" name="start-assembly"/>
|
128
|
+
<process version="1" laneId="default" elapsed="0.509" attempts="1" datetime="2013-02-18T14:42:24-0800" status="completed" name="jp2-create"/>
|
129
|
+
<process version="2" laneId="default" elapsed="0.509" attempts="1" datetime="2013-02-18T14:42:24-0800" status="error" name="jp2-create" errorMessage="it just broke"/>
|
130
|
+
</workflow>
|
131
|
+
XML
|
132
|
+
end
|
133
|
+
|
134
|
+
it 'returns a process' do
|
135
|
+
expect(process).to be_kind_of Dor::Workflow::Response::Process
|
136
|
+
expect(process.status).to eq 'error'
|
137
|
+
expect(process.error_message).to eq 'it just broke'
|
138
|
+
expect(process.name).to eq 'jp2-create'
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
lib = File.expand_path('lib', __dir__)
|
4
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
|
+
|
6
|
+
require 'simplecov'
|
7
|
+
SimpleCov.start do
|
8
|
+
add_filter 'spec'
|
9
|
+
end
|
10
|
+
|
11
|
+
require 'byebug'
|
12
|
+
require 'dor/workflow/client'
|
13
|
+
require 'equivalent-xml'
|
14
|
+
require 'equivalent-xml/rspec_matchers'
|
15
|
+
require 'webmock/rspec'
|
16
|
+
|
17
|
+
# RSpec.configure do |conf|
|
18
|
+
# end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
# This test can take up to 15s to run because it does retries with exponential backoff
|
6
|
+
RSpec.describe Dor::Workflow::Client::ConnectionFactory do
|
7
|
+
let(:mock_logger) { double('Logger', info: true, debug: true, warn: true) }
|
8
|
+
|
9
|
+
let(:repo) { 'dor' }
|
10
|
+
let(:druid) { 'druid:123' }
|
11
|
+
before do
|
12
|
+
stub_request(:put, "http://example.com/#{repo}/objects/#{druid}/workflows/httpException?create-ds=true")
|
13
|
+
.to_return(status: 500, body: 'Internal error', headers: {})
|
14
|
+
end
|
15
|
+
|
16
|
+
let(:client) { Dor::Workflow::Client.new url: 'http://example.com', logger: mock_logger }
|
17
|
+
|
18
|
+
describe '#create_workflow' do
|
19
|
+
it 'logs an error and retry upon a targeted Faraday exception' do
|
20
|
+
expect(mock_logger).to receive(:warn).with('retrying connection (1 remaining) to http://example.com/dor/objects/druid:123/workflows/httpException?create-ds=true: (Faraday::RetriableResponse) 500')
|
21
|
+
expect(mock_logger).to receive(:warn).with('retrying connection (0 remaining) to http://example.com/dor/objects/druid:123/workflows/httpException?create-ds=true: (Faraday::RetriableResponse) 500')
|
22
|
+
expect { client.create_workflow(repo, druid, 'httpException', '<xml>') }.to raise_error Dor::WorkflowException
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
RSpec.describe Dor::Workflow::Client::LifecycleRoutes do
|
6
|
+
let(:mock_requestor) { instance_double(Dor::Workflow::Client::Requestor) }
|
7
|
+
|
8
|
+
let(:routes) { described_class.new(requestor: mock_requestor) }
|
9
|
+
|
10
|
+
describe '#milestones' do
|
11
|
+
let(:ng_xml) { Nokogiri::XML(xml) }
|
12
|
+
let(:xml) do
|
13
|
+
'<?xml version="1.0" encoding="UTF-8"?><lifecycle objectId="druid:gv054hp4128"><milestone date="2012-01-26T21:06:54-0800" version="2">published</milestone></lifecycle>'
|
14
|
+
end
|
15
|
+
|
16
|
+
before do
|
17
|
+
allow(routes).to receive(:query_lifecycle).and_return(ng_xml)
|
18
|
+
end
|
19
|
+
|
20
|
+
subject(:milestones) { routes.milestones('dor', 'druid:gv054hp4128') }
|
21
|
+
|
22
|
+
it 'includes the version in with the milestones' do
|
23
|
+
expect(milestones.first[:milestone]).to eq('published')
|
24
|
+
expect(milestones.first[:version]).to eq('2')
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
RSpec.describe Dor::Workflow::Client::Requestor do
|
6
|
+
let(:mock_http_connection) do
|
7
|
+
Faraday.new(url: 'http://example.com/') do |builder|
|
8
|
+
builder.use Faraday::Response::RaiseError
|
9
|
+
builder.options.params_encoder = Faraday::FlatParamsEncoder
|
10
|
+
|
11
|
+
builder.adapter :test, stubs
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
let(:requestor) { described_class.new(connection: mock_http_connection) }
|
16
|
+
|
17
|
+
describe '.send_workflow_resource_request' do
|
18
|
+
let(:stubs) do
|
19
|
+
Faraday::Adapter::Test::Stubs.new do |stub|
|
20
|
+
stub.get('x?complete=a&complete=b') do |_env|
|
21
|
+
[200, {}, 'ab']
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'uses the flat params encoder' do
|
27
|
+
response = requestor.send(:send_workflow_resource_request, 'x?complete=a&complete=b')
|
28
|
+
|
29
|
+
expect(response.body).to eq 'ab'
|
30
|
+
expect(response.env.url.query).to eq 'complete=a&complete=b'
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
RSpec.describe Dor::Workflow::Client::WorkflowRoutes do
|
6
|
+
let(:mock_requestor) { instance_double(Dor::Workflow::Client::Requestor) }
|
7
|
+
|
8
|
+
let(:routes) { described_class.new(requestor: mock_requestor) }
|
9
|
+
|
10
|
+
let(:wf_xml) do
|
11
|
+
<<-EOXML
|
12
|
+
<workflow id="etdSubmitWF">
|
13
|
+
<process name="register-object" status="completed" attempts="1" />
|
14
|
+
<process name="submit" status="waiting" />
|
15
|
+
<process name="reader-approval" status="waiting" />
|
16
|
+
<process name="registrar-approval" status="waiting" />
|
17
|
+
<process name="start-accession" status="waiting" />
|
18
|
+
</workflow>
|
19
|
+
EOXML
|
20
|
+
end
|
21
|
+
|
22
|
+
describe '#add_lane_id_to_workflow_xml' do
|
23
|
+
it 'adds laneId attributes to all process elements' do
|
24
|
+
expected = <<-XML
|
25
|
+
<workflow id="etdSubmitWF">
|
26
|
+
<process name="register-object" status="completed" attempts="1" laneId="lane1"/>
|
27
|
+
<process name="submit" status="waiting" laneId="lane1"/>
|
28
|
+
<process name="reader-approval" status="waiting" laneId="lane1"/>
|
29
|
+
<process name="registrar-approval" status="waiting" laneId="lane1"/>
|
30
|
+
<process name="start-accession" status="waiting" laneId="lane1"/>
|
31
|
+
</workflow>
|
32
|
+
XML
|
33
|
+
expect(routes.send(:add_lane_id_to_workflow_xml, 'lane1', wf_xml)).to be_equivalent_to(expected)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe '#workflow' do
|
38
|
+
let(:xml) do
|
39
|
+
<<~XML
|
40
|
+
<workflow repository="dor" objectId="druid:mw971zk1113" id="accessionWF">
|
41
|
+
<process laneId="default" lifecycle="submitted" elapsed="0.0" attempts="1" datetime="2013-02-18T15:08:10-0800" status="completed" name="start-accession"/>
|
42
|
+
</workflow>
|
43
|
+
XML
|
44
|
+
end
|
45
|
+
before do
|
46
|
+
allow(routes).to receive(:workflow_xml) { xml }
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'it returns a workflow' do
|
50
|
+
expect(routes.workflow(pid: 'druid:mw971zk1113', workflow_name: 'accessionWF')).to be_kind_of Dor::Workflow::Response::Workflow
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|