sufia-models 6.0.0.rc4 → 6.0.0

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.
Files changed (31) hide show
  1. checksums.yaml +4 -4
  2. data/app/actors/sufia/generic_file/actor.rb +1 -1
  3. data/app/jobs/active_fedora_id_based_job.rb +22 -0
  4. data/app/jobs/active_fedora_pid_based_job.rb +5 -20
  5. data/app/jobs/audit_job.rb +5 -6
  6. data/app/jobs/characterize_job.rb +1 -1
  7. data/app/jobs/create_derivatives_job.rb +1 -1
  8. data/app/jobs/import_url_job.rb +2 -2
  9. data/app/models/batch.rb +18 -4
  10. data/app/models/checksum_audit_log.rb +2 -2
  11. data/app/models/concerns/sufia/ability.rb +7 -1
  12. data/app/models/concerns/sufia/collection_behavior.rb +1 -1
  13. data/app/models/concerns/sufia/generic_file/full_text_indexing.rb +23 -14
  14. data/app/models/concerns/sufia/generic_file/proxy_deposit.rb +1 -1
  15. data/app/models/datastreams/fits_datastream.rb +1 -36
  16. data/app/models/proxy_deposit_request.rb +6 -6
  17. data/app/services/sufia/generic_file_audit_service.rb +1 -1
  18. data/app/services/sufia/generic_file_indexing_service.rb +0 -1
  19. data/app/services/sufia/id_service.rb +2 -3
  20. data/app/services/sufia/noid.rb +1 -1
  21. data/lib/generators/sufia/models/templates/config/sufia.rb +1 -1
  22. data/lib/generators/sufia/models/templates/migrations/change_audit_log_pid_to_generic_file_id.rb +5 -0
  23. data/lib/generators/sufia/models/templates/migrations/change_proxy_deposit_request_pid_to_generic_file_id.rb +5 -0
  24. data/lib/generators/sufia/models/upgrade600_generator.rb +21 -0
  25. data/lib/sufia/models/stats/user_stat_importer.rb +20 -1
  26. data/lib/sufia/models/version.rb +1 -1
  27. data/lib/tasks/batch_cleanup.rake +19 -0
  28. data/lib/tasks/migrate.rake +21 -0
  29. data/lib/tasks/sufia-models_tasks.rake +55 -38
  30. data/sufia-models.gemspec +1 -1
  31. metadata +21 -9
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c298d5e01fec3e19368cbcf8c9dab669675fef6d
4
- data.tar.gz: 5f35bbef30f86ed7c770fdc9fb2864eeb9d98ef3
3
+ metadata.gz: c12a4f1425665634659dfd88233a2c365594589d
4
+ data.tar.gz: 06d1405c0b4f1537c071700faadc20a0264f34e8
5
5
  SHA512:
6
- metadata.gz: caa1ef71957cc6aa759a7a41d22cf99468f334aa86b0a3cce30badc6d488a6aa1eb5b2830708add33cdb5356ff8c3fe507c8771374e91da7f1ffe2c232e05442
7
- data.tar.gz: 0f21473f2cb5f7ad5be47ee563ca8ee2a70ef02357121683a0f528ea1566b9ed529ad659efc5678b64f973b217647f4ff8685bef40e513b837d1b1be118a1b44
6
+ metadata.gz: 07a66fa4a7b7c950459a91143ac460859ce38edc9a7d336badb586bbaed916c168fe468dcdcad36405fa8d653774db8ad1acc9a9da07ab42b06e066ba18a6c1e
7
+ data.tar.gz: ae73b9db8e0607bfb3dcfcab6aef808a8b88be53b8447c66db279a6071ec8433f024dfdac404a5c5167865a6df153f22b03854e625df929175fe07f98cb6a93b
@@ -31,7 +31,7 @@ module Sufia::GenericFile
31
31
  def create_content(file, file_name, path, mime_type)
32
32
  generic_file.add_file(file, path: path, original_name: file_name, mime_type: mime_type)
33
33
  generic_file.label ||= file_name
34
- generic_file.title = [file_name] if generic_file.title.blank?
34
+ generic_file.title = [generic_file.label] if generic_file.title.blank?
35
35
  save_characterize_and_record_committer do
36
36
  if Sufia.config.respond_to?(:after_create_content)
37
37
  Sufia.config.after_create_content.call(generic_file, user)
@@ -0,0 +1,22 @@
1
+ class ActiveFedoraIdBasedJob
2
+ def queue_name
3
+ :id_based
4
+ end
5
+
6
+ attr_accessor :id
7
+
8
+ def initialize(id)
9
+ self.id = id
10
+ end
11
+
12
+ def object
13
+ @object ||= ActiveFedora::Base.find(id)
14
+ end
15
+
16
+ alias_method :generic_file, :object
17
+ alias_method :generic_file_id, :id
18
+
19
+ def run
20
+ raise RuntimeError, "Define #run in a subclass"
21
+ end
22
+ end
@@ -1,22 +1,7 @@
1
- class ActiveFedoraPidBasedJob
2
- def queue_name
3
- :pid_based
4
- end
5
-
6
- attr_accessor :pid
7
-
8
- def initialize(pid)
9
- self.pid = pid
10
- end
11
-
12
- def object
13
- @object ||= ActiveFedora::Base.find(pid)
14
- end
15
-
16
- alias_method :generic_file, :object
17
- alias_method :generic_file_id, :pid
18
-
19
- def run
20
- raise RuntimeError, "Define #run in a subclass"
1
+ class ActiveFedoraPidBasedJob < ActiveFedoraIdBasedJob
2
+ extend Deprecation
3
+ def self.extended(document)
4
+ Deprecation.warn ActiveFedoraPidBasedJob, "ActiveFedoraPidBasedJob is deprecated; use ActiveFedoraIdBasedJob instead."
21
5
  end
