dor-workflow-client 3.0.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
[![Build Status](https://travis-ci.org/sul-dlss/dor-workflow-service.svg?branch=master)](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
|