sufia-models 6.0.0.rc4 → 6.0.0

Sign up to get free protection for your applications and to get access to all the features.
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