22
6
  end
7
+
@@ -1,4 +1,4 @@
1
- class AuditJob < ActiveFedoraPidBasedJob
1
+ class AuditJob < ActiveFedoraIdBasedJob
2
2
  def queue_name
3
3
  :audit
4
4
  end
@@ -6,7 +6,7 @@ class AuditJob < ActiveFedoraPidBasedJob
6
6
  PASS = 'Passing Audit Run'
7
7
  FAIL = 'Failing Audit Run'
8
8
 
9
- attr_accessor :uri, :pid, :path
9
+ attr_accessor :uri, :id, :path
10
10
 
11
11
  # URI of the resource to audit.
12
12
  # This URI could include the actual resource (e.g. content) and the version to audit:
@@ -14,8 +14,7 @@ class AuditJob < ActiveFedoraPidBasedJob
14
14
  # but it could also just be:
15
15
  # http://localhost:8983/fedora/rest/test/a/b/c/abcxyz/content
16
16
  def initialize(id, path, uri)
17
- super(uri)
18
- self.pid = id
17
+ super(id)
19
18
  self.path = path
20
19
  self.uri = uri
21
20
  end
@@ -49,12 +48,12 @@ class AuditJob < ActiveFedoraPidBasedJob
49
48
 
50
49
  if fixity_ok
51
50
  passing = 1
52
- ChecksumAuditLog.prune_history(pid, path)
51
+ ChecksumAuditLog.prune_history(id, path)
53
52
  else
54
53
  logger.warn "***AUDIT*** Audit failed for #{uri} #{error_msg}"
55
54
  passing = 0
56
55
  end
57
- ChecksumAuditLog.create!(pass: passing, pid: pid, version: uri, dsid: path)
56
+ ChecksumAuditLog.create!(pass: passing, generic_file_id: id, version: uri, dsid: path)
58
57
  end
59
58
 
60
59
  def logger
@@ -1,4 +1,4 @@
1
- class CharacterizeJob < ActiveFedoraPidBasedJob
1
+ class CharacterizeJob < ActiveFedoraIdBasedJob
2
2
  def queue_name
3
3
  :characterize
4
4
  end
@@ -1,4 +1,4 @@
1
- class CreateDerivativesJob < ActiveFedoraPidBasedJob
1
+ class CreateDerivativesJob < ActiveFedoraIdBasedJob
2
2
  def queue_name
3
3
  :derivatives
4
4
  end
@@ -2,7 +2,7 @@ require 'net/https'
2
2
  require 'uri'
3
3
  require 'tempfile'
4
4
 
5
- class ImportUrlJob < ActiveFedoraPidBasedJob
5
+ class ImportUrlJob < ActiveFedoraIdBasedJob
6
6
 
7
7
  def queue_name
8
8
  :import_url
@@ -11,7 +11,7 @@ class ImportUrlJob < ActiveFedoraPidBasedJob
11
11
  def run
12
12
  user = User.find_by_user_key(generic_file.depositor)
13
13
 
14
- Tempfile.open(pid.gsub('/', '_')) do |f|
14
+ Tempfile.open(id.gsub('/', '_')) do |f|
15
15
  path, mime_type = copy_remote_file(generic_file.import_url, f)
16
16
  # attach downloaded file to generic file stubbed out
17
17
  if Sufia::GenericFile::Actor.new(generic_file, user).create_content(f, path, 'content', mime_type)
data/app/models/batch.rb CHANGED
@@ -10,13 +10,27 @@ class Batch < ActiveFedora::Base
10
10
  property :status, predicate: ::RDF::DC.type
11
11
 
12
12
  def self.find_or_create(id)
13
- # FIXME potential race condition in this method. Consider that `find' may raise
14
- # ObjectNotFound in multiple processes. However, Fedora should raise an error
15
- # if we try to create two objects with the same id.
16
13
  begin
17
14
  Batch.find(id)
18
15
  rescue ActiveFedora::ObjectNotFoundError
19
- Batch.create(id: id)
16
+ safe_create(id)
20
17
  end
21
18
  end
19
+
20
+ private
21
+
22
+ # This method handles most race conditions gracefully.
23
+ # If a batch with the same ID is created by another thread
24
+ # we fetch the batch that was created (rather than throwing
25
+ # an error) and continute.
26
+ def self.safe_create(id)
27
+ begin
28
+ Batch.create(id: id)
29
+ rescue ActiveFedora::IllegalOperation => ex
30
+ # This is the exception thrown by LDP when we attempt to
31
+ # create a duplicate object. If we can find the object
32
+ # then we are good to go.
33
+ Batch.find(id)
34
+ end
35
+ end
22
36
  end
@@ -1,7 +1,7 @@
1
1
  class ChecksumAuditLog < ActiveRecord::Base
