Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a service object, which uploads all files of a problem in minio #153

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion app/models/contest.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class Contest < ActiveRecord::Base
scope :practicable, -> { where(:practicable => true) }
scope :visible, -> { where(:visible => true) }

validates_presence_of :name, :duration, :start_time
validates_presence_of :name, :duration, :start_time, :end_time
validates_numericality_of :duration

validates_inclusion_of :runner_type, :in => RUNNER_TYPES
Expand Down
2 changes: 2 additions & 0 deletions app/models/problem.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ class Problem < ActiveRecord::Base
has_and_belongs_to_many :categories
has_one :problem_stats, dependent: :destroy

has_many_attached :assets

validates_presence_of :name, :time_limit
validates_numericality_of :time_limit, :memory_limit, :greater_than => 0

Expand Down
13 changes: 13 additions & 0 deletions app/services/upload_problem_assets.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
class UploadProblemAssets
def initialize(problem)
@problem = problem
end

def call
@problem.all_files.each do |file|
next if @problem.assets_blobs.any? { |blob| blob.filename == File.basename(file) }

@problem.assets.attach(io: File.open(file), filename: File.basename(file))
end
end
end
2 changes: 1 addition & 1 deletion config/environments/development.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,5 +38,5 @@
config.active_job.queue_adapter = :sidekiq

# Active Storage config
config.active_storage.service = :local
config.active_storage.service = :minio
end
13 changes: 13 additions & 0 deletions config/storage.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
local:
service: Disk
root: <%= Rails.root.join("storage") %>

test:
service: Disk
root: <%= Rails.root.join("tmp/storage") %>

minio:
service: S3
bucket: "maycamp-files"
endpoint: http://minio:9000
force_path_style: true
42 changes: 33 additions & 9 deletions db/seeds.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,36 @@
#
# cities = City.create([{ :name => 'Chicago' }, { :name => 'Copenhagen' }])
# Mayor.create(:name => 'Daley', :city => cities.first)
u = User.create(
:login => 'root',
:name => "The admin",
:email => "valentin.mihov@gmail.com",
:unencrypted_password => "123123",
:unencrypted_password_confirmation => "123123",
:role => User::ADMIN,
:city => "Sofia"
)
User
.create_with(
name: "The admin",
email: "valentin.mihov@gmail.com",
unencrypted_password: "123123",
unencrypted_password_confirmation: "123123",
role: User::ADMIN,
city: "Sofia")
.find_or_create_by!(
login: 'root'
)

group = Group.find_or_create_by!(name: "Група Е")

contest = Contest.create_with(
duration: 300,
group: group,
start_time: 1.year.ago,
end_time: 1.year.ago,
runner_type: "fork"
).find_or_create_by!(name: "Пролетен турнир 2020")

problem1 = Problem.create_with(
contest: contest,
time_limit: 1,
memory_limit: 128.megabytes
).find_or_create_by!(name: "Задача 1")

problem2 = Problem.create_with(
contest: contest,
time_limit: 1,
memory_limit: 128.megabytes
).find_or_create_by!(name: "Задача 2")
19 changes: 19 additions & 0 deletions docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ services:
- DATABASE_URL=mysql2://arena:arena@mysql:3306/arena?encoding=utf8&collation=utf8_general_ci
- REDIS_PROVIDER=redis://redis:6379
- MEMCACHE_URL=memcached:11211
- AWS_ACCESS_KEY=AKIAIOSFODNN7EXAMPLE
- AWS_SECRET_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
- AWS_REGION=us-east-1
- SECRET_KEY_BASE=123
- SECRET_TOKEN=123
- SIDEKIQ_USERNAME=arena
Expand Down Expand Up @@ -44,6 +47,9 @@ services:
- RAILS_ENV=development
- DATABASE_URL=mysql2://arena:arena@mysql:3306/arena?encoding=utf8&collation=utf8_general_ci
- REDIS_PROVIDER=redis://redis:6379
- AWS_ACCESS_KEY=AKIAIOSFODNN7EXAMPLE
- AWS_SECRET_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
- AWS_REGION=us-east-1
tmpfs:
- /app/tmp
grader:
Expand All @@ -59,6 +65,9 @@ services:
- RAILS_ENV=development
- DATABASE_URL=mysql2://arena:arena@mysql:3306/arena?encoding=utf8&collation=utf8_general_ci
- REDIS_PROVIDER=redis://redis:6379
- AWS_ACCESS_KEY=AKIAIOSFODNN7EXAMPLE
- AWS_SECRET_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
- AWS_REGION=us-east-1
volumes:
- ./sets:/app/sets:ro
- ./sandbox:/app/sandbox
Expand All @@ -67,6 +76,16 @@ services:
image: redis:alpine
memcached:
image: memcached:alpine
minio:
image: minio/minio
environment:
- MINIO_ACCESS_KEY=AKIAIOSFODNN7EXAMPLE
- MINIO_SECRET_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
ports:
- 9000:9000
command: "server /data"
volumes:
- ./sets:/data
mysql:
image: mariadb
volumes:
Expand Down
31 changes: 31 additions & 0 deletions spec/services/upload_problem_assets_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
describe UploadProblemAssets do
let(:problem) { create(:problem) }
let(:file_zip) { fixture_file_upload(file_fixture("archive.zip")) }
let(:file_in) { fixture_file_upload(file_fixture("task_input.in00")) }

it "creates assets for all uploaded files" do
ProcessUploadedFile.new(file_zip, problem).extract

expect(problem.all_files.length).to be > 0

UploadProblemAssets.new(problem).call

expect(problem.assets.count).to eq(problem.all_files.count)

expect(problem.assets_blobs.map(&:filename).sort + ["test"]).to eq(problem.all_files.map { |file| File.basename(file) }.sort)
end

it "is idempotent" do
ProcessUploadedFile.new(file_in, problem).extract

expect(problem.all_files.length).to eq(1)

UploadProblemAssets.new(problem).call

expect(problem.assets.count).to eq(1)

UploadProblemAssets.new(problem).call

expect(problem.assets.reload.count).to eq(1)
end
end