Skip to content

Commit

Permalink
Cache PDF on job submission, and download it if available
Browse files Browse the repository at this point in the history
  • Loading branch information
starswan committed Nov 25, 2024
1 parent 32e64d7 commit 3a41bd5
Show file tree
Hide file tree
Showing 10 changed files with 88 additions and 11 deletions.
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ gem "govuk-components", "~> 5.7.1"
gem "govuk_design_system_formbuilder", "~> 5.7.1"
gem "high_voltage"
gem "httparty"
gem "image_processing", "~> 1.2"
gem "ipaddr"
gem "jbuilder"
gem "jwt"
Expand Down
12 changes: 9 additions & 3 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -226,8 +226,7 @@ GEM
faraday-net_http (3.3.0)
net-http
fastimage (2.3.1)
ffi (1.17.0-arm64-darwin)
ffi (1.17.0-x86_64-linux-gnu)
ffi (1.16.3)
friendly_id (5.5.1)
activerecord (>= 4.0.0)
front_matter_parser (1.0.1)
Expand Down Expand Up @@ -296,6 +295,9 @@ GEM
httpclient (2.8.3)
i18n (1.14.6)
concurrent-ruby (~> 1.0)
image_processing (1.13.0)
mini_magick (>= 4.9.5, < 5)
ruby-vips (>= 2.0.17, < 3)
inflection (1.0.0)
io-console (0.7.2)
ipaddr (1.2.7)
Expand Down Expand Up @@ -353,7 +355,7 @@ GEM
mimemagic (0.4.3)
nokogiri (~> 1)
rake
mini_magick (5.0.1)
mini_magick (4.13.2)
mini_mime (1.1.5)
minitest (5.25.1)
multi_json (1.15.0)
Expand Down Expand Up @@ -618,6 +620,9 @@ GEM
rubocop-rspec (~> 3, >= 3.0.1)
ruby-progressbar (1.13.0)
ruby-rc4 (0.1.5)
ruby-vips (2.2.2)
ffi (~> 1.12)
logger
rubyzip (2.3.2)
sanitize (6.1.3)
crass (~> 1.0.2)
Expand Down Expand Up @@ -812,6 +817,7 @@ DEPENDENCIES
govuk_design_system_formbuilder (~> 5.7.1)
high_voltage
httparty
image_processing (~> 1.2)
ipaddr
jbuilder
jsbundling-rails
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,24 @@ def show
end

def download_pdf
pdf = JobApplicationPdfGenerator.new(job_application, vacancy).generate

send_data(
pdf.render,
filename: "job_application_#{job_application.id}.pdf",
type: "application/pdf",
disposition: "inline",
)
if job_application.pdf_version.attached?
send_data(
job_application.pdf_version.attachment.download,
filename: "job_application_#{job_application.id}.pdf",
type: "application/pdf",
disposition: "inline",
)
else
pdf = JobApplicationPdfGenerator.new(job_application, vacancy).generate
pdf_data = pdf.render

send_data(
pdf_data,
filename: "job_application_#{job_application.id}.pdf",
type: "application/pdf",
disposition: "inline",
)
end
end

def update_status
Expand Down
13 changes: 13 additions & 0 deletions app/jobs/make_job_application_pdf_job.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
class MakeJobApplicationPdfJob < ApplicationJob
queue_as :low

def perform(job_application)
pdf = JobApplicationPdfGenerator.new(job_application, job_application.vacancy).generate
pdf_data = pdf.render

job_application.pdf_version.attach(io: StringIO.open(pdf_data),
filename: "job_application_#{job_application.id}.pdf",
identify: false,
content_type: "application/pdf")
end
end
3 changes: 3 additions & 0 deletions app/models/job_application.rb
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ class JobApplication < ApplicationRecord

has_many :feedbacks, dependent: :destroy, inverse_of: :job_application

has_one_attached :pdf_version, service: :amazon_s3_documents

has_noticed_notifications

scope :submitted_yesterday, -> { submitted.where("DATE(submitted_at) = ?", Date.yesterday) }
Expand All @@ -80,6 +82,7 @@ def submit!
submitted!
Publishers::JobApplicationReceivedNotifier.with(vacancy: vacancy, job_application: self).deliver(vacancy.publisher)
Jobseekers::JobApplicationMailer.application_submitted(self).deliver_later
MakeJobApplicationPdfJob.perform_later self
end

def for_a_teaching_role?
Expand Down
2 changes: 2 additions & 0 deletions config/application.rb
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ class Application < Rails::Application

config.active_storage.routes_prefix = "/attachments"
config.active_storage.resolve_model_to_route = :rails_storage_proxy
# avoid default of :vips for now - we already have mini_magick
config.active_storage.variant_processor = :mini_magick

config.log_level = ENV.fetch("RAILS_LOG_LEVEL", "info").to_sym

Expand Down
11 changes: 11 additions & 0 deletions lib/tasks/backfill_application_pdfs.rake
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
namespace :vacancy do
desc "backfill all submitted applications to have a PDF version"

task backfill_application_pdfs: :environment do
Vacancy.expires_within_data_access_period.find_each do |vacancy|
vacancy.job_applications.after_submission.reject { |ja| ja.pdf_version.attached? }.each do |job_application|
MakeJobApplicationPdfJob.perform_later job_application
end
end
end
end
1 change: 1 addition & 0 deletions spec/configuration/sidekiq_scheduled_jobs_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
SetOrganisationSlugsJob
SetOrganisationSlugsOfBatchJob
ImportFromVacancySourceJob
MakeJobApplicationPdfJob
]
end

Expand Down
10 changes: 10 additions & 0 deletions spec/jobs/make_job_application_pdf_job_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
require "rails_helper"

RSpec.describe MakeJobApplicationPdfJob do
let(:job_application) { create(:job_application, :status_submitted) }

it "produces a PDF when called" do
described_class.perform_now job_application
expect(job_application.pdf_version).not_to be_nil
end
end
20 changes: 20 additions & 0 deletions spec/requests/publishers/vacancies/job_applications_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,26 @@
end
end

describe "download pdf" do
context "without cache" do
it "allows the PDF to be downloaded" do
get(organisation_job_job_application_download_pdf_path(vacancy.id, job_application.id))
expect(response.body).to satisfy { |body| body.size > 128000 }
end
end

context "with cache" do
before do
MakeJobApplicationPdfJob.perform_now job_application
end

it "allows the PDF to be downloaded" do
get(organisation_job_job_application_download_pdf_path(vacancy.id, job_application.id))
expect(response.body).to satisfy { |body| body.size > 128000 }
end
end
end

describe "GET #index" do
context "when the vacancy does not belong to the current organisation" do
let(:vacancy) { create(:vacancy, :published, organisations: [build(:school)]) }
Expand Down

0 comments on commit 3a41bd5

Please sign in to comment.