2
2
 
3
3
  def self.get_audit_log(id, path, version_uri)
4
- ChecksumAuditLog.find_or_create_by(pid: id, dsid: path, version: version_uri)
4
+ ChecksumAuditLog.find_or_create_by(generic_file_id: id, dsid: path, version: version_uri)
5
5
  end
6
6
 
7
7
  # Check to see if there are previous passing logs that we can delete
@@ -16,6 +16,6 @@ class ChecksumAuditLog < ActiveRecord::Base
16
16
  end
17
17
 
18
18
  def self.logs_for(id, path)
19
- ChecksumAuditLog.where(pid: id, dsid: path).order('created_at desc, id desc')
19
+ ChecksumAuditLog.where(generic_file_id: id, dsid: path).order('created_at desc, id desc')
20
20
  end
21
21
  end
@@ -8,6 +8,7 @@ module Sufia
8
8
 
9
9
  def sufia_abilities
10
10
  generic_file_abilities
11
+ user_abilities
11
12
  featured_work_abilities
12
13
  editor_abilities
13
14
  stats_abilities
@@ -23,7 +24,10 @@ module Sufia
23
24
  can :reject, ProxyDepositRequest, receiving_user_id: current_user.id, status: 'pending'
24
25
  # a user who sent a proxy deposit request can cancel it if it's pending.
25
26
  can :destroy, ProxyDepositRequest, sending_user_id: current_user.id, status: 'pending'
26
- can :edit, ::User, id: current_user.id
27
+ end
28
+
29
+ def user_abilities
30
+ can [:edit, :update, :toggle_trophy], ::User, id: current_user.id
27
31
  end
28
32
 
29
33
  def featured_work_abilities
@@ -31,6 +35,7 @@ module Sufia
31
35
  end
32
36
 
33
37
  def generic_file_abilities
38
+ can :view_share_work, [GenericFile]
34
39
  can :create, [GenericFile, Collection] if user_groups.include? 'registered'
35
40
  end
36
41
 
@@ -51,5 +56,6 @@ module Sufia
51
56
  def depositor_for_document(document_id)
52
57
  ::GenericFile.load_instance_from_solr(document_id).depositor
53
58
  end
59
+
54
60
  end
55
61
  end
@@ -18,7 +18,7 @@ module Sufia
18
18
  # Compute the sum of each file in the collection
19
19
  # Return an integer of the result
20
20
  def bytes
21
- members.reduce(0) { |sum, gf| sum + gf.file_size.first.to_i }
21
+ members.reduce(0) { |sum, gf| sum + gf.content.size.to_i }
22
22
  end
23
23
  end
24
24
  end
@@ -14,21 +14,30 @@ module Sufia
14
14
 
15
15
  private
16
16
 
17
- def extract_content
18
- url = Blacklight.solr_config[:url] ? Blacklight.solr_config[:url] : Blacklight.solr_config["url"] ? Blacklight.solr_config["url"] : Blacklight.solr_config[:fulltext] ? Blacklight.solr_config[:fulltext]["url"] : Blacklight.solr_config[:default]["url"]
19
- uri = URI("#{url}/update/extract?extractOnly=true&wt=json&extractFormat=text")
20
- req = Net::HTTP.new(uri.host, uri.port)
21
- resp = req.post(uri.to_s, self.content.content, {
22
- 'Content-type' => "#{self.mime_type};charset=utf-8",
23
- 'Content-Length' => self.content.content.size.to_s
24
- })
25
- raise "URL '#{uri}' returned code #{resp.code}" unless resp.code == "200"
26
- self.content.content.rewind if self.content.content.respond_to?(:rewind)
27
- extracted_text = JSON.parse(resp.body)[''].rstrip
28
- full_text.content = extracted_text if extracted_text.present?
29
- rescue => e
30
- logger.error("Error extracting content from #{self.id}: #{e.inspect}")
17
+ def extract_content
18
+ uri = URI("#{connection_url}/update/extract?extractOnly=true&wt=json&extractFormat=text")
19
+ req = Net::HTTP.new(uri.host, uri.port)
20
+ resp = req.post(uri.to_s, self.content.content, {
21
+ 'Content-type' => "#{self.mime_type};charset=utf-8",
22
+ 'Content-Length' => self.content.content.size.to_s
23
+ })
24
+ raise "URL '#{uri}' returned code #{resp.code}" unless resp.code == "200"
25
+ self.content.content.rewind if self.content.content.respond_to?(:rewind)
26
+ extracted_text = JSON.parse(resp.body)[''].rstrip
27
+ full_text.content = extracted_text if extracted_text.present?
28
+ rescue => e
29
+ logger.error("Error extracting content from #{self.id}: #{e.inspect}")
30
+ end
31
+
32
+ def connection_url
33
+ case
34
+ when Blacklight.connection_config[:url] then Blacklight.connection_config[:url]
35
+ when Blacklight.connection_config["url"] then Blacklight.connection_config["url"]
36
+ when Blacklight.connection_config[:fulltext] then Blacklight.connection_config[:fulltext]["url"]
37
+ else Blacklight.connection_config[:default]["url"]
31
38
  end
39
+ end
40
+
32
41
  end
33
42
  end
34
43
  end
