-
Notifications
You must be signed in to change notification settings - Fork 13
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #39 from CDL-Dryad/download-limits
Limit simultaneous downloads by ip address
- Loading branch information
Showing
16 changed files
with
239 additions
and
20 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
# Trying to add new models to this area instead of inside 'stash' subdirectories since it's much easier to maintain tests | ||
# inside of here than in the engines. Also the loading of tests isn't hacked together in some unmaintainable and non-standard | ||
# way like they are inside the engine tests. | ||
|
||
require 'rails_helper' | ||
|
||
module StashEngine | ||
RSpec.describe DownloadHistory, type: :model do | ||
|
||
describe :mark_event do | ||
before(:each) do | ||
DownloadHistory.mark_start(ip: '168.10.0.1', user_agent: 'HorseStomping Browser', resource_id: 37, file_id: 88) | ||
end | ||
|
||
it 'adds started downloads to the database' do | ||
expect(DownloadHistory.all.count).to eq(1) | ||
dlh = DownloadHistory.all.first | ||
expect(dlh.ip_address).to eq('168.10.0.1') | ||
expect(dlh.user_agent).to eq('HorseStomping Browser') | ||
expect(dlh.state).to eq('downloading') | ||
end | ||
|
||
it 'modifies finished download to change state and updated_at timestamp' do | ||
expect(DownloadHistory.all.count).to eq(1) | ||
dlh = DownloadHistory.all.first | ||
updated_at_before = dlh.updated_at | ||
sleep 1 # just to be sure timestamps are different seconds | ||
DownloadHistory.mark_end(download_history: dlh) | ||
dlh.reload | ||
expect(dlh.updated_at).not_to eq(updated_at_before) | ||
expect(dlh.state).to eq('finished') | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
# see https://raw.githubusercontent.com/eliotsykes/rails-testing-toolbox/master/tasks.rb | ||
# and https://www.eliotsykes.com/test-rails-rake-tasks-with-rspec | ||
# For testing rake tasks | ||
require 'rake' | ||
|
||
# Task names should be used in the top-level describe, with an optional | ||
# "rake "-prefix for better documentation. Both of these will work: | ||
# | ||
# 1) describe 'foo:bar' do ... end | ||
# | ||
# 2) describe 'rake foo:bar' do ... end | ||
# | ||
# Favor including 'rake '-prefix as in the 2nd example above as it produces | ||
# doc output that makes it clear a rake task is under test and how it is | ||
# invoked. | ||
module TaskExampleGroup | ||
extend ActiveSupport::Concern | ||
|
||
included do | ||
let(:task_name) { self.class.top_level_description.sub(/\Arake /, '') } | ||
let(:tasks) { Rake::Task } | ||
subject(:task) { tasks[task_name] } | ||
|
||
after(:each) do | ||
task.all_prerequisite_tasks.each { |prerequisite| tasks[prerequisite].reenable } | ||
task.reenable | ||
end | ||
end | ||
end | ||
|
||
RSpec.configure do |config| | ||
config.define_derived_metadata(file_path: %r{/spec/tasks/}) do |metadata| | ||
metadata[:type] = :task | ||
end | ||
|
||
config.include TaskExampleGroup, type: :task | ||
|
||
config.before(:suite) do | ||
Rails.application.load_tasks | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
require 'rails_helper' | ||
require 'byebug' | ||
|
||
describe 'download_tracking:cleanup', type: :task do | ||
|
||
it 'preloads the Rails environment' do | ||
expect(task.prerequisites).to include 'environment' | ||
end | ||
|
||
it 'logs to stdout' do | ||
expect { task.execute }.to output(/Finished DownloadHistory cleanup/).to_stdout | ||
end | ||
|
||
it 'cleans up old entries more than 60 days old' do | ||
StashEngine::DownloadHistory.create(ip_address: '127.0.0.1', created_at: 65.days.ago) | ||
StashEngine::DownloadHistory.create(ip_address: '127.0.0.1') | ||
expect(StashEngine::DownloadHistory.all.count).to eq(2) | ||
expect { task.execute }.to output(/Finished DownloadHistory cleanup/).to_stdout | ||
# it removed the old one | ||
expect(StashEngine::DownloadHistory.all.count).to eq(1) | ||
end | ||
|
||
it 'fixes download status for non-updated items more than one day old' do | ||
StashEngine::DownloadHistory.create(ip_address: '127.0.0.1', created_at: 3.days.ago, state: 'downloading') | ||
dlh = StashEngine::DownloadHistory.all | ||
expect(dlh.count).to eq(1) | ||
item = dlh.first | ||
expect(item.state).to eq('downloading') | ||
expect { task.execute }.to output(/Finished DownloadHistory cleanup/).to_stdout | ||
item.reload | ||
expect(item.state).to eq('finished') | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
21 changes: 21 additions & 0 deletions
21
stash/stash_engine/app/models/stash_engine/download_history.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
module StashEngine | ||
class DownloadHistory < ActiveRecord::Base | ||
belongs_to :resource, class_name: 'StashEngine::Resource' | ||
belongs_to :file_upload, class_name: 'StashEngine::FileUpload' | ||
enum state: %w[downloading finished].map { |i| [i.to_sym, i] }.to_h | ||
|
||
scope :downloading, -> { where(state: 'downloading') } | ||
|
||
def self.mark_start(ip:, user_agent:, resource_id:, file_id: nil) | ||
create(ip_address: ip, user_agent: user_agent, resource_id: resource_id, file_upload_id: file_id, state: 'downloading') | ||
end | ||
|
||
# this just changes the status so it is marked as finished | ||
def self.mark_end(download_history: nil) | ||
return if download_history.nil? | ||
|
||
download_history.update(state: 'finished') | ||
end | ||
|
||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
20 changes: 20 additions & 0 deletions
20
stash/stash_engine/app/views/stash_engine/downloads/download_limit.html.erb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
<% @page_title = "Concurrent Download Limits" %> | ||
<h1 class="o-heading__level1">Concurrent download limits</h1> | ||
|
||
<p> | ||
In order to maintain a responsive service for all users, we limit concurrent downloads to | ||
<%= StashEngine::DownloadsController::CONCURRENT_DOWNLOAD_LIMIT %> at a time. When an in-progress download | ||
completes, you may start another. | ||
</p> | ||
|
||
<p> | ||
If you need to download all or most files in a dataset, please use the <em>Download dataset</em> button since it will give you | ||
all the files in a single zip package and will usually also reduce your download time and size. | ||
</p> | ||
|
||
<p> | ||
If you are getting this message and you're using an automated robot or crawler, please reduce your usage to fewer | ||
concurrent downloads at the same time. You should also be aware of the | ||
<a href="https://en.wikipedia.org/wiki/Robots_exclusion_standard">robots.txt</a> standard which is a voluntary | ||
standard honored by most well-behaved crawlers. | ||
</p> |
15 changes: 15 additions & 0 deletions
15
stash/stash_engine/db/migrate/20200102182121_create_stash_engine_download_histories.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
class CreateStashEngineDownloadHistories < ActiveRecord::Migration | ||
def change | ||
create_table :stash_engine_download_histories do |t| | ||
t.string :ip_address, index: true | ||
t.text :user_agent | ||
t.references :resource, index: true | ||
t.references :file_upload, index: true | ||
t.column :state, "ENUM('downloading', 'finished') DEFAULT 'downloading'" | ||
t.timestamps null: false | ||
|
||
t.index :user_agent, length: { user_agent: 100 } | ||
t.index :state | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
namespace :download_tracking do | ||
|
||
# because of our privacy policy we don't keep most logs or log-like info for more than 60 days as I understand it | ||
desc 'cleanup download history' | ||
task cleanup: :environment do | ||
# Reset downloads from table that show longer than 24 hours in progress, since most likely the status is wrong. | ||
# If the server is shut down in a disorderly way, the 'ensure' clause may not run to close out download info. | ||
# It seems to happen quite rarely (also leaves stray download files in our EFS mount in the rare cases). | ||
StashEngine::DownloadHistory.downloading.where('created_at < ?', 1.day.ago).update_all(state: 'finished') | ||
|
||
# clean up information older than 60 days to comply with privacy and no callbacks | ||
StashEngine::DownloadHistory.where('created_at < ?', 60.days.ago).delete_all | ||
puts "#{Time.new.iso8601} Finished DownloadHistory cleanup" | ||
end | ||
|
||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.