lyber-core 6.1.1 → 7.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 72f25a04a8a79879923e52f8a0ba9e8fbb7d7a92deaf195961548cab5898baf2
4
- data.tar.gz: 9dd75e18b11858d897a1dcdeabb0841595bc1a5db02fed17fe84bdf78c7a249d
3
+ metadata.gz: 9594bf0c91b30860cdc8580d1e7e53b47ab5cbf64b9c7be0738e43e9020d9dc8
4
+ data.tar.gz: 1e3bfe3e564263ee64b681c38df4c0ca84a3d1b90716b68be4654ac4b23ebbbb
5
5
  SHA512:
6
- metadata.gz: 479c21c2be8a01e3545035009cfda6c2655e5d78f8e191a5e901be7e33eec7ff2f5b3a0623afce4d73edab1b31f79da0c43f3e0afa379dd40914079ee248476f
7
- data.tar.gz: edeed4efdf04ee301091f104c1e40047a9f124cfe269be8de88103a0b8ec27632298d9f9a06a1c379b98c0d019131f785721777be41fba924cf92280d6d60b4a
6
+ metadata.gz: 6dc1ddef3619e90a55e8f1dc8d8b5ce1fdb832fe0f36a1d14ab7be9e0e2ff2ac76753d7822bea43bf44fc33e846e603a6a328b29562bb526ec4a555bf9b323f9
7
+ data.tar.gz: 881fbd6acd736e7e1c020bd50149436359ac880b0804188662a039e97a70f3fc15e8e7e259b71b3a37d6f56742bb605fa2847f87358759f9e9801e333fb14493
data/README.md CHANGED
@@ -1,31 +1,30 @@
1
- [![Build Status](https://travis-ci.org/sul-dlss/lyber-core.svg?branch=master)](https://travis-ci.org/sul-dlss/lyber-core)
2
- [![Coverage Status](https://coveralls.io/repos/github/sul-dlss/lyber-core/badge.svg?branch=master)](https://coveralls.io/github/sul-dlss/lyber-core?branch=master)
1
+ [![CircleCI](https://circleci.com/gh/sul-dlss/lyber-core/tree/main.svg?style=svg)](https://circleci.com/gh/sul-dlss/lyber-core/tree/main)
2
+ [![Test Coverage](https://api.codeclimate.com/v1/badges/472f67659e513e3d8ffa/test_coverage)](https://codeclimate.com/github/sul-dlss/lyber-core/test_coverage)
3
+ [![Maintainability](https://api.codeclimate.com/v1/badges/472f67659e513e3d8ffa/maintainability)](https://codeclimate.com/github/sul-dlss/lyber-core/maintainability)
3
4
  [![Gem Version](https://badge.fury.io/rb/lyber-core.svg)](https://badge.fury.io/rb/lyber-core)
4
5
 
5
6
  # lyber_core
6
7
 
7
8
  ## Robot Creation
8
9
 
9
- Create a class that mixes in `LyberCore::Robot`
10
+ Create a class that subclasses `LyberCore::Robot`
10
11
 
11
- * In the initializer, call `super` with the repository, workflow name, step name
12
- * Your class `#perform` method will perform the actual work, with `druid` passed in as the one and only argument
12
+ * In the initializer, call `super` with the workflow name, step name
13
+ * Your class `#perform_work` method will perform the actual work; `druid` is available as an instance variable.
13
14
 
14
15
  ```ruby
15
16
  module Robots
16
17
  module DorRepo
17
18
  module Accession
18
19
 
19
- class Shelve
20
- include LyberCore::Robot
20
+ class Shelve < LyberCore::Robot
21
21
 
22
22
  def initialize
23
- super('dor', 'accessionWF', 'shelve')
23
+ super('accessionWF', 'shelve')
24
24
  end
25
25
 
26
- def perform druid
27
- obj = Dor::Item.find(druid)
28
- obj.shelve
26
+ def perform_work
27
+ cocina_object.shelve
29
28
  end
30
29
 
31
30
  end
@@ -42,24 +41,22 @@ module Robots
42
41
  module DorRepo
43
42
  module Accession
44
43
 
45
- class Shelve
46
- include LyberCore::Robot
44
+ class Shelve < LyberCore::Robot
47
45
 
48
46
  def initialize
49
- super('dor', 'accessionWF', 'shelve')
47
+ super('accessionWF', 'shelve')
50
48
  end
51
49
 
52
- def perform druid
53
- obj = Dor::Item.find(druid)
50
+ def perform
54
51
  if some_logic_here_to_determine_if_shelving_occurs
55
- obj.shelve
56
- return LyberCore::Robot::ReturnState.new(status: 'completed') # set the final state to completed
57
- # return LyberCore::Robot::ReturnState.new(status: 'completed', note: 'some custom note to pass back to workflow') # set the final state to completed with a custom note
52
+ cocina_object.shelve
53
+ return LyberCore::ReturnState.new(status: 'completed') # set the final state to completed
54
+ # return LyberCore::ReturnState.new(status: 'completed', note: 'some custom note to pass back to workflow') # set the final state to completed with a custom note
58
55
 
59
56
  else
60
57
  # just return skipped if we did nothing
61
- return LyberCore::Robot::ReturnState.new(status: 'skipped') # set the final state to skipped
62
- # return LyberCore::Robot::ReturnState.new(status: 'skipped', note: 'some custom note to pass back to workflow') # set the final state to skipped with a custom note
58
+ return LyberCore::ReturnState.new(status: 'skipped') # set the final state to skipped
59
+ # return LyberCore::ReturnState.new(status: 'skipped', note: 'some custom note to pass back to workflow') # set the final state to skipped with a custom note
63
60
  end
64
61
  end
65
62
 
@@ -72,50 +69,58 @@ end
72
69
 
73
70
  ## Robot Environment Setup
74
71
 
75
- * Create a `config/boot.rb` file to load the classpath, classes and configuration that your robot will need in order to run.
76
- See the [boot.rb file from the Common-Accessioning robot suite](https://github.com/sul-dlss/common-accessioning/blob/master/config/boot.rb) as an example
77
-
78
- * Add `require 'resque/tasks'` to your `Rakefile`
72
+ Create a `config/boot.rb` containing:
73
+ ```
74
+ require 'rubygems'
75
+ require 'bundler/setup'
76
+ Bundler.require(:default)
79
77
 
80
- * Create an `environment` task within your `Rakefile` that requires your `config/boot.rb` file
78
+ LyberCore::Boot.up(__dir__)
81
79
 
82
- #### Example Rakefile modifications
83
- ```ruby
84
- require 'robot-controller/tasks'
85
- ...
86
- task :environment do
87
- require_relative 'config/boot'
88
- end
80
+ # Any additional robot-specific configuratio.
89
81
  ```
90
82
 
91
- ## Start the Robot
92
-
93
- * Use rake to start your robot, specifying the Resque queue as the environment variable `QUEUE`
83
+ The configuration must include:
84
+ ```
85
+ redis_url: ~
94
86
 
87
+ workflow:
88
+ url: http://workflow.example.com/workflow
89
+ logfile: 'log/workflow_service.log'
90
+ shift_age: 'weekly'
91
+ timeout: 60
95
92
  ```
96
- $ QUEUE=accessionWF_shelve rake environment workers
93
+
94
+ And optionally:
97
95
  ```
96
+ # For Dor Services Client
97
+ dor_services:
98
+ url: 'https://dor-services-test.stanford.test'
99
+ token: secret-token
98
100
 
99
- ## Enqueing a Job
101
+ # For Cocina::Models::Mapping::Purl
102
+ purl_url: 'https://purl-example.stanford.edu'
100
103
 
101
- ```ruby
102
- require 'resque'
103
- Resque.enqueue_to('accessionWF_shelve'.to_sym, Robot::DorRepo::Accession::Shelve, 'druid:aa123bb4567')
104
+ # For DruidTools::Druid
105
+ stacks:
106
+ local_workspace_root: ~
104
107
  ```
105
108
 
109
+ The following environment variables can optionally be set:
110
+ * ROBOT_ENVIRONMENT
111
+ * ROBOT_LOG_LEVEL
106
112
 
107
- ## Releases
108
- * **4.0** Remove unused classes and dependencies
109
- * **3.0** Robot overhaul. Use `resque` for job management and `bluepill` for process management
110
- * **2.1.1** Relax dor-services-gem version requirement
111
- * **2.0** Moved what was left of DorService (namely get_objects_for_workstep()) to dor-services' Dor::WorkflowService. Removed IdentityMetadata and DublinCore XML models. Factored out all remaining global constants. Removed unnecessary dependencies.
112
- * **1.3** Started to use Dor::Config for workspace configuration
113
- * **1.0.0** Factored all Dor::* classes and object models out of lyber-core and into a separate dor-services gem. WARNING: MAY BREAK COMPATIBILITY WITH PREVIOUS DOR-ENABLED CODE.
114
- * **0.9.8** Created branch for legacy work "0.9-legacy". Robots can now be configured with fully qualified workflows for prerequisites
115
- eg <i>dor:googleScannedBookWF:register-object</i>
116
- * **0.9.2** Workflow bug fixes. Last version that supports active-fedora 1.0.7
117
- * We recommend that you **DO NOT USE** any version older than these
113
+ ## Robot Testing
114
+ Include the following in `rspec/spec_helper.rb`:
115
+ ```
116
+ ENV['ROBOT_ENVIRONMENT'] = 'test'
117
+ require File.expand_path("#{__dir__}/../config/boot")
118
118
 
119
- ## Copyright
119
+ include LyberCore::Rspec
120
+ ```
120
121
 
121
- Copyright (c) 2014-16 Stanford University Library. See LICENSE for details.
122
+ Robots can be invoked with:
123
+ ```
124
+ test_perform(robot, druid)
125
+ ```
126
+ to avoid the workflow updates in `perform()`.
@@ -0,0 +1,81 @@
1
+ # frozen_string_literal: true
2
+
3
+ # The following is required in config/boot.rb
4
+ # require 'rubygems'
5
+ # require 'bundler/setup'
6
+ # Bundler.require(:default)
7
+
8
+ # LyberCore::Boot.up(__dir__)
9
+
10
+ module LyberCore
11
+ # Boots up the robot environment, including configuration, logging, clients, and Sidekiq.
12
+ class Boot
13
+ def self.up(config_dir)
14
+ new(config_dir).perform
15
+ end
16
+
17
+ def initialize(config_dir)
18
+ @config_dir = config_dir
19
+ end
20
+
21
+ def perform
22
+ boot_config
23
+ boot_dsa
24
+ boot_cocina_models
25
+ boot_sidekiq
26
+ end
27
+
28
+ def environment
29
+ @environment ||= ENV['ROBOT_ENVIRONMENT'] ||= 'development'
30
+ end
31
+
32
+ def boot_config
33
+ Config.setup do |config|
34
+ config.const_name = 'Settings'
35
+ config.use_env = true
36
+ config.env_prefix = 'SETTINGS'
37
+ config.env_separator = '__'
38
+ end
39
+ Config.load_and_set_settings(
40
+ Config.setting_files(File.expand_path(config_dir), environment)
41
+ )
42
+ end
43
+
44
+ private
45
+
46
+ attr_reader :config_dir
47
+
48
+ def robot_root
49
+ @robot_root ||= File.expand_path("#{config_dir}/..")
50
+ end
51
+
52
+ def robot_log
53
+ Sidekiq::Logger.new(File.join(robot_root, "log/#{environment}.log")).tap do |log|
54
+ log.level = Logger::SEV_LABEL.index(ENV.fetch('ROBOT_LOG_LEVEL', nil)) || Logger::INFO
55
+ end
56
+ end
57
+
58
+ def boot_dsa
59
+ return unless Settings.dor_services&.url
60
+
61
+ Dor::Services::Client.configure(url: Settings.dor_services.url,
62
+ token: Settings.dor_services.token,
63
+ enable_get_retries: true)
64
+ end
65
+
66
+ def boot_cocina_models
67
+ Cocina::Models::Mapping::Purl.base_url = Settings.purl_url if Settings.purl_url
68
+ end
69
+
70
+ def boot_sidekiq
71
+ return if environment == 'test'
72
+
73
+ Sidekiq.configure_server do |config|
74
+ config.logger = robot_log
75
+ config.redis = { url: Settings.redis_url }
76
+ # For Sidekiq Pro
77
+ config.super_fetch!
78
+ end
79
+ end
80
+ end
81
+ end
@@ -1,27 +1,26 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # this object defines the allowed states robots can optionally return upon completion
4
- # if the return value of the "perform" step is an object of this type and the status value is set an allowed value,
5
- # it will be used to set the final workflow state for that druid
6
3
  module LyberCore
7
- module Robot
8
- class ReturnState
9
- attr_reader :status
10
- attr_accessor :note
11
- ALLOWED_RETURN_STATES = %w[completed skipped waiting noop].freeze
12
- DEFAULT_RETURN_STATE = 'completed'
4
+ # this object defines the allowed states robots can optionally return upon completion
5
+ # if the return value of the "perform" step is an object of this type and the status value is set an allowed value,
6
+ # it will be used to set the final workflow state for that druid
7
+ class ReturnState
8
+ attr_reader :status
9
+ attr_accessor :note
13
10
 
14
- def initialize(params = {})
15
- self.status = params[:status] || DEFAULT_RETURN_STATE
16
- self.note = params[:note] || ''
17
- end
11
+ ALLOWED_RETURN_STATES = %w[completed skipped waiting noop].freeze
12
+ DEFAULT_RETURN_STATE = 'completed'
18
13
 
19
- def status=(value)
20
- state = value.to_s.downcase
21
- raise 'invalid return state' unless ALLOWED_RETURN_STATES.include? state
14
+ def initialize(params = {})
15
+ self.status = params[:status] || DEFAULT_RETURN_STATE
16
+ self.note = params[:note] || ''
17
+ end
18
+
19
+ def status=(value)
20
+ state = value.to_s.downcase
21
+ raise 'invalid return state' unless ALLOWED_RETURN_STATES.include? state
22
22
 
23
- @status = state
24
- end
23
+ @status = state
25
24
  end
26
25
  end
27
26
  end
@@ -1,112 +1,119 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'benchmark'
4
-
5
3
  module LyberCore
6
- module Robot
7
- # Add the ClassMethods to the class this is being mixed into
8
- def self.included(base)
9
- base.extend ClassMethods
10
- end
4
+ # Base class for all robots.
5
+ # Subclasses should implement the #perform_work method.
6
+ class Robot
7
+ include Sidekiq::Job
8
+ sidekiq_options retry: 0
11
9
 
12
- module ClassMethods
13
- # Called by job-manager on derived-class
14
- # Instantiate the Robot and call #work with the passed in druid
15
- def perform(druid, *context)
16
- bot = new
17
- bot.work druid, context
18
- end
19
- end
10
+ attr_reader :workflow_name, :process, :druid
20
11
 
21
- attr_accessor :check_queued_status
22
- attr_reader :workflow_name, :process
12
+ delegate :lane_id, to: :workflow
23
13
 
24
- def initialize(workflow_name, process, check_queued_status: true)
25
- Signal.trap('QUIT') { puts "#{Process.pid} ignoring SIGQUIT" } # SIGQUIT ignored to let the robot finish
14
+ def initialize(workflow_name, process)
26
15
  @workflow_name = workflow_name
27
16
  @process = process
28
- @check_queued_status = check_queued_status
29
17
  end
30
18
 
31
19
  def workflow_service
32
- raise 'The workflow_service method must be implemented on the class that includes LyberCore::Robot'
20
+ @workflow_service ||= WorkflowClientFactory.build(logger: logger)
21
+ end
22
+
23
+ def object_client
24
+ @object_client ||= Dor::Services::Client.object(druid)
25
+ end
26
+
27
+ def cocina_object
28
+ @cocina_object ||= object_client.find
29
+ end
30
+
31
+ def druid_object
32
+ @druid_object ||= DruidTools::Druid.new(druid, Settings.stacks.local_workspace_root)
33
33
  end
34
34
 
35
35
  # Sets up logging, timing and error handling of the job
36
- # Calls the #perform method, then sets workflow to 'completed' or 'error' depending on success
36
+ # Calls the #perform_work method, then sets workflow to 'completed' or 'error' depending on success
37
37
  # rubocop:disable Metrics/AbcSize
38
- # rubocop:disable Metrics/CyclomaticComplexity
39
- # rubocop:disable Metrics/PerceivedComplexity
40
- def work(druid, context)
41
- Honeybadger.context(druid: druid, process: process, workflow_name: workflow_name) if defined? Honeybadger
42
- workflow = workflow(druid)
43
- LyberCore::Log.set_logfile($stdout) # let process manager handle logging
44
- LyberCore::Log.info "#{druid} processing #{process} (#{workflow_name})"
45
- return if check_queued_status && !item_queued?(druid)
38
+ # rubocop:disable Metrics/MethodLength
39
+ def perform(druid)
40
+ @druid = druid
41
+ Honeybadger.context(druid: druid, process: process, workflow_name: workflow_name)
42
+
43
+ logger.info "#{druid} processing #{process} (#{workflow_name})"
44
+ return unless check_item_queued?
46
45
 
47
46
  # this is the default note to pass back to workflow service,
48
- # but it can be overriden by a robot that uses the Lybercore::Robot::ReturnState
47
+ # but it can be overriden by a robot that uses the Robots::ReturnState
49
48
  # object to return a status
50
49
  note = Socket.gethostname
51
50
 
52
51
  # update the workflow status to indicate that started
53
- workflow.start(note)
52
+ workflow.start!(note)
54
53
 
55
54
  result = nil
56
55
  elapsed = Benchmark.realtime do
57
- result = if method(:perform).arity == 1
58
- perform druid # implemented in the mixed-in robot class
59
- else
60
- perform druid, context
61
- end
56
+ result = perform_work
62
57
  end
63
58
 
64
59
  # the final workflow state is determined by the return value of the perform step, if it is a ReturnState object,
65
60
  # we will use the defined status, otherwise default to completed
66
61
  # if a note is passed back, we will also use that instead of the default
67
- if result.class == LyberCore::Robot::ReturnState
62
+ if result.instance_of?(ReturnState)
68
63
  workflow_state = result.status
69
64
  note = result.note unless result.note.blank?
70
65
  else
71
66
  workflow_state = 'completed'
72
67
  end
73
- # update the workflow status from its current state to the state returned by perform (or 'completed' as the default)
68
+ # update the workflow status from its current state to the state returned by perform
69
+ # (or 'completed' as the default)
74
70
  # noop allows a robot to not set a workflow as complete, e.g., if that is delegated to another service.
75
- workflow.complete(workflow_state, elapsed, note) unless workflow_state == 'noop'
71
+ workflow.complete!(workflow_state, elapsed, note) unless workflow_state == 'noop'
76
72
 
77
- LyberCore::Log.info "Finished #{druid} in #{sprintf('%0.4f', elapsed)}s"
73
+ logger.info "Finished #{druid} in #{format('%0.4f', elapsed)}s"
78
74
  rescue StandardError => e
79
- Honeybadger.notify(e) if defined? Honeybadger
80
- begin
81
- LyberCore::Log.error e.message + "\n" + e.backtrace.join("\n")
82
- workflow.error(e.message, Socket.gethostname)
83
- rescue StandardError => e
84
- LyberCore::Log.error "Cannot set #{druid} to status='error'\n#{e.message}\n#{e.backtrace.join("\n")}"
85
- raise e # send exception to Resque failed queue
86
- end
75
+ handle_error(e)
76
+ end
77
+ # rubocop:enable Metrics/AbcSize
78
+ # rubocop:enable Metrics/MethodLength
79
+
80
+ # Work performed by the robot.
81
+ # This method is to be implemented by robot subclasses.
82
+ def perform_work
83
+ raise NotImplementedError
84
+ end
85
+
86
+ def bare_druid
87
+ @bare_druid = druid.delete_prefix('druid:')
87
88
  end
88
- # rubocop:enable Metrics/AbcSize
89
- # rubocop:enable Metrics/CyclomaticComplexity
90
- # rubocop:enable Metrics/PerceivedComplexity
91
89
 
92
- private
90
+ private
91
+
92
+ # rubocop:disable Metrics/AbcSize
93
+ def handle_error(error)
94
+ Honeybadger.notify(error)
95
+ logger.error "#{error.message}\n#{error.backtrace.join("\n")}"
96
+ workflow.error!(error.message, Socket.gethostname)
97
+ rescue StandardError => e
98
+ logger.error "Cannot set #{druid} to status='error'\n#{e.message}\n#{e.backtrace.join("\n")}"
99
+ raise e # send exception to Sidekiq failed queue
100
+ end
101
+ # rubocop:enable Metrics/AbcSize
93
102
 
94
- def workflow(druid)
95
- Workflow.new(workflow_service: workflow_service,
96
- druid: druid,
97
- workflow_name: workflow_name,
98
- process: process)
103
+ def workflow
104
+ @workflow ||= Workflow.new(workflow_service: workflow_service,
105
+ druid: druid,
106
+ workflow_name: workflow_name,
107
+ process: process)
99
108
  end
100
109
 
101
- def item_queued?(druid)
102
- status = workflow_service.workflow_status(druid: druid,
103
- workflow: workflow_name,
104
- process: process)
105
- return true if status =~ /queued/i
110
+ def check_item_queued?
111
+ return true if /queued/i.match?(workflow.status)
106
112
 
107
- msg = "Item #{druid} is not queued for #{process} (#{workflow_name}), but has status of '#{status}'. Will skip processing"
108
- Honeybadger.notify(msg) if defined? Honeybadger
109
- LyberCore::Log.warn msg
113
+ msg = "Item #{druid} is not queued for #{process} (#{workflow_name}), " \
114
+ "but has status of '#{workflow.status}'. Will skip processing"
115
+ Honeybadger.notify(msg)
116
+ logger.warn(msg)
110
117
  false
111
118
  end
112
119
  end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LyberCore
4
+ # Methods to support testing robots
5
+ module Rspec
6
+ def test_perform(robot, druid)
7
+ allow(robot).to receive(:druid).and_return(druid)
8
+ robot.perform_work
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LyberCore
4
+ VERSION = '7.0.0'
5
+ end
@@ -10,7 +10,7 @@ module LyberCore
10
10
  @process = process
11
11
  end
12
12
 
13
- def start(note)
13
+ def start!(note)
14
14
  workflow_service.update_status(druid: druid,
15
15
  workflow: workflow_name,
16
16
  process: process,
@@ -19,7 +19,7 @@ module LyberCore
19
19
  note: note)
20
20
  end
21
21
 
22
- def complete(status, elapsed, note)
22
+ def complete!(status, elapsed, note)
23
23
  workflow_service.update_status(druid: druid,
24
24
  workflow: workflow_name,
25
25
  process: process,
@@ -28,7 +28,7 @@ module LyberCore
28
28
  note: note)
29
29
  end
30
30
 
31
- def error(error_msg, error_text)
31
+ def error!(error_msg, error_text)
32
32
  workflow_service.update_error_status(druid: druid,
33
33
  workflow: workflow_name,
34
34
  process: process,
@@ -36,7 +36,17 @@ module LyberCore
36
36
  error_text: error_text)
37
37
  end
38
38
 
39
- private
39
+ def status
40
+ @status ||= workflow_service.workflow_status(druid: druid,
41
+ workflow: workflow_name,
42
+ process: process)
43
+ end
44
+
45
+ def lane_id
46
+ @lane_id ||= workflow_service.process(pid: druid, workflow_name: workflow_name, process: process).lane_id
47
+ end
48
+
49
+ private
40
50
 
41
51
  attr_reader :workflow_service, :druid, :workflow_name, :process
42
52
  end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LyberCore
4
+ # Factory for creating a workflow client
5
+ class WorkflowClientFactory
6
+ def self.build(logger:)
7
+ Dor::Workflow::Client.new(url: Settings.workflow.url, logger: logger, timeout: Settings.workflow.timeout)
8
+ end
9
+ end
10
+ end
data/lib/lyber_core.rb CHANGED
@@ -1,6 +1,21 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'lyber_core/log'
4
- require 'lyber_core/workflow'
5
- require 'lyber_core/robot'
6
- require 'lyber_core/return_state'
3
+ require 'benchmark'
4
+ require 'socket'
5
+ require 'active_support'
6
+ require 'active_support/core_ext/object/blank' # String#blank?
7
+ require 'active_support/core_ext/module/delegation'
8
+ require 'sidekiq'
9
+ require 'honeybadger'
10
+ require 'dor/workflow/client'
11
+ require 'dor/services/client'
12
+ require 'druid-tools'
13
+ require 'zeitwerk'
14
+
15
+ loader = Zeitwerk::Loader.for_gem
16
+ loader.ignore("#{__dir__}/lyber-core.rb")
17
+ loader.setup
18
+
19
+ # Elon Musk: "Robots will be able to do everything better than us"
20
+ module LyberCore
21
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lyber-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 6.1.1
4
+ version: 7.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alpana Pande
@@ -13,19 +13,19 @@ authors:
13
13
  - Michael Klein
14
14
  - Darren Weber
15
15
  - Peter Mangiafico
16
- autorequire:
16
+ autorequire:
17
17
  bindir: bin
18
18
  cert_chain: []
19
- date: 2020-03-29 00:00:00.000000000 Z
19
+ date: 2023-02-21 00:00:00.000000000 Z
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
22
- name: coveralls
22
+ name: activesupport
23
23
  requirement: !ruby/object:Gem::Requirement
24
24
  requirements:
25
25
  - - ">="
26
26
  - !ruby/object:Gem::Version
27
27
  version: '0'
28
- type: :development
28
+ type: :runtime
29
29
  prerelease: false
30
30
  version_requirements: !ruby/object:Gem::Requirement
31
31
  requirements:
@@ -33,27 +33,55 @@ dependencies:
33
33
  - !ruby/object:Gem::Version
34
34
  version: '0'
35
35
  - !ruby/object:Gem::Dependency
36
- name: rake
36
+ name: config
37
37
  requirement: !ruby/object:Gem::Requirement
38
38
  requirements:
39
39
  - - ">="
40
40
  - !ruby/object:Gem::Version
41
- version: 0.8.7
42
- type: :development
41
+ version: '0'
42
+ type: :runtime
43
43
  prerelease: false
44
44
  version_requirements: !ruby/object:Gem::Requirement
45
45
  requirements:
46
46
  - - ">="
47
47
  - !ruby/object:Gem::Version
48
- version: 0.8.7
48
+ version: '0'
49
49
  - !ruby/object:Gem::Dependency
50
- name: rdoc
50
+ name: dor-services-client
51
+ requirement: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - "~>"
54
+ - !ruby/object:Gem::Version
55
+ version: '12.10'
56
+ type: :runtime
57
+ prerelease: false
58
+ version_requirements: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - "~>"
61
+ - !ruby/object:Gem::Version
62
+ version: '12.10'
63
+ - !ruby/object:Gem::Dependency
64
+ name: dor-workflow-client
65
+ requirement: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - "~>"
68
+ - !ruby/object:Gem::Version
69
+ version: '5.0'
70
+ type: :runtime
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - "~>"
75
+ - !ruby/object:Gem::Version
76
+ version: '5.0'
77
+ - !ruby/object:Gem::Dependency
78
+ name: druid-tools
51
79
  requirement: !ruby/object:Gem::Requirement
52
80
  requirements:
53
81
  - - ">="
54
82
  - !ruby/object:Gem::Version
55
83
  version: '0'
56
- type: :development
84
+ type: :runtime
57
85
  prerelease: false
58
86
  version_requirements: !ruby/object:Gem::Requirement
59
87
  requirements:
@@ -61,27 +89,41 @@ dependencies:
61
89
  - !ruby/object:Gem::Version
62
90
  version: '0'
63
91
  - !ruby/object:Gem::Dependency
64
- name: rspec
92
+ name: honeybadger
93
+ requirement: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ version: '0'
98
+ type: :runtime
99
+ prerelease: false
100
+ version_requirements: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - ">="
103
+ - !ruby/object:Gem::Version
104
+ version: '0'
105
+ - !ruby/object:Gem::Dependency
106
+ name: sidekiq
65
107
  requirement: !ruby/object:Gem::Requirement
66
108
  requirements:
67
109
  - - "~>"
68
110
  - !ruby/object:Gem::Version
69
- version: '3.0'
70
- type: :development
111
+ version: '6.2'
112
+ type: :runtime
71
113
  prerelease: false
72
114
  version_requirements: !ruby/object:Gem::Requirement
73
115
  requirements:
74
116
  - - "~>"
75
117
  - !ruby/object:Gem::Version
76
- version: '3.0'
118
+ version: '6.2'
77
119
  - !ruby/object:Gem::Dependency
78
- name: rubocop
120
+ name: zeitwerk
79
121
  requirement: !ruby/object:Gem::Requirement
80
122
  requirements:
81
123
  - - ">="
82
124
  - !ruby/object:Gem::Version
83
125
  version: '0'
84
- type: :development
126
+ type: :runtime
85
127
  prerelease: false
86
128
  version_requirements: !ruby/object:Gem::Requirement
87
129
  requirements:
@@ -89,7 +131,35 @@ dependencies:
89
131
  - !ruby/object:Gem::Version
90
132
  version: '0'
91
133
  - !ruby/object:Gem::Dependency
92
- name: rubocop-rspec
134
+ name: rake
135
+ requirement: !ruby/object:Gem::Requirement
136
+ requirements:
137
+ - - ">="
138
+ - !ruby/object:Gem::Version
139
+ version: 0.8.7
140
+ type: :development
141
+ prerelease: false
142
+ version_requirements: !ruby/object:Gem::Requirement
143
+ requirements:
144
+ - - ">="
145
+ - !ruby/object:Gem::Version
146
+ version: 0.8.7
147
+ - !ruby/object:Gem::Dependency
148
+ name: rspec
149
+ requirement: !ruby/object:Gem::Requirement
150
+ requirements:
151
+ - - "~>"
152
+ - !ruby/object:Gem::Version
153
+ version: '3.0'
154
+ type: :development
155
+ prerelease: false
156
+ version_requirements: !ruby/object:Gem::Requirement
157
+ requirements:
158
+ - - "~>"
159
+ - !ruby/object:Gem::Version
160
+ version: '3.0'
161
+ - !ruby/object:Gem::Dependency
162
+ name: rubocop
93
163
  requirement: !ruby/object:Gem::Requirement
94
164
  requirements:
95
165
  - - "~>"
@@ -103,7 +173,21 @@ dependencies:
103
173
  - !ruby/object:Gem::Version
104
174
  version: '1.24'
105
175
  - !ruby/object:Gem::Dependency
106
- name: yard
176
+ name: rubocop-rspec
177
+ requirement: !ruby/object:Gem::Requirement
178
+ requirements:
179
+ - - ">="
180
+ - !ruby/object:Gem::Version
181
+ version: '0'
182
+ type: :development
183
+ prerelease: false
184
+ version_requirements: !ruby/object:Gem::Requirement
185
+ requirements:
186
+ - - ">="
187
+ - !ruby/object:Gem::Version
188
+ version: '0'
189
+ - !ruby/object:Gem::Dependency
190
+ name: simplecov
107
191
  requirement: !ruby/object:Gem::Requirement
108
192
  requirements:
109
193
  - - ">="
@@ -129,16 +213,18 @@ files:
129
213
  - README.md
130
214
  - lib/lyber-core.rb
131
215
  - lib/lyber_core.rb
132
- - lib/lyber_core/log.rb
216
+ - lib/lyber_core/boot.rb
133
217
  - lib/lyber_core/return_state.rb
134
218
  - lib/lyber_core/robot.rb
219
+ - lib/lyber_core/rspec.rb
220
+ - lib/lyber_core/version.rb
135
221
  - lib/lyber_core/workflow.rb
136
- - lib/tasks/rdoc.rake
222
+ - lib/lyber_core/workflow_client_factory.rb
137
223
  homepage: http://github.com/sul-dlss/lyber-core
138
224
  licenses:
139
225
  - Apache-2.0
140
226
  metadata: {}
141
- post_install_message:
227
+ post_install_message:
142
228
  rdoc_options: []
143
229
  require_paths:
144
230
  - lib
@@ -146,15 +232,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
146
232
  requirements:
147
233
  - - ">="
148
234
  - !ruby/object:Gem::Version
149
- version: '0'
235
+ version: '3.0'
150
236
  required_rubygems_version: !ruby/object:Gem::Requirement
151
237
  requirements:
152
238
  - - ">="
153
239
  - !ruby/object:Gem::Version
154
240
  version: 1.3.6
155
241
  requirements: []
156
- rubygems_version: 3.1.2
157
- signing_key:
242
+ rubygems_version: 3.3.7
243
+ signing_key:
158
244
  specification_version: 4
159
245
  summary: Core services used by the SUL Digital Library
160
246
  test_files: []
@@ -1,105 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module LyberCore
4
- class LyberCore::Log
5
- require 'logger'
6
-
7
- # Default values
8
- DEFAULT_LOGFILE = '/tmp/lybercore_log.log' # TODO: change to STDOUT?
9
- DEFAULT_LOG_LEVEL = Logger::INFO
10
- DEFAULT_FORMATTER = proc do |s, t, p, m|
11
- "%5s [%s] (%s) %s :: %s\n" % [s, t.strftime('%Y-%m-%d %H:%M:%S'), $$, p, m]
12
- end
13
-
14
- # Initial state
15
- @@logfile = DEFAULT_LOGFILE
16
- @@log ||= Logger.new(@@logfile)
17
- # $stdout.reopen(@@logfile)
18
- # $stderr.reopen(@@logfile)
19
- @@log.level = DEFAULT_LOG_LEVEL
20
- @@log.formatter = DEFAULT_FORMATTER
21
-
22
- # Restore LyberCore::Log to its default state
23
- def Log.restore_defaults
24
- @@log.level = DEFAULT_LOG_LEVEL
25
- Log.set_logfile(DEFAULT_LOGFILE)
26
- @@log.formatter = DEFAULT_FORMATTER
27
- end
28
-
29
- # The current location of the logfile
30
- def Log.logfile
31
- @@logfile
32
- end
33
-
34
- # Accepts a filename as an argument, and checks to see whether that file can be
35
- # opened for writing. If it can be opened, it closes the existing Logger object
36
- # and re-opens it with the new logfile location. It raises an exception if it
37
- # cannot write to the specified logfile.
38
- def Log.set_logfile(new_logfile)
39
- current_log_level = @@log.level
40
- current_formatter = @@log.formatter
41
- @@log = Logger.new(new_logfile)
42
- @@logfile = new_logfile
43
- @@log.level = current_log_level
44
- @@log.formatter = current_formatter
45
- rescue Exception => e
46
- raise e, "Couldn't initialize logfile #{new_logfile} because\n#{e.message}: #{e.backtrace.join(%(\n))}}"
47
- end
48
-
49
- # Set the log level.
50
- # See http://ruby-doc.org/core/classes/Logger.html for more info.
51
- # Possible values are:
52
- # Logger::FATAL (4): an unhandleable error that results in a program crash
53
- # Logger::ERROR (3): a handleable error condition
54
- # Logger::WARN (2): a warning
55
- # Logger::INFO (1): generic (useful) information about system operation
56
- # Logger::DEBUG (0): low-level information for developers
57
- def Log.set_level(loglevel)
58
- if [0, 1, 2, 3, 4].include? loglevel
59
- @@log.level = loglevel
60
- @@log.debug "Setting LyberCore::Log.level to #{loglevel}"
61
- else
62
- @@log.warn "I received an invalid option for log level. I expected a number between 0 and 4 but I got #{loglevel}"
63
- @@log.warn "I'm setting the loglevel to 0 (debug) because you seem to be having trouble."
64
- @@log.level = 0
65
- end
66
- rescue Exception => e
67
- raise e, "Couldn't set log level because\n#{e.message}: #{e.backtrace.join(%(\n))}"
68
- end
69
-
70
- # Return the current log level
71
- def Log.level
72
- @@log.level
73
- end
74
-
75
- def Log.fatal(msg)
76
- @@log.add(Logger::FATAL) { msg }
77
- end
78
-
79
- def Log.error(msg)
80
- @@log.add(Logger::ERROR) { msg }
81
- end
82
-
83
- def Log.warn(msg)
84
- @@log.add(Logger::WARN) { msg }
85
- end
86
-
87
- def Log.info(msg)
88
- @@log.add(Logger::INFO) { msg }
89
- end
90
-
91
- def Log.debug(msg)
92
- @@log.add(Logger::DEBUG) { msg }
93
- end
94
-
95
- def Log.exception(exc)
96
- msg = Log.exception_message(exc)
97
- Log.error(msg)
98
- end
99
-
100
- def Log.exception_message(exc)
101
- msg = exc.inspect.split($/).join('; ') + "\n"
102
- msg << exc.backtrace.join("\n") if exc.backtrace
103
- end
104
- end
105
- end
data/lib/tasks/rdoc.rake DELETED
@@ -1,33 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- desc 'Generate RDoc'
4
- task doc: ['doc:generate']
5
-
6
- namespace :doc do
7
- project_root = File.expand_path(File.join(File.dirname(__FILE__), '..', '..'))
8
- doc_destination = File.join(project_root, 'rdoc')
9
-
10
- begin
11
- require 'yard'
12
- require 'yard/rake/yardoc_task'
13
-
14
- YARD::Rake::YardocTask.new(:generate) do |yt|
15
- yt.files = Dir.glob(File.join(project_root, 'lib', '*.rb')) +
16
- Dir.glob(File.join(project_root, 'lib', '**', '*.rb')) +
17
- [File.join(project_root, 'README.rdoc')] +
18
- [File.join(project_root, 'LICENSE')]
19
-
20
- yt.options = ['--output-dir', doc_destination, '--readme', 'README.rdoc']
21
- end
22
- rescue LoadError
23
- desc 'Generate YARD Documentation'
24
- task :generate do
25
- abort 'Please install the YARD gem to generate rdoc.'
26
- end
27
- end
28
-
29
- desc 'Remove generated documenation'
30
- task :clean do
31
- rm_r doc_destination if File.exist?(doc_destination)
32
- end
33
- end