@@ -24,7 +24,7 @@ module Sufia
24
24
  def request_transfer_to(target)
25
25
  raise ArgumentError, "Must provide a target" unless target
26
26
  deposit_user = ::User.find_by_user_key(depositor)
27
- ProxyDepositRequest.create!(pid: id, receiving_user: target, sending_user: deposit_user)
27
+ ProxyDepositRequest.create!(generic_file_id: id, receiving_user: target, sending_user: deposit_user)
28
28
  end
29
29
  end
30
30
  end
@@ -144,42 +144,7 @@ class FitsDatastream < ActiveFedora::OmDatastream
144
144
  http://hul.harvard.edu/ois/xml/xsd/fits/fits_output.xsd",
145
145
  version: "0.6.0",
146
146
  timestamp: "1/25/12 11:04 AM") {
147
- xml.identification {
148
- xml.identity(format: '', mimetype: '',
149
- toolname: 'FITS', toolversion: '') {
150
- xml.tool(toolname: '', toolversion: '')
151
- xml.version(toolname: '', toolversion: '')
152
- xml.externalIdentifier(toolname: '', toolversion: '')
153
- }
154
- }
155
- xml.fileinfo {
156
- xml.size(toolname: '', toolversion: '')
157
- xml.creatingApplicatioName(toolname: '', toolversion: '',
158
- status: '')
159
- xml.lastmodified(toolname: '', toolversion: '', status: '')
160
- xml.filepath(toolname: '', toolversion: '', status: '')
161
- xml.filename(toolname: '', toolversion: '', status: '')
162
- xml.md5checksum(toolname: '', toolversion: '', status: '')
163
- xml.fslastmodified(toolname: '', toolversion: '', status: '')
164
- }
165
- xml.filestatus {
166
- xml.tag! "well-formed", toolname: '', toolversion: '', status: ''
167
- xml.valid(toolname: '', toolversion: '', status: '')
168
- }
169
- xml.metadata {
170
- xml.document {
171
- xml.title(toolname: '', toolversion: '', status: '')
172
- xml.author(toolname: '', toolversion: '', status: '')
173
- xml.pageCount(toolname: '', toolversion: '')
174
- xml.isTagged(toolname: '', toolversion: '')
175
- xml.hasOutline(toolname: '', toolversion: '')
176
- xml.hasAnnotations(toolname: '', toolversion: '')
177
- xml.isRightsManaged(toolname: '', toolversion: '',
178
- status: '')
179
- xml.isProtected(toolname: '', toolversion: '')
180
- xml.hasForms(toolname: '', toolversion: '', status: '')
181
- }
182
- }
147
+ xml.identification { xml.identity(toolname: 'FITS') }
183
148
  }
184
149
  end
185
150
  builder.doc
@@ -1,11 +1,11 @@
1
1
  class ProxyDepositRequest < ActiveRecord::Base
2
- include Blacklight::SolrHelper
2
+ include Blacklight::SearchHelper
3
3
  include ActionView::Helpers::UrlHelper
4
4
 
5
5
  belongs_to :receiving_user, class_name: 'User'
6
6
  belongs_to :sending_user, class_name: 'User'
7
7
 
8
- validates :sending_user, :pid, presence: true
8
+ validates :sending_user, :generic_file_id, presence: true
9
9
  validate :transfer_to_should_be_a_valid_username
10
10
  validate :sending_user_should_not_be_receiving_user
11
11
  validate :should_not_be_already_part_of_a_transfer
@@ -28,7 +28,7 @@ class ProxyDepositRequest < ActiveRecord::Base
28
28
  end
29
29
 
30
30
  def should_not_be_already_part_of_a_transfer
31
- transfers = ProxyDepositRequest.where(pid: pid)
31
+ transfers = ProxyDepositRequest.where(generic_file_id: generic_file_id, status: 'pending')
32
32
  errors.add(:open_transfer, 'must close open transfer on the file before creating a new one') unless transfers.blank? || ( transfers.count == 1 && transfers[0].id == self.id)
33
33
  end
34
34
 
@@ -53,7 +53,7 @@ class ProxyDepositRequest < ActiveRecord::Base
53
53
 
54
54
  # @param [Boolean] reset (false) should the access controls be reset. This means revoking edit access from the depositor
55
55
  def transfer!(reset = false)
56
- Sufia.queue.push(ContentDepositorChangeEventJob.new(pid, receiving_user.user_key, reset))
56
+ Sufia.queue.push(ContentDepositorChangeEventJob.new(generic_file_id, receiving_user.user_key, reset))
57
57
  self.status = 'accepted'
58
58
  self.fulfillment_date = Time.now
59
59
  save!
@@ -73,12 +73,12 @@ class ProxyDepositRequest < ActiveRecord::Base
73
73
  end
74
74
 
75
75
  def deleted_file?
76
- !GenericFile.exists?(pid)
76
+ !GenericFile.exists?(generic_file_id)
77
77
  end
78
78
 
79
79
  def title
80
80
  return 'file not found' if deleted_file?
81
- query = ActiveFedora::SolrQueryBuilder.construct_query_for_ids([pid])
81
+ query = ActiveFedora::SolrQueryBuilder.construct_query_for_ids([generic_file_id])
82
82
  solr_response = ActiveFedora::SolrService.query(query, raw: true)
