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
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 5f6d5ba580a5c98372eed49a683d9db35e1e83fbbf91350e401ab7dccbd93c38
|
4
|
+
data.tar.gz: 7899acc1174d4b43e56ae9e4a1823e9302c2219f0623b159014f4c1d9e130214
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b5c2081451447bf2732c7450562e20cad324d50f5c88f5733579a7c200ad646aa11eb89ae24d1c8535f761c81049b82394dcce4b7003d1d31880bc307474dcb0
|
7
|
+
data.tar.gz: a92d0a03be85f00934f03d5f3e68e5796c9c4779c4db8f8c368faf541fdb93a336d0c40deebc879b7e424ac667f5896ee6d656f840a669ffe6490ffbbb6dc5d9
|
data/.gitignore
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
.bundle
|
4
|
+
.config
|
5
|
+
.yardoc
|
6
|
+
.rvmrc
|
7
|
+
Gemfile.lock
|
8
|
+
InstalledFiles
|
9
|
+
_yardoc
|
10
|
+
coverage
|
11
|
+
doc/
|
12
|
+
lib/bundler/man
|
13
|
+
pkg
|
14
|
+
rdoc
|
15
|
+
spec/reports
|
16
|
+
test/tmp
|
17
|
+
test/version_tmp
|
18
|
+
tmp
|
19
|
+
.ruby-version
|
20
|
+
.ruby-gemset
|
21
|
+
|
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/.rubocop.yml
ADDED
data/.rubocop_todo.yml
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# This configuration was generated by
|
2
|
+
# `rubocop --auto-gen-config`
|
3
|
+
# on 2019-04-06 08:08:20 -0500 using RuboCop version 0.63.1.
|
4
|
+
# The point is for the user to remove these configuration records
|
5
|
+
# one by one as the offenses are removed from the code base.
|
6
|
+
# Note that changes in the inspected code, or installation of new
|
7
|
+
# versions of RuboCop, may require this file to be generated again.
|
8
|
+
|
9
|
+
# Offense count: 3
|
10
|
+
Metrics/AbcSize:
|
11
|
+
Max: 23
|
12
|
+
|
13
|
+
# Offense count: 1
|
14
|
+
# Configuration parameters: CountComments, ExcludedMethods.
|
15
|
+
Metrics/MethodLength:
|
16
|
+
Max: 13
|
17
|
+
|
18
|
+
# Offense count: 2
|
19
|
+
# Configuration parameters: CountKeywordArgs.
|
20
|
+
Metrics/ParameterLists:
|
21
|
+
Max: 6
|
data/.travis.yml
ADDED
data/.yardopts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--markup markdown
|
data/Gemfile
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
source 'https://rubygems.org'
|
4
|
+
|
5
|
+
# Specify your gem's dependencies in dor-workflow-service.gemspec
|
6
|
+
gemspec
|
7
|
+
|
8
|
+
gem 'activesupport', ENV['RAILS_VERSION'] if ENV['RAILS_VERSION']
|
9
|
+
|
10
|
+
group :development, :test do
|
11
|
+
gem 'byebug'
|
12
|
+
gem 'simplecov'
|
13
|
+
end
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 Willy Mene
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
[](https://travis-ci.org/sul-dlss/dor-workflow-service)
|
2
|
+
|
3
|
+
# dor-workflow-client gem
|
4
|
+
|
5
|
+
A Ruby client to work with the DOR Workflow REST Service. The REST API is defined here:
|
6
|
+
https://consul.stanford.edu/display/DOR/DOR+services#DORservices-initializeworkflow
|
7
|
+
|
8
|
+
## Usage
|
9
|
+
|
10
|
+
You should initialize a `Dor::Workflow::Client` object in your application configuration, i.e. in a bootup or startup method like:
|
11
|
+
|
12
|
+
```ruby
|
13
|
+
wfs = Dor::Workflow::Client.new(url: 'https://test-server.edu/workflow/')
|
14
|
+
```
|
15
|
+
|
16
|
+
Consumers of recent versions of the [dor-services](https://github.com/sul-dlss/dor-services) gem can access the configured `Dor::Workflow::Client` object via `Dor::Config`.
|
17
|
+
|
18
|
+
## Underlying Clients
|
19
|
+
|
20
|
+
This gem currently uses the [Faraday](https://github.com/lostisland/faraday) HTTP client to access the back-end service. The clients be accessed directly from your `Dor::Workflow::Client` object:
|
21
|
+
|
22
|
+
```ruby
|
23
|
+
wfs.connection # the Faraday object
|
24
|
+
```
|
25
|
+
|
26
|
+
Or for advanced configurations, ONE of them (not both) can be passed to the constructor instead of the raw URL string:
|
27
|
+
|
28
|
+
```ruby
|
29
|
+
conn = Faraday.new(:url => 'http://sushi.com') do |faraday|
|
30
|
+
faraday.request :url_encoded # form-encode POST params
|
31
|
+
faraday.response :logger # log requests to STDOUT
|
32
|
+
faraday.adapter Faraday.default_adapter # make requests with Net::HTTP
|
33
|
+
end
|
34
|
+
wfs = Dor::Workflow::Client.new(connection: conn)
|
35
|
+
```
|
data/Rakefile
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'bundler/gem_tasks'
|
5
|
+
|
6
|
+
require 'rspec/core/rake_task'
|
7
|
+
require 'rubocop/rake_task'
|
8
|
+
|
9
|
+
RuboCop::RakeTask.new
|
10
|
+
RSpec::Core::RakeTask.new(:spec)
|
11
|
+
|
12
|
+
desc 'Run linter and tests'
|
13
|
+
task default: %i[rubocop spec]
|
14
|
+
|
15
|
+
require 'yard'
|
16
|
+
YARD::Rake::YardocTask.new
|
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'rubygems'
|
5
|
+
require 'irb'
|
6
|
+
|
7
|
+
project_root = File.expand_path(File.dirname(__FILE__) + '/..')
|
8
|
+
|
9
|
+
# Load config for current environment.
|
10
|
+
$LOAD_PATH.unshift(project_root + '/lib')
|
11
|
+
|
12
|
+
require 'dor-workflow-service'
|
13
|
+
|
14
|
+
IRB.start
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
lib = File.expand_path('lib', __dir__)
|
4
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
|
+
require 'dor/workflow/client/version'
|
6
|
+
|
7
|
+
Gem::Specification.new do |gem|
|
8
|
+
gem.name = 'dor-workflow-client'
|
9
|
+
gem.version = Dor::Workflow::Client::VERSION
|
10
|
+
gem.authors = ['Willy Mene', 'Darren Hardy']
|
11
|
+
gem.email = ['wmene@stanford.edu']
|
12
|
+
gem.description = 'Enables Ruby manipulation of the DOR Workflow Service via its REST API'
|
13
|
+
gem.summary = 'Provides convenience methods to work with the DOR Workflow Service'
|
14
|
+
gem.homepage = 'https://consul.stanford.edu/display/DOR/DOR+services#DORservices-initializeworkflow'
|
15
|
+
|
16
|
+
gem.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
|
17
|
+
gem.executables = gem.files.grep(%r{^bin/}).map { |f| File.basename(f) }
|
18
|
+
gem.test_files = gem.files.grep(%r{^(spec)/})
|
19
|
+
gem.require_paths = ['lib']
|
20
|
+
|
21
|
+
gem.add_dependency 'activesupport', '>= 3.2.1', '< 6'
|
22
|
+
gem.add_dependency 'confstruct', '>= 0.2.7', '< 2'
|
23
|
+
gem.add_dependency 'faraday', '~> 0.9', '>= 0.9.2'
|
24
|
+
gem.add_dependency 'faraday_middleware'
|
25
|
+
gem.add_dependency 'net-http-persistent', '>= 2.9.4', '< 4.a'
|
26
|
+
gem.add_dependency 'nokogiri', '~> 1.6'
|
27
|
+
|
28
|
+
gem.add_development_dependency 'equivalent-xml', '~> 0.5', '>= 0.5.1'
|
29
|
+
gem.add_development_dependency 'rake'
|
30
|
+
gem.add_development_dependency 'redcarpet'
|
31
|
+
gem.add_development_dependency 'rspec', '~> 3.3'
|
32
|
+
gem.add_development_dependency 'rubocop', '~> 0.63.1'
|
33
|
+
gem.add_development_dependency 'simplecov'
|
34
|
+
gem.add_development_dependency 'webmock'
|
35
|
+
gem.add_development_dependency 'yard'
|
36
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Dor
|
4
|
+
module Workflow
|
5
|
+
module Response
|
6
|
+
# Represents the status of an object doing a workflow process
|
7
|
+
class Process
|
8
|
+
# @params [Workflow] parent
|
9
|
+
# @params [Hash] attributes
|
10
|
+
def initialize(parent:, **attributes)
|
11
|
+
@parent = parent
|
12
|
+
@attributes = attributes
|
13
|
+
end
|
14
|
+
|
15
|
+
def name
|
16
|
+
@attributes[:name].presence
|
17
|
+
end
|
18
|
+
|
19
|
+
def status
|
20
|
+
@attributes[:status].presence
|
21
|
+
end
|
22
|
+
|
23
|
+
def datetime
|
24
|
+
@attributes[:datetime].presence
|
25
|
+
end
|
26
|
+
|
27
|
+
def elapsed
|
28
|
+
@attributes[:elapsed].presence
|
29
|
+
end
|
30
|
+
|
31
|
+
def attempts
|
32
|
+
@attributes[:attempts].presence
|
33
|
+
end
|
34
|
+
|
35
|
+
def lifecycle
|
36
|
+
@attributes[:lifecycle].presence
|
37
|
+
end
|
38
|
+
|
39
|
+
def note
|
40
|
+
@attributes[:note].presence
|
41
|
+
end
|
42
|
+
|
43
|
+
def error_message
|
44
|
+
@attributes[:errorMessage].presence
|
45
|
+
end
|
46
|
+
|
47
|
+
delegate :pid, :workflow_name, to: :parent
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
attr_reader :parent
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'dor/models/response/process'
|
4
|
+
|
5
|
+
module Dor
|
6
|
+
module Workflow
|
7
|
+
module Response
|
8
|
+
# The response from telling the server to update a workflow step.
|
9
|
+
class Update
|
10
|
+
def initialize(json:)
|
11
|
+
@json = JSON.parse(json)
|
12
|
+
end
|
13
|
+
|
14
|
+
def next_steps
|
15
|
+
@json[:next_steps]
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'dor/models/response/process'
|
4
|
+
|
5
|
+
module Dor
|
6
|
+
module Workflow
|
7
|
+
module Response
|
8
|
+
# The response form asking the server about a workflow for an item
|
9
|
+
class Workflow
|
10
|
+
def initialize(xml:)
|
11
|
+
@xml = xml
|
12
|
+
end
|
13
|
+
|
14
|
+
def pid
|
15
|
+
ng_xml.at_xpath('/workflow/@objectId').text
|
16
|
+
end
|
17
|
+
|
18
|
+
def workflow_name
|
19
|
+
ng_xml.at_xpath('/workflow/@id').text
|
20
|
+
end
|
21
|
+
|
22
|
+
# @param [Integer] version the version we are checking for.
|
23
|
+
def active_for?(version:)
|
24
|
+
result = ng_xml.at_xpath("/workflow/process[@version=#{version}]")
|
25
|
+
result ? true : false
|
26
|
+
end
|
27
|
+
|
28
|
+
# Returns the process, for the most recent version that matches the given name:
|
29
|
+
def process_for_recent_version(name:)
|
30
|
+
nodes = process_nodes_for(name: name)
|
31
|
+
node = nodes.max { |a, b| a.attr('version').to_i <=> b.attr('version').to_i }
|
32
|
+
attributes = node ? Hash[node.attributes.collect { |k, v| [k.to_sym, v.value] }] : {}
|
33
|
+
Process.new(parent: self, **attributes)
|
34
|
+
end
|
35
|
+
|
36
|
+
def empty?
|
37
|
+
ng_xml.xpath('/workflow/process').empty?
|
38
|
+
end
|
39
|
+
|
40
|
+
attr_reader :xml
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def process_nodes_for(name:)
|
45
|
+
ng_xml.xpath("/workflow/process[@name = '#{name}']")
|
46
|
+
end
|
47
|
+
|
48
|
+
def ng_xml
|
49
|
+
@ng_xml ||= Nokogiri::XML(@xml)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'faraday'
|
4
|
+
require 'faraday_middleware'
|
5
|
+
|
6
|
+
module Dor
|
7
|
+
module Workflow
|
8
|
+
class Client
|
9
|
+
# Builds Faraday connections that follow redirects
|
10
|
+
class ConnectionFactory
|
11
|
+
def self.build_connection(url, timeout:, logger:)
|
12
|
+
new(url, timeout: timeout, logger: logger).build_connection
|
13
|
+
end
|
14
|
+
|
15
|
+
def initialize(url, timeout:, logger:)
|
16
|
+
@url = url
|
17
|
+
@timeout = timeout
|
18
|
+
@logger = logger
|
19
|
+
end
|
20
|
+
|
21
|
+
# rubocop:disable Metrics/MethodLength
|
22
|
+
def build_connection
|
23
|
+
Faraday.new(url: url) do |faraday|
|
24
|
+
faraday.use Faraday::Response::RaiseError # raise exceptions on 40x, 50x responses
|
25
|
+
faraday.use FaradayMiddleware::FollowRedirects, limit: 3
|
26
|
+
faraday.options.params_encoder = Faraday::FlatParamsEncoder
|
27
|
+
if timeout
|
28
|
+
faraday.options.timeout = timeout
|
29
|
+
faraday.options.open_timeout = timeout
|
30
|
+
end
|
31
|
+
faraday.headers[:user_agent] = user_agent
|
32
|
+
faraday.request :retry,
|
33
|
+
max: 2,
|
34
|
+
interval: 5.0,
|
35
|
+
interval_randomness: 0.01,
|
36
|
+
backoff_factor: 2.0,
|
37
|
+
methods: retriable_methods,
|
38
|
+
exceptions: retriable_exceptions,
|
39
|
+
retry_block: retry_block,
|
40
|
+
retry_statuses: retry_statuses
|
41
|
+
faraday.adapter Faraday.default_adapter # Last middleware must be the adapter
|
42
|
+
end
|
43
|
+
end
|
44
|
+
# rubocop:enable Metrics/MethodLength
|
45
|
+
|
46
|
+
def user_agent
|
47
|
+
"dor-workflow-service #{VERSION}"
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
attr_reader :logger, :timeout, :url
|
53
|
+
|
54
|
+
def retriable_methods
|
55
|
+
Faraday::Request::Retry::IDEMPOTENT_METHODS + [:post]
|
56
|
+
end
|
57
|
+
|
58
|
+
def retriable_exceptions
|
59
|
+
Faraday::Request::Retry::DEFAULT_EXCEPTIONS + [Faraday::ConnectionFailed]
|
60
|
+
end
|
61
|
+
|
62
|
+
def retry_block
|
63
|
+
lambda do |env, _opts, retries, exception|
|
64
|
+
logger.warn "retrying connection (#{retries} remaining) to #{env.url}: (#{exception.class}) " \
|
65
|
+
"#{exception.message} #{env.status}"
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def retry_statuses
|
70
|
+
[429, 500, 502, 503, 504, 599]
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Dor
|
4
|
+
module Workflow
|
5
|
+
class Client
|
6
|
+
# Makes requests relating to a lifecycle
|
7
|
+
class LifecycleRoutes
|
8
|
+
def initialize(requestor:)
|
9
|
+
@requestor = requestor
|
10
|
+
end
|
11
|
+
|
12
|
+
# Returns the Date for a requested milestone from workflow lifecycle
|
13
|
+
# @param [String] repo repository name
|
14
|
+
# @param [String] druid object id
|
15
|
+
# @param [String] milestone name of the milestone being queried for
|
16
|
+
# @return [Time] when the milestone was achieved. Returns nil if the milestone does not exist
|
17
|
+
# @example An example lifecycle xml from the workflow service.
|
18
|
+
# <lifecycle objectId="druid:ct011cv6501">
|
19
|
+
# <milestone date="2010-04-27T11:34:17-0700">registered</milestone>
|
20
|
+
# <milestone date="2010-04-29T10:12:51-0700">inprocess</milestone>
|
21
|
+
# <milestone date="2010-06-15T16:08:58-0700">released</milestone>
|
22
|
+
# </lifecycle>
|
23
|
+
def lifecycle(repo, druid, milestone)
|
24
|
+
doc = query_lifecycle(repo, druid)
|
25
|
+
milestone = doc.at_xpath("//lifecycle/milestone[text() = '#{milestone}']")
|
26
|
+
return Time.parse(milestone['date']) if milestone
|
27
|
+
|
28
|
+
nil
|
29
|
+
end
|
30
|
+
|
31
|
+
# Returns the Date for a requested milestone ONLY FROM THE ACTIVE workflow table
|
32
|
+
# @param [String] repo repository name
|
33
|
+
# @param [String] druid object id
|
34
|
+
# @param [String] milestone name of the milestone being queried for
|
35
|
+
# @return [Time] when the milestone was achieved. Returns nil if the milestone does not exist
|
36
|
+
# @example An example lifecycle xml from the workflow service.
|
37
|
+
# <lifecycle objectId="druid:ct011cv6501">
|
38
|
+
# <milestone date="2010-04-27T11:34:17-0700">registered</milestone>
|
39
|
+
# <milestone date="2010-04-29T10:12:51-0700">inprocess</milestone>
|
40
|
+
# <milestone date="2010-06-15T16:08:58-0700">released</milestone>
|
41
|
+
# </lifecycle>
|
42
|
+
def active_lifecycle(repo, druid, milestone)
|
43
|
+
doc = query_lifecycle(repo, druid, true)
|
44
|
+
milestone = doc.at_xpath("//lifecycle/milestone[text() = '#{milestone}']")
|
45
|
+
return Time.parse(milestone['date']) if milestone
|
46
|
+
|
47
|
+
nil
|
48
|
+
end
|
49
|
+
|
50
|
+
# @return [Hash]
|
51
|
+
def milestones(repo, druid)
|
52
|
+
doc = query_lifecycle(repo, druid)
|
53
|
+
doc.xpath('//lifecycle/milestone').collect do |node|
|
54
|
+
{ milestone: node.text, at: Time.parse(node['date']), version: node['version'] }
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
# @return [Nokogiri::XML::Document]
|
61
|
+
def query_lifecycle(repo, druid, active_only = false)
|
62
|
+
req = "#{repo}/objects/#{druid}/lifecycle"
|
63
|
+
req += '?active-only=true' if active_only
|
64
|
+
Nokogiri::XML(requestor.request(req))
|
65
|
+
end
|
66
|
+
|
67
|
+
attr_reader :requestor
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|