diff --git a/app/assets/javascripts/ovens/show.js b/app/assets/javascripts/ovens/show.js new file mode 100644 index 0000000..d401094 --- /dev/null +++ b/app/assets/javascripts/ovens/show.js @@ -0,0 +1,11 @@ +document.addEventListener('DOMContentLoaded', () => { + let cookieStatus, eventSource; + + cookieStatus = document.querySelector('.cookie-status'); + eventSource = new EventSource('/ovens/2/progress'); + + eventSource.addEventListener('message', event => { + cookieStatus.innerHTML = event.data; + eventSource.close(); + }); +}) diff --git a/app/controllers/ovens_controller.rb b/app/controllers/ovens_controller.rb index 20cbbfc..015c162 100755 --- a/app/controllers/ovens_controller.rb +++ b/app/controllers/ovens_controller.rb @@ -1,4 +1,7 @@ class OvensController < ApplicationController + include ActionController::Live + SSE_RETRY_TIME = 5000.freeze + before_action :authenticate_user! def index @@ -16,4 +19,19 @@ def empty end redirect_to @oven, alert: 'Oven emptied!' end + + def progress + @oven = Oven.find(params[:id]) + sse = SSE.new(response.stream) + response.headers['Content-Type'] = 'text/event-stream' + + return sse.close if @oven.cookie.ready? == false + + template = render_to_string(partial: 'cookie.ready', formats: [:html]) + sse.write(template, retry: SSE_RETRY_TIME) + rescue IOError + Rails.Logger.error(IOError) + ensure + sse.close if sse.present? + end end diff --git a/app/views/ovens/_cookie.ready.html.haml b/app/views/ovens/_cookie.ready.html.haml new file mode 100644 index 0000000..4fd5541 --- /dev/null +++ b/app/views/ovens/_cookie.ready.html.haml @@ -0,0 +1,2 @@ +(Your Cookie is Ready) += button_to "Retrieve Cookie", empty_oven_path, class: 'button tiny' diff --git a/app/views/ovens/show.html.haml b/app/views/ovens/show.html.haml index 58bf18a..d41b523 100755 --- a/app/views/ovens/show.html.haml +++ b/app/views/ovens/show.html.haml @@ -4,12 +4,13 @@ Cookie in oven: - if @oven.cookie 1 cookie with #{show_cookie_filling(@oven.cookie)} - - if @oven.cookie.ready? - (Your Cookie is Ready) - = button_to "Retrieve Cookie", empty_oven_path, class: 'button tiny' + .cookie-status + - if @oven.cookie.ready? + = render 'ovens/cookie.ready' - else None %br = link_to "Prepare Cookie", new_oven_cookies_path(@oven), class: 'button' += javascript_include_tag "ovens/show" diff --git a/config/environments/development.rb b/config/environments/development.rb index b612833..60a04c8 100755 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -6,6 +6,8 @@ # since you don't have to restart the web server when you make code changes. config.cache_classes = false + config.allow_concurrency = true + # Do not eager load code on boot. config.eager_load = false diff --git a/config/environments/production.rb b/config/environments/production.rb index 1f1431a..eae84b0 100755 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -4,6 +4,8 @@ # Code is not reloaded between requests. config.cache_classes = true + config.allow_concurrency = true + # Eager load code on boot. This eager loads most of Rails and # your application in memory, allowing both threaded web servers # and those relying on copy on write to perform better. diff --git a/config/initializers/assets.rb b/config/initializers/assets.rb index fd10964..28b8230 100755 --- a/config/initializers/assets.rb +++ b/config/initializers/assets.rb @@ -12,4 +12,4 @@ # application.js, application.css, and all non-JS/CSS in the app/assets # folder are already added. # Rails.application.config.assets.precompile += %w[admin.js admin.css] -Rails.application.config.assets.precompile += %w[vendor/modernizr] +Rails.application.config.assets.precompile += %w[vendor/modernizr ovens/show] diff --git a/config/routes.rb b/config/routes.rb index d16d0b2..129ec8f 100755 --- a/config/routes.rb +++ b/config/routes.rb @@ -12,6 +12,7 @@ resources :ovens do resource :cookies member do + get :progress post :empty end end diff --git a/spec/controllers/ovens_controller_spec.rb b/spec/controllers/ovens_controller_spec.rb index b275f49..de57fa9 100755 --- a/spec/controllers/ovens_controller_spec.rb +++ b/spec/controllers/ovens_controller_spec.rb @@ -117,4 +117,22 @@ end end + + describe 'GET progress' do + context "when not authenticated" do + before { sign_in nil } + + it "blocks access" do + the_request + expect(response).to redirect_to new_user_session_path + end + end + + context "when authenticated" do + before { get :progress } + it { expect(response.headers['Content-Type']).to eq("text/event-stream") } + after {response.stream.close unless response.stream.closed? } + end + end + end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index cfb18dc..bbd7371 100755 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -76,3 +76,23 @@ end =end end + +# Trying to debug what's wrong with RSpec and ActionController::Live +# puts "rspec pid: #{Process.pid}" +# +# trap 'USR1' do +# threads = Thread.list +# +# puts +# puts "=" * 80 +# puts "Received USR1 signal; printing all #{threads.count} thread backtraces." +# +# threads.each do |thr| +# description = thr == Thread.main ? "Main thread" : thr.inspect +# puts +# puts "#{description} backtrace: " +# puts thr.backtrace.join("\n") +# end +# +# puts "=" * 80 +# end