83
83
  SolrDocument.new(solr_response['response']['docs'].first, solr_response).title
84
84
  end
@@ -63,7 +63,7 @@ module Sufia
63
63
  latest_audit = ChecksumAuditLog.logs_for(generic_file.id, file).first
64
64
  return latest_audit unless needs_audit?(latest_audit)
65
65
  Sufia.queue.push(AuditJob.new(generic_file.id, file, uri))
66
- latest_audit || ChecksumAuditLog.new(pass: NO_RUNS, pid: generic_file.id, dsid: file, version: label)
66
+ latest_audit || ChecksumAuditLog.new(pass: NO_RUNS, generic_file_id: generic_file.id, dsid: file, version: label)
67
67
  end
68
68
 
69
69
  def needs_audit?(latest_audit)
@@ -6,7 +6,6 @@ module Sufia
6
6
  solr_doc[Solrizer.solr_name('file_format')] = object.file_format
7
7
  solr_doc[Solrizer.solr_name('file_format', :facetable)] = object.file_format
8
8
  solr_doc['all_text_timv'] = object.full_text.content
9
- solr_doc = object.index_collection_ids(solr_doc)
10
9
  end
11
10
  end
12
11
  end
@@ -8,7 +8,6 @@ module Sufia
8
8
  end
9
9
 
10
10
  @minter = ::Noid::Minter.new(template: noid_template)
11
- @pid = $$
12
11
  @semaphore = Mutex.new
13
12
  def self.valid?(identifier)
14
13
  # remove the fedora namespace since it's not part of the noid
@@ -18,8 +17,8 @@ module Sufia
18
17
  def self.mint
19
18
  @semaphore.synchronize do
20
19
  while true
21
- pid = self.next_id
22
- return pid unless ActiveFedora::Base.exists?(pid)
20
+ id = self.next_id
21
+ return id unless ActiveFedora::Base.exists?(id)
23
22
  end
24
23
  end
25
24
  end
@@ -2,7 +2,7 @@ module Sufia
2
2
  module Noid
3
3
  extend ActiveSupport::Concern
4
4
 
5
- ## This overrides the default behavior, which is to ask Fedora for a pid
5
+ ## This overrides the default behavior, which is to ask Fedora for an id
6
6
  # @see ActiveFedora::Persistence.assign_id
7
7
  def assign_id
8
8
  Sufia::IdService.mint if Sufia.config.enable_noids
@@ -123,7 +123,7 @@ Sufia.config do |config|
123
123
  # NOTE: if you have always sent analytics to GA for downloads and page views leave this commented out
124
124
  # config.analytic_start_date = DateTime.new(2014,9,10)
125
125
  #
126
- # Method of converting pids into URIs for storage in Fedora
126
+ # Method of converting ids into URIs for storage in Fedora
127
127
  # config.translate_uri_to_id = lambda { |uri| uri.to_s.split('/')[-1] }
128
128
  # config.translate_id_to_uri = lambda { |id|
129
129
  # "#{ActiveFedora.fedora.host}#{ActiveFedora.fedora.base_path}/#{Sufia::Noid.treeify(id)}" }
@@ -0,0 +1,5 @@
1
+ class ChangeAuditLogPidToGenericFileId < ActiveRecord::Migration
2
+ def change
3
+ rename_column :checksum_audit_logs, :pid, :generic_file_id
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ class ChangeProxyDepositRequestPidToGenericFileId < ActiveRecord::Migration
2
+ def change
3
+ rename_column :proxy_deposit_requests, :pid, :generic_file_id
4
+ end
5
+ end
@@ -0,0 +1,21 @@
1
+ require_relative 'abstract_migration_generator'
2
+
3
+ class Sufia::Models::Upgrade600Generator < Sufia::Models::AbstractMigrationGenerator
4
+ source_root File.expand_path('../templates', __FILE__)
5
+
6
+ desc """
7
+ This generator for upgrading sufia-models to 6.0 makes the following changes to your application:
8
+ 1. Creates several database migrations if they do not exist in /db/migrate
9
+ """
10
+
11
+ # Setup the database migrations
12
+ def copy_migrations
13
+ [
14
+ 'change_audit_log_pid_to_generic_file_id.rb',
15
+ 'change_proxy_deposit_request_pid_to_generic_file_id.rb'
16
+ ].each do |file|
17
+ better_migration_template file
18
+ end
19
+ end
20
+ end
21
+
@@ -1,23 +1,28 @@
1
1
  module Sufia
2
2
  class UserStatImporter
3
3
 
4
+ UserRecord = Struct.new("UserRecord", :id, :user_key, :last_stats_update)
5
+
4
6
  def initialize(options={})
5
7
  @verbose = options[:verbose]
6
8
  @logging = options[:logging]
9
+ @delay_secs = options[:delay_secs].to_f
7
10
  end
8
11
 
9
12
  def import
10
13
  log_message('Begin import of User stats.')
11
- ::User.find_each do |user|
14
+ sorted_users.each do |user|
12
15
  start_date = date_since_last_cache(user)
13
16
 
14
17
  stats = {}
15
18
  file_ids_for_user(user).each do |file_id|
16
19
  view_stats = FileViewStat.statistics(file_id, start_date, user.id)
17
20
  stats = tally_results(view_stats, :views, stats)
21
+ delay
18
22
 
19
23
  dl_stats = FileDownloadStat.statistics(file_id, start_date, user.id)
20
24
  stats = tally_results(dl_stats, :downloads, stats)
25
+ delay
21
26
  end
22
27
 
23
28
  create_or_update_user_stats(stats, user)
@@ -25,9 +30,23 @@ module Sufia
25
30
  log_message('User stats import complete.')
26
31
  end
27
32
 
33
+ # Returns an array of users sorted by the date of their last
34
+ # stats update. Users that have not been recently updated
35
+ # will be at the top of the array.
36
+ def sorted_users
37
+ users = []
38
+ ::User.find_each do |user|
39
+ users.push(UserRecord.new(user.id, user.user_key, date_since_last_cache(user)))
40
+ end
41
+ users.sort! {|a, b| a.last_stats_update <=> b.last_stats_update}
42
+ end
28
43
 
29
44
  private
30
45
 
46
+ def delay
47
+ sleep @delay_secs
48
+ end
49
+
31
50
  def date_since_last_cache(user)
32
51
  last_cached_stat = UserStat.where(user_id: user.id).order(date: :asc).last
33
52
 
@@ -1,5 +1,5 @@
1
1
  module Sufia
2
2
  module Models
3
- VERSION = "6.0.0.rc4"
3
+ VERSION = "6.0.0"
4
4
  end
5
5
  end
@@ -0,0 +1,19 @@
1
+ namespace :sufia do
2
+
3
+ desc "Reports on and optionally removes empty batches that contain no associated files"
4
+ task :empty_batches, [:remove] => :environment do |t, args|
5
+ option = args.to_hash.fetch(:remove, "keep")
6
+ Batch.all.each do |batch|
7
+ if batch.generic_files.empty?
8
+ print "#{batch.id} contains no files - "
9
+ if option == "remove"
10
+ batch.destroy
11
+ puts "deleted"
12
+ else
13
+ puts "to delete, rerun with the remove option: rake sufia:empty_batches[remove]"
14
+ end
15
+ end
16
+ end
17
+ end
18
+
19
+ end
@@ -0,0 +1,21 @@
1
+ namespace :sufia do
2
+ namespace :migrate do
3
+
4
+ desc "Migrate proxy deposits"
5
+ task proxy_deposits: :environment do
6
+ ProxyDepositRequest.all.each do |pd|
7
+ pd.generic_file_id = pd.generic_file_id.delete "#{Sufia.config.redis_namespace}:"
8
+ pd.save
9
+ end
10
+ end
11
+
12
+ desc "Migrate audit logs"
13
+ task audit_logs: :environment do
14
+ ChecksumAuditLog.all.each do |cs|
15
+ cs.generic_file_id = cs.generic_file_id.delete "#{Sufia.config.redis_namespace}:"
16
+ cs.save
17
+ end
18
+ end
19
+
20
+ end
21
+ end
@@ -1,3 +1,5 @@
1
+ require 'net/http'
2
+
1
3
  namespace :solr do
2
4
  desc "Enqueue a job to resolrize the repository objects"
3
5
  task reindex: :environment do
@@ -7,6 +9,41 @@ end
7
9
 
8
10
  namespace :sufia do
9
11
  namespace :jetty do
12
+
13
+ FULLTEXT_JARS = %w(
14
+ org/apache/james/apache-mime4j-core/0.7.2/apache-mime4j-core-0.7.2.jar
15
+ org/apache/james/apache-mime4j-dom/0.7.2/apache-mime4j-dom-0.7.2.jar
16
+ org/apache/solr/solr-cell/4.0.0/solr-cell-4.0.0.jar
17
+ org/bouncycastle/bcmail-jdk15/1.45/bcmail-jdk15-1.45.jar
18
+ org/bouncycastle/bcprov-jdk15/1.45/bcprov-jdk15-1.45.jar
19
+ de/l3s/boilerpipe/boilerpipe/1.1.0/boilerpipe-1.1.0.jar
20
+ org/apache/commons/commons-compress/1.4.1/commons-compress-1.4.1.jar
21
+ dom4j/dom4j/1.6.1/dom4j-1.6.1.jar
22
+ org/apache/pdfbox/fontbox/1.7.0/fontbox-1.7.0.jar
23
+ com/ibm/icu/icu4j/49.1/icu4j-49.1.jar
24
+ com/googlecode/mp4parser/isoparser/1.0-RC-1/isoparser-1.0-RC-1.jar
25
+ jdom/jdom/1.0/jdom-1.0.jar
26
+ org/apache/pdfbox/jempbox/1.7.0/jempbox-1.7.0.jar
27
+ com/googlecode/juniversalchardet/juniversalchardet/1.0.3/juniversalchardet-1.0.3.jar
28
+ com/drewnoakes/metadata-extractor/2.4.0-beta-1/metadata-extractor-2.4.0-beta-1.jar
29
+ edu/ucar/netcdf/4.2-min/netcdf-4.2-min.jar
30
+ org/apache/pdfbox/pdfbox/1.7.0/pdfbox-1.7.0.jar
31
+ org/apache/poi/poi/3.8/poi-3.8.jar
32
+ org/apache/poi/poi-ooxml/3.8/poi-ooxml-3.8.jar
33
+ org/apache/poi/poi-ooxml-schemas/3.8/poi-ooxml-schemas-3.8.jar
34
+ org/apache/poi/poi-scratchpad/3.8/poi-scratchpad-3.8.jar
35
+ rome/rome/0.9/rome-0.9.jar
36
+ org/ccil/cowan/tagsoup/tagsoup/1.2.1/tagsoup-1.2.1.jar
37
+ org/apache/tika/tika-core/1.2/tika-core-1.2.jar
38
+ org/apache/tika/tika-parsers/1.2/tika-parsers-1.2.jar
39
+ org/gagravarr/vorbis-java-core/0.1/vorbis-java-core-0.1.jar
40
+ org/gagravarr/vorbis-java-tika/0.1/vorbis-java-tika-0.1.jar
41
+ xerces/xercesImpl/2.9.1/xercesImpl-2.9.1.jar
42
+ org/apache/xmlbeans/xmlbeans/2.3.0/xmlbeans-2.3.0.jar
43
+ org/tukaani/xz/1.0/xz-1.0.jar
44
+ org/aspectj/aspectjrt/1.8.5/aspectjrt-1.8.5.jar
45
+ )
46
+
10
47
  desc 'Configure jetty with full-text indexing'
11
48
  task config: :download_jars do
12
49
  Rake::Task['jetty:config'].invoke
@@ -15,49 +52,29 @@ namespace :sufia do
15
52
  desc 'Download Solr full-text extraction jars'
16
53
  task :download_jars do
17
54
  puts "Downloading full-text jars from maven.org ..."
18
- url_prefix = 'http://search.maven.org/remotecontent?filepath='
19
55
  fulltext_dir = 'jetty/solr/lib/contrib/extraction/lib'
20
- jars = %w(
21
- org/apache/james/apache-mime4j-core/0.7.2/apache-mime4j-core-0.7.2.jar
22
- org/apache/james/apache-mime4j-dom/0.7.2/apache-mime4j-dom-0.7.2.jar
23
- org/apache/solr/solr-cell/4.0.0/solr-cell-4.0.0.jar
24
- org/bouncycastle/bcmail-jdk15/1.45/bcmail-jdk15-1.45.jar
25
- org/bouncycastle/bcprov-jdk15/1.45/bcprov-jdk15-1.45.jar
26
- de/l3s/boilerpipe/boilerpipe/1.1.0/boilerpipe-1.1.0.jar
27
- org/apache/commons/commons-compress/1.4.1/commons-compress-1.4.1.jar
28
- dom4j/dom4j/1.6.1/dom4j-1.6.1.jar
29
- org/apache/pdfbox/fontbox/1.7.0/fontbox-1.7.0.jar
30
- com/ibm/icu/icu4j/49.1/icu4j-49.1.jar
31
- com/googlecode/mp4parser/isoparser/1.0-RC-1/isoparser-1.0-RC-1.jar
32
- jdom/jdom/1.0/jdom-1.0.jar
33
- org/apache/pdfbox/jempbox/1.7.0/jempbox-1.7.0.jar
34
- com/googlecode/juniversalchardet/juniversalchardet/1.0.3/juniversalchardet-1.0.3.jar
35
- com/drewnoakes/metadata-extractor/2.4.0-beta-1/metadata-extractor-2.4.0-beta-1.jar
36
- edu/ucar/netcdf/4.2-min/netcdf-4.2-min.jar
37
- org/apache/pdfbox/pdfbox/1.7.0/pdfbox-1.7.0.jar
38
- org/apache/poi/poi/3.8/poi-3.8.jar
39
- org/apache/poi/poi-ooxml/3.8/poi-ooxml-3.8.jar
40
- org/apache/poi/poi-ooxml-schemas/3.8/poi-ooxml-schemas-3.8.jar
41
- org/apache/poi/poi-scratchpad/3.8/poi-scratchpad-3.8.jar
42
- rome/rome/0.9/rome-0.9.jar
43
- org/ccil/cowan/tagsoup/tagsoup/1.2.1/tagsoup-1.2.1.jar
44
- org/apache/tika/tika-core/1.2/tika-core-1.2.jar
45
- org/apache/tika/tika-parsers/1.2/tika-parsers-1.2.jar
46
- org/gagravarr/vorbis-java-core/0.1/vorbis-java-core-0.1.jar
47
- org/gagravarr/vorbis-java-tika/0.1/vorbis-java-tika-0.1.jar
48
- xerces/xercesImpl/2.9.1/xercesImpl-2.9.1.jar
49
- org/apache/xmlbeans/xmlbeans/2.3.0/xmlbeans-2.3.0.jar
50
- org/tukaani/xz/1.0/xz-1.0.jar
51
- )
52
56
  FileUtils.mkdir_p(fulltext_dir) unless File.directory?(fulltext_dir)
53
57
  Dir.chdir(fulltext_dir) do
54
- jars.each do |jar|
55
- url = url_prefix + jar
56
- jarfile = jar.split('/').last
57
- puts "Fetching #{url}" unless File.exists?(jarfile)
58
- system "wget --quiet --no-clobber #{url} -O #{jarfile}"
58
+ FULLTEXT_JARS.each do |jar|
59
+ destination = jar.split('/').last
60
+ download_from_maven(jar, destination) unless File.exists?(destination)
59
61
  end
60
62
  end
61
63
  end
62
64
  end
63
65
  end
66
+
67
+ def download_from_maven url, dst
68
+ full_url = '/remotecontent?filepath=' + url
69
+ file = File.open(dst, "w")
70
+ Net::HTTP.start("search.maven.org") do |http|
71
+ puts "Fetching #{full_url}"
72
+ begin
73
+ http.request_get(full_url) do |resp|
74
+ resp.read_body { |segment| file.write(segment) }
75
+ end
76
+ ensure
77
+ file.close
78
+ end
79
+ end
80
+ end
data/sufia-models.gemspec CHANGED
@@ -31,7 +31,7 @@ Gem::Specification.new do |spec|
31
31
 
32
32
  spec.add_dependency "hydra-head", "~> 9.0"
33
33
  spec.add_dependency "active-fedora", "~> 9.0"
34
- spec.add_dependency "hydra-collections", "~> 4.0"
34
+ spec.add_dependency "hydra-collections", [">= 5.0.2", "< 6.0"]
35
35
  spec.add_dependency 'hydra-derivatives', '~> 1.0'
36
36
  spec.add_dependency 'nest', '~> 1.1'
37
37
  spec.add_dependency 'resque', '~> 1.23'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sufia-models
3
3
  version: !ruby/object:Gem::Version
4
- version: 6.0.0.rc4
4
+ version: 6.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jeremy Friesen
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-02-18 00:00:00.000000000 Z
11
+ date: 2015-03-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -98,16 +98,22 @@ dependencies:
98
98
  name: hydra-collections
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
- - - "~>"
101
+ - - ">="
102
102
  - !ruby/object:Gem::Version
103
- version: '4.0'
103
+ version: 5.0.2
104
+ - - "<"
105
+ - !ruby/object:Gem::Version
106
+ version: '6.0'
104
107
  type: :runtime
105
108
  prerelease: false
106
109
  version_requirements: !ruby/object:Gem::Requirement
107
110
  requirements:
108
- - - "~>"
111
+ - - ">="
109
112
  - !ruby/object:Gem::Version
110
- version: '4.0'
113
+ version: 5.0.2
114
+ - - "<"
115
+ - !ruby/object:Gem::Version
116
+ version: '6.0'
111
117
  - !ruby/object:Gem::Dependency
112
118
  name: hydra-derivatives
113
119
  requirement: !ruby/object:Gem::Requirement
@@ -309,6 +315,7 @@ files:
309
315
  - README.md
310
316
  - Rakefile
311
317
  - app/actors/sufia/generic_file/actor.rb
318
+ - app/jobs/active_fedora_id_based_job.rb
312
319
  - app/jobs/active_fedora_pid_based_job.rb
313
320
  - app/jobs/audit_job.rb
314
321
  - app/jobs/batch_update_job.rb
@@ -401,6 +408,8 @@ files:
401
408
  - lib/generators/sufia/models/templates/migrations/add_linkedin_to_users.rb
402
409
  - lib/generators/sufia/models/templates/migrations/add_orcid_to_users.rb
403
410
  - lib/generators/sufia/models/templates/migrations/add_social_to_users.rb
411
+ - lib/generators/sufia/models/templates/migrations/change_audit_log_pid_to_generic_file_id.rb
412
+ - lib/generators/sufia/models/templates/migrations/change_proxy_deposit_request_pid_to_generic_file_id.rb
404
413
  - lib/generators/sufia/models/templates/migrations/create_checksum_audit_logs.rb
405
414
  - lib/generators/sufia/models/templates/migrations/create_content_blocks.rb
406
415
  - lib/generators/sufia/models/templates/migrations/create_featured_works.rb
@@ -416,6 +425,7 @@ files:
416
425
  - lib/generators/sufia/models/templates/migrations/create_version_committers.rb
417
426
  - lib/generators/sufia/models/update_content_blocks_generator.rb
418
427
  - lib/generators/sufia/models/upgrade400_generator.rb
428
+ - lib/generators/sufia/models/upgrade600_generator.rb
419
429
  - lib/generators/sufia/models/usagestats_generator.rb
420
430
  - lib/generators/sufia/models/user_stats_generator.rb
421
431
  - lib/sufia/messages.rb
@@ -434,6 +444,8 @@ files:
434
444
  - lib/sufia/permissions.rb
435
445
  - lib/sufia/permissions/readable.rb
436
446
  - lib/sufia/permissions/writable.rb
447
+ - lib/tasks/batch_cleanup.rake
448
+ - lib/tasks/migrate.rake
437
449
  - lib/tasks/resque.rake
438
450
  - lib/tasks/stats_tasks.rake
439
451
  - lib/tasks/sufia-models_tasks.rake
@@ -453,12 +465,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
453
465
  version: '0'
454
466
  required_rubygems_version: !ruby/object:Gem::Requirement
455
467
  requirements:
456
- - - ">"
468
+ - - ">="
457
469
  - !ruby/object:Gem::Version
458
- version: 1.3.1
470
+ version: '0'
459
471
  requirements: []
460
472
  rubyforge_project:
461
- rubygems_version: 2.4.5
473
+ rubygems_version: 2.4.6
462
474
  signing_key:
463
475
  specification_version: 4
464
476
  summary: Models and services for sufia