sidekiq 3.4.1 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of sidekiq might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/4.0-Upgrade.md +50 -0
- data/COMM-LICENSE +55 -45
- data/Changes.md +73 -1
- data/Ent-Changes.md +66 -0
- data/Gemfile +7 -1
- data/Pro-2.0-Upgrade.md +2 -2
- data/Pro-3.0-Upgrade.md +46 -0
- data/Pro-Changes.md +65 -2
- data/README.md +8 -9
- data/bin/sidekiq +5 -0
- data/bin/sidekiqctl +8 -2
- data/bin/sidekiqload +167 -0
- data/lib/sidekiq/api.rb +29 -31
- data/lib/sidekiq/cli.rb +41 -42
- data/lib/sidekiq/client.rb +5 -10
- data/lib/sidekiq/fetch.rb +35 -111
- data/lib/sidekiq/launcher.rb +102 -42
- data/lib/sidekiq/manager.rb +78 -180
- data/lib/sidekiq/middleware/server/logging.rb +10 -5
- data/lib/sidekiq/middleware/server/retry_jobs.rb +5 -5
- data/lib/sidekiq/processor.rb +126 -97
- data/lib/sidekiq/redis_connection.rb +23 -5
- data/lib/sidekiq/scheduled.rb +47 -26
- data/lib/sidekiq/testing.rb +96 -17
- data/lib/sidekiq/util.rb +20 -0
- data/lib/sidekiq/version.rb +1 -1
- data/lib/sidekiq/web.rb +17 -1
- data/lib/sidekiq/web_helpers.rb +26 -4
- data/lib/sidekiq/worker.rb +14 -0
- data/lib/sidekiq.rb +37 -14
- data/sidekiq.gemspec +11 -11
- data/test/helper.rb +45 -10
- data/test/test_actors.rb +137 -0
- data/test/test_api.rb +388 -388
- data/test/test_cli.rb +29 -59
- data/test/test_client.rb +60 -135
- data/test/test_extensions.rb +29 -23
- data/test/test_fetch.rb +2 -57
- data/test/test_launcher.rb +80 -0
- data/test/test_logging.rb +1 -1
- data/test/test_manager.rb +16 -131
- data/test/test_middleware.rb +3 -5
- data/test/test_processor.rb +110 -76
- data/test/test_rails.rb +21 -0
- data/test/test_redis_connection.rb +0 -1
- data/test/test_retry.rb +114 -162
- data/test/test_scheduled.rb +11 -17
- data/test/test_scheduling.rb +20 -42
- data/test/test_sidekiq.rb +46 -16
- data/test/test_testing.rb +80 -20
- data/test/test_testing_fake.rb +68 -8
- data/test/test_testing_inline.rb +3 -3
- data/test/test_util.rb +16 -0
- data/test/test_web.rb +17 -3
- data/test/test_web_helpers.rb +3 -2
- data/web/assets/images/favicon.ico +0 -0
- data/web/assets/javascripts/application.js +6 -1
- data/web/assets/javascripts/dashboard.js +2 -8
- data/web/assets/javascripts/locales/jquery.timeago.pt-br.js +14 -14
- data/web/assets/stylesheets/application.css +33 -56
- data/web/locales/de.yml +1 -1
- data/web/locales/en.yml +1 -0
- data/web/locales/{no.yml → nb.yml} +10 -2
- data/web/locales/uk.yml +76 -0
- data/web/views/_footer.erb +2 -7
- data/web/views/_job_info.erb +1 -1
- data/web/views/_nav.erb +2 -2
- data/web/views/_poll_js.erb +5 -0
- data/web/views/{_poll.erb → _poll_link.erb} +0 -3
- data/web/views/busy.erb +2 -1
- data/web/views/dead.erb +1 -0
- data/web/views/layout.erb +2 -0
- data/web/views/morgue.erb +3 -0
- data/web/views/queue.erb +1 -0
- data/web/views/queues.erb +1 -0
- data/web/views/retries.erb +3 -0
- data/web/views/retry.erb +1 -0
- data/web/views/scheduled.erb +1 -0
- data/web/views/scheduled_job_info.erb +1 -0
- metadata +81 -47
- data/lib/sidekiq/actor.rb +0 -39
- data/test/test_worker_generator.rb +0 -17
    
        data/test/test_testing.rb
    CHANGED
    
    | @@ -1,6 +1,5 @@ | |
| 1 1 | 
             
            require_relative 'helper'
         | 
| 2 | 
            -
             | 
| 3 | 
            -
            require 'sidekiq/worker'
         | 
| 2 | 
            +
             | 
| 4 3 | 
             
            require 'active_record'
         | 
| 5 4 | 
             
            require 'action_mailer'
         | 
| 6 5 | 
             
            require 'sidekiq/rails'
         | 
| @@ -13,7 +12,7 @@ class TestTesting < Sidekiq::Test | |
| 13 12 | 
             
              describe 'sidekiq testing' do
         | 
| 14 13 | 
             
                describe 'require/load sidekiq/testing.rb' do
         | 
| 15 14 | 
             
                  before do
         | 
| 16 | 
            -
                    require 'sidekiq/testing | 
| 15 | 
            +
                    require 'sidekiq/testing'
         | 
| 17 16 | 
             
                  end
         | 
| 18 17 |  | 
| 19 18 | 
             
                  after do
         | 
| @@ -22,37 +21,43 @@ class TestTesting < Sidekiq::Test | |
| 22 21 |  | 
| 23 22 | 
             
                  it 'enables fake testing' do
         | 
| 24 23 | 
             
                    Sidekiq::Testing.fake!
         | 
| 25 | 
            -
                     | 
| 26 | 
            -
                     | 
| 24 | 
            +
                    assert Sidekiq::Testing.enabled?
         | 
| 25 | 
            +
                    assert Sidekiq::Testing.fake?
         | 
| 26 | 
            +
                    refute Sidekiq::Testing.inline?
         | 
| 27 27 | 
             
                  end
         | 
| 28 28 |  | 
| 29 29 | 
             
                  it 'enables fake testing in a block' do
         | 
| 30 30 | 
             
                    Sidekiq::Testing.disable!
         | 
| 31 | 
            -
                     | 
| 31 | 
            +
                    assert Sidekiq::Testing.disabled?
         | 
| 32 | 
            +
                    refute Sidekiq::Testing.fake?
         | 
| 32 33 |  | 
| 33 34 | 
             
                    Sidekiq::Testing.fake! do
         | 
| 34 | 
            -
                       | 
| 35 | 
            -
                       | 
| 35 | 
            +
                      assert Sidekiq::Testing.enabled?
         | 
| 36 | 
            +
                      assert Sidekiq::Testing.fake?
         | 
| 37 | 
            +
                      refute Sidekiq::Testing.inline?
         | 
| 36 38 | 
             
                    end
         | 
| 37 39 |  | 
| 38 | 
            -
                     | 
| 39 | 
            -
                     | 
| 40 | 
            +
                    refute Sidekiq::Testing.enabled?
         | 
| 41 | 
            +
                    refute Sidekiq::Testing.fake?
         | 
| 40 42 | 
             
                  end
         | 
| 41 43 |  | 
| 42 44 | 
             
                  it 'disables testing in a block' do
         | 
| 43 45 | 
             
                    Sidekiq::Testing.fake!
         | 
| 46 | 
            +
                    assert Sidekiq::Testing.fake?
         | 
| 44 47 |  | 
| 45 48 | 
             
                    Sidekiq::Testing.disable! do
         | 
| 46 | 
            -
                       | 
| 49 | 
            +
                      refute Sidekiq::Testing.fake?
         | 
| 50 | 
            +
                      assert Sidekiq::Testing.disabled?
         | 
| 47 51 | 
             
                    end
         | 
| 48 52 |  | 
| 49 | 
            -
                     | 
| 53 | 
            +
                    assert Sidekiq::Testing.fake?
         | 
| 54 | 
            +
                    assert Sidekiq::Testing.enabled?
         | 
| 50 55 | 
             
                  end
         | 
| 51 56 | 
             
                end
         | 
| 52 57 |  | 
| 53 58 | 
             
                describe 'require/load sidekiq/testing/inline.rb' do
         | 
| 54 59 | 
             
                  before do
         | 
| 55 | 
            -
                    require 'sidekiq/testing/inline | 
| 60 | 
            +
                    require 'sidekiq/testing/inline'
         | 
| 56 61 | 
             
                  end
         | 
| 57 62 |  | 
| 58 63 | 
             
                  after do
         | 
| @@ -61,22 +66,77 @@ class TestTesting < Sidekiq::Test | |
| 61 66 |  | 
| 62 67 | 
             
                  it 'enables inline testing' do
         | 
| 63 68 | 
             
                    Sidekiq::Testing.inline!
         | 
| 64 | 
            -
                     | 
| 65 | 
            -
                     | 
| 69 | 
            +
                    assert Sidekiq::Testing.enabled?
         | 
| 70 | 
            +
                    assert Sidekiq::Testing.inline?
         | 
| 71 | 
            +
                    refute Sidekiq::Testing.fake?
         | 
| 66 72 | 
             
                  end
         | 
| 67 73 |  | 
| 68 74 | 
             
                  it 'enables inline testing in a block' do
         | 
| 69 75 | 
             
                    Sidekiq::Testing.disable!
         | 
| 70 | 
            -
                     | 
| 76 | 
            +
                    assert Sidekiq::Testing.disabled?
         | 
| 77 | 
            +
                    refute Sidekiq::Testing.fake?
         | 
| 71 78 |  | 
| 72 79 | 
             
                    Sidekiq::Testing.inline! do
         | 
| 73 | 
            -
                       | 
| 74 | 
            -
                       | 
| 80 | 
            +
                      assert Sidekiq::Testing.enabled?
         | 
| 81 | 
            +
                      assert Sidekiq::Testing.inline?
         | 
| 75 82 | 
             
                    end
         | 
| 76 83 |  | 
| 77 | 
            -
                     | 
| 78 | 
            -
                     | 
| 84 | 
            +
                    refute Sidekiq::Testing.enabled?
         | 
| 85 | 
            +
                    refute Sidekiq::Testing.inline?
         | 
| 86 | 
            +
                    refute Sidekiq::Testing.fake?
         | 
| 79 87 | 
             
                  end
         | 
| 80 88 | 
             
                end
         | 
| 81 89 | 
             
              end
         | 
| 90 | 
            +
             | 
| 91 | 
            +
              describe 'with middleware' do
         | 
| 92 | 
            +
                before do
         | 
| 93 | 
            +
                  require 'sidekiq/testing'
         | 
| 94 | 
            +
                end
         | 
| 95 | 
            +
             | 
| 96 | 
            +
                after do
         | 
| 97 | 
            +
                  Sidekiq::Testing.disable!
         | 
| 98 | 
            +
                end
         | 
| 99 | 
            +
             | 
| 100 | 
            +
                class AttributeWorker
         | 
| 101 | 
            +
                  include Sidekiq::Worker
         | 
| 102 | 
            +
                  class_attribute :count
         | 
| 103 | 
            +
                  self.count = 0
         | 
| 104 | 
            +
                  attr_accessor :foo
         | 
| 105 | 
            +
             | 
| 106 | 
            +
                  def perform
         | 
| 107 | 
            +
                    self.class.count += 1 if foo == :bar
         | 
| 108 | 
            +
                  end
         | 
| 109 | 
            +
                end
         | 
| 110 | 
            +
             | 
| 111 | 
            +
                class AttributeMiddleware
         | 
| 112 | 
            +
                  def call(worker, msg, queue)
         | 
| 113 | 
            +
                    worker.foo = :bar if worker.respond_to?(:foo=)
         | 
| 114 | 
            +
                    yield
         | 
| 115 | 
            +
                  end
         | 
| 116 | 
            +
                end
         | 
| 117 | 
            +
             | 
| 118 | 
            +
                it 'wraps the inlined worker with middleware' do
         | 
| 119 | 
            +
                  Sidekiq::Testing.server_middleware do |chain|
         | 
| 120 | 
            +
                    chain.add AttributeMiddleware
         | 
| 121 | 
            +
                  end
         | 
| 122 | 
            +
             | 
| 123 | 
            +
                  begin
         | 
| 124 | 
            +
                    Sidekiq::Testing.fake! do
         | 
| 125 | 
            +
                      AttributeWorker.perform_async
         | 
| 126 | 
            +
                      assert_equal 0, AttributeWorker.count
         | 
| 127 | 
            +
                    end
         | 
| 128 | 
            +
             | 
| 129 | 
            +
                    AttributeWorker.perform_one
         | 
| 130 | 
            +
                    assert_equal 1, AttributeWorker.count
         | 
| 131 | 
            +
             | 
| 132 | 
            +
                    Sidekiq::Testing.inline! do
         | 
| 133 | 
            +
                      AttributeWorker.perform_async
         | 
| 134 | 
            +
                      assert_equal 2, AttributeWorker.count
         | 
| 135 | 
            +
                    end
         | 
| 136 | 
            +
                  ensure
         | 
| 137 | 
            +
                    Sidekiq::Testing.server_middleware.clear
         | 
| 138 | 
            +
                  end
         | 
| 139 | 
            +
                end
         | 
| 140 | 
            +
              end
         | 
| 141 | 
            +
             | 
| 82 142 | 
             
            end
         | 
    
        data/test/test_testing_fake.rb
    CHANGED
    
    | @@ -1,6 +1,5 @@ | |
| 1 1 | 
             
            require_relative 'helper'
         | 
| 2 | 
            -
             | 
| 3 | 
            -
            require 'sidekiq/worker'
         | 
| 2 | 
            +
             | 
| 4 3 | 
             
            require 'active_record'
         | 
| 5 4 | 
             
            require 'action_mailer'
         | 
| 6 5 | 
             
            require 'sidekiq/rails'
         | 
| @@ -47,7 +46,7 @@ class TestTesting < Sidekiq::Test | |
| 47 46 | 
             
                end
         | 
| 48 47 |  | 
| 49 48 | 
             
                before do
         | 
| 50 | 
            -
                  require 'sidekiq/testing | 
| 49 | 
            +
                  require 'sidekiq/testing'
         | 
| 51 50 | 
             
                  Sidekiq::Testing.fake!
         | 
| 52 51 | 
             
                  EnqueuedWorker.jobs.clear
         | 
| 53 52 | 
             
                  DirectWorker.jobs.clear
         | 
| @@ -55,6 +54,7 @@ class TestTesting < Sidekiq::Test | |
| 55 54 |  | 
| 56 55 | 
             
                after do
         | 
| 57 56 | 
             
                  Sidekiq::Testing.disable!
         | 
| 57 | 
            +
                  Sidekiq::Queues.clear_all
         | 
| 58 58 | 
             
                end
         | 
| 59 59 |  | 
| 60 60 | 
             
                it 'stubs the async call' do
         | 
| @@ -94,7 +94,7 @@ class TestTesting < Sidekiq::Test | |
| 94 94 | 
             
                it 'stubs the enqueue_to call' do
         | 
| 95 95 | 
             
                  assert_equal 0, EnqueuedWorker.jobs.size
         | 
| 96 96 | 
             
                  assert Sidekiq::Client.enqueue_to('someq', EnqueuedWorker, 1, 2)
         | 
| 97 | 
            -
                  assert_equal 1,  | 
| 97 | 
            +
                  assert_equal 1, Sidekiq::Queues['someq'].size
         | 
| 98 98 | 
             
                end
         | 
| 99 99 |  | 
| 100 100 | 
             
                it 'executes all stored jobs' do
         | 
| @@ -106,7 +106,6 @@ class TestTesting < Sidekiq::Test | |
| 106 106 | 
             
                    StoredWorker.drain
         | 
| 107 107 | 
             
                  end
         | 
| 108 108 | 
             
                  assert_equal 0, StoredWorker.jobs.size
         | 
| 109 | 
            -
             | 
| 110 109 | 
             
                end
         | 
| 111 110 |  | 
| 112 111 | 
             
                class SpecificJidWorker
         | 
| @@ -263,9 +262,70 @@ class TestTesting < Sidekiq::Test | |
| 263 262 | 
             
                end
         | 
| 264 263 |  | 
| 265 264 | 
             
                it 'can execute a job' do
         | 
| 266 | 
            -
                   | 
| 267 | 
            -
             | 
| 268 | 
            -
             | 
| 265 | 
            +
                  DirectWorker.execute_job(DirectWorker.new, [2, 3])
         | 
| 266 | 
            +
                end
         | 
| 267 | 
            +
              end
         | 
| 268 | 
            +
             | 
| 269 | 
            +
              describe 'queue testing' do
         | 
| 270 | 
            +
                before do
         | 
| 271 | 
            +
                  require 'sidekiq/testing'
         | 
| 272 | 
            +
                  Sidekiq::Testing.fake!
         | 
| 273 | 
            +
                end
         | 
| 274 | 
            +
             | 
| 275 | 
            +
                after do
         | 
| 276 | 
            +
                  Sidekiq::Testing.disable!
         | 
| 277 | 
            +
                  Sidekiq::Queues.clear_all
         | 
| 278 | 
            +
                end
         | 
| 279 | 
            +
             | 
| 280 | 
            +
                class QueueWorker
         | 
| 281 | 
            +
                  include Sidekiq::Worker
         | 
| 282 | 
            +
                  def perform(a, b)
         | 
| 283 | 
            +
                    a + b
         | 
| 284 | 
            +
                  end
         | 
| 285 | 
            +
                end
         | 
| 286 | 
            +
             | 
| 287 | 
            +
                class AltQueueWorker
         | 
| 288 | 
            +
                  include Sidekiq::Worker
         | 
| 289 | 
            +
                  sidekiq_options queue: :alt
         | 
| 290 | 
            +
                  def perform(a, b)
         | 
| 291 | 
            +
                    a + b
         | 
| 292 | 
            +
                  end
         | 
| 293 | 
            +
                end
         | 
| 294 | 
            +
             | 
| 295 | 
            +
                it 'finds enqueued jobs' do
         | 
| 296 | 
            +
                  assert_equal 0, Sidekiq::Queues["default"].size
         | 
| 297 | 
            +
             | 
| 298 | 
            +
                  QueueWorker.perform_async(1, 2)
         | 
| 299 | 
            +
                  QueueWorker.perform_async(1, 2)
         | 
| 300 | 
            +
                  AltQueueWorker.perform_async(1, 2)
         | 
| 301 | 
            +
             | 
| 302 | 
            +
                  assert_equal 2, Sidekiq::Queues["default"].size
         | 
| 303 | 
            +
                  assert_equal [1, 2], Sidekiq::Queues["default"].first["args"]
         | 
| 304 | 
            +
             | 
| 305 | 
            +
                  assert_equal 1, Sidekiq::Queues["alt"].size
         | 
| 306 | 
            +
                end
         | 
| 307 | 
            +
             | 
| 308 | 
            +
                it 'clears out all queues' do
         | 
| 309 | 
            +
                  assert_equal 0, Sidekiq::Queues["default"].size
         | 
| 310 | 
            +
             | 
| 311 | 
            +
                  QueueWorker.perform_async(1, 2)
         | 
| 312 | 
            +
                  QueueWorker.perform_async(1, 2)
         | 
| 313 | 
            +
                  AltQueueWorker.perform_async(1, 2)
         | 
| 314 | 
            +
             | 
| 315 | 
            +
                  Sidekiq::Queues.clear_all
         | 
| 316 | 
            +
             | 
| 317 | 
            +
                  assert_equal 0, Sidekiq::Queues["default"].size
         | 
| 318 | 
            +
                  assert_equal 0, Sidekiq::Queues["alt"].size
         | 
| 319 | 
            +
                end
         | 
| 320 | 
            +
             | 
| 321 | 
            +
                it 'finds jobs enqueued by client' do
         | 
| 322 | 
            +
                  Sidekiq::Client.push(
         | 
| 323 | 
            +
                    'class' => 'NonExistentWorker',
         | 
| 324 | 
            +
                    'queue' => 'missing',
         | 
| 325 | 
            +
                    'args' => [1]
         | 
| 326 | 
            +
                  )
         | 
| 327 | 
            +
             | 
| 328 | 
            +
                  assert_equal 1, Sidekiq::Queues["missing"].size
         | 
| 269 329 | 
             
                end
         | 
| 270 330 | 
             
              end
         | 
| 271 331 | 
             
            end
         | 
    
        data/test/test_testing_inline.rb
    CHANGED
    
    | @@ -1,6 +1,5 @@ | |
| 1 1 | 
             
            require_relative 'helper'
         | 
| 2 | 
            -
             | 
| 3 | 
            -
            require 'sidekiq/worker'
         | 
| 2 | 
            +
             | 
| 4 3 | 
             
            require 'active_record'
         | 
| 5 4 | 
             
            require 'action_mailer'
         | 
| 6 5 | 
             
            require 'sidekiq/rails'
         | 
| @@ -42,7 +41,7 @@ class TestInline < Sidekiq::Test | |
| 42 41 | 
             
                end
         | 
| 43 42 |  | 
| 44 43 | 
             
                before do
         | 
| 45 | 
            -
                  require 'sidekiq/testing/inline | 
| 44 | 
            +
                  require 'sidekiq/testing/inline'
         | 
| 46 45 | 
             
                  Sidekiq::Testing.inline!
         | 
| 47 46 | 
             
                end
         | 
| 48 47 |  | 
| @@ -89,5 +88,6 @@ class TestInline < Sidekiq::Test | |
| 89 88 | 
             
                it 'should relay parameters through json' do
         | 
| 90 89 | 
             
                  assert Sidekiq::Client.enqueue(InlineWorkerWithTimeParam, Time.now)
         | 
| 91 90 | 
             
                end
         | 
| 91 | 
            +
             | 
| 92 92 | 
             
              end
         | 
| 93 93 | 
             
            end
         | 
    
        data/test/test_util.rb
    ADDED
    
    | @@ -0,0 +1,16 @@ | |
| 1 | 
            +
            require_relative 'helper'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            class TestUtil < Sidekiq::Test
         | 
| 4 | 
            +
             | 
| 5 | 
            +
              class Helpers
         | 
| 6 | 
            +
                include Sidekiq::Util
         | 
| 7 | 
            +
              end
         | 
| 8 | 
            +
             | 
| 9 | 
            +
              def test_hertz_donut
         | 
| 10 | 
            +
                obj = Helpers.new
         | 
| 11 | 
            +
                output = capture_logging(Logger::DEBUG) do
         | 
| 12 | 
            +
                  assert_equal false, obj.want_a_hertz_donut?
         | 
| 13 | 
            +
                end
         | 
| 14 | 
            +
                assert_includes output, "hz: 10"
         | 
| 15 | 
            +
              end
         | 
| 16 | 
            +
            end
         | 
    
        data/test/test_web.rb
    CHANGED
    
    | @@ -1,8 +1,8 @@ | |
| 1 1 | 
             
            # encoding: utf-8
         | 
| 2 2 | 
             
            require_relative 'helper'
         | 
| 3 | 
            -
            require 'sidekiq'
         | 
| 4 3 | 
             
            require 'sidekiq/web'
         | 
| 5 4 | 
             
            require 'rack/test'
         | 
| 5 | 
            +
            require 'tilt/erubis'
         | 
| 6 6 |  | 
| 7 7 | 
             
            class TestWeb < Sidekiq::Test
         | 
| 8 8 |  | 
| @@ -18,7 +18,6 @@ class TestWeb < Sidekiq::Test | |
| 18 18 | 
             
                end
         | 
| 19 19 |  | 
| 20 20 | 
             
                before do
         | 
| 21 | 
            -
                  Sidekiq.redis = REDIS
         | 
| 22 21 | 
             
                  Sidekiq.redis {|c| c.flushdb }
         | 
| 23 22 | 
             
                end
         | 
| 24 23 |  | 
| @@ -40,6 +39,15 @@ class TestWeb < Sidekiq::Test | |
| 40 39 | 
             
                  rackenv = {'HTTP_ACCEPT_LANGUAGE' => 'en-us'}
         | 
| 41 40 | 
             
                  get '/', {}, rackenv
         | 
| 42 41 | 
             
                  assert_match(/Dashboard/, last_response.body)
         | 
| 42 | 
            +
                  rackenv = {'HTTP_ACCEPT_LANGUAGE' => 'zh-cn'}
         | 
| 43 | 
            +
                  get '/', {}, rackenv
         | 
| 44 | 
            +
                  assert_match(/信息板/, last_response.body)
         | 
| 45 | 
            +
                  rackenv = {'HTTP_ACCEPT_LANGUAGE' => 'zh-tw'}
         | 
| 46 | 
            +
                  get '/', {}, rackenv
         | 
| 47 | 
            +
                  assert_match(/資訊主頁/, last_response.body)
         | 
| 48 | 
            +
                  rackenv = {'HTTP_ACCEPT_LANGUAGE' => 'nb'}
         | 
| 49 | 
            +
                  get '/', {}, rackenv
         | 
| 50 | 
            +
                  assert_match(/Oversikt/, last_response.body)
         | 
| 43 51 | 
             
                end
         | 
| 44 52 |  | 
| 45 53 | 
             
                describe 'busy' do
         | 
| @@ -292,7 +300,13 @@ class TestWeb < Sidekiq::Test | |
| 292 300 |  | 
| 293 301 | 
             
                  get '/queues/default'
         | 
| 294 302 | 
             
                  assert_equal 200, last_response.status
         | 
| 295 | 
            -
                  assert_match | 
| 303 | 
            +
                  assert_match(/#{msg['args'][2]}/, last_response.body)
         | 
| 304 | 
            +
                end
         | 
| 305 | 
            +
             | 
| 306 | 
            +
                it 'calls updatePage() once when polling' do
         | 
| 307 | 
            +
                  get '/busy?poll=true'
         | 
| 308 | 
            +
                  assert_equal 200, last_response.status
         | 
| 309 | 
            +
                  assert_equal 1, last_response.body.scan('updatePage(').count
         | 
| 296 310 | 
             
                end
         | 
| 297 311 |  | 
| 298 312 | 
             
                it 'escape job args and error messages' do
         | 
    
        data/test/test_web_helpers.rb
    CHANGED
    
    | @@ -1,6 +1,4 @@ | |
| 1 1 | 
             
            require_relative 'helper'
         | 
| 2 | 
            -
            require 'sidekiq'
         | 
| 3 | 
            -
            require 'sidekiq/web_helpers'
         | 
| 4 2 |  | 
| 5 3 | 
             
            class TestWebHelpers < Sidekiq::Test
         | 
| 6 4 |  | 
| @@ -43,6 +41,9 @@ class TestWebHelpers < Sidekiq::Test | |
| 43 41 | 
             
                obj = Helpers.new('HTTP_ACCEPT_LANGUAGE' => 'zh-CN,zh;q=0.8,en-US;q=0.6,en;q=0.4,ru;q=0.2')
         | 
| 44 42 | 
             
                assert_equal 'zh-cn', obj.locale
         | 
| 45 43 |  | 
| 44 | 
            +
                obj = Helpers.new('HTTP_ACCEPT_LANGUAGE' => 'nb-NO,nb;q=0.2')
         | 
| 45 | 
            +
                assert_equal 'nb', obj.locale
         | 
| 46 | 
            +
             | 
| 46 47 | 
             
                obj = Helpers.new('HTTP_ACCEPT_LANGUAGE' => 'en-us; *')
         | 
| 47 48 | 
             
                assert_equal 'en', obj.locale
         | 
| 48 49 |  | 
| Binary file | 
| @@ -58,9 +58,14 @@ function updatePage(url) { | |
| 58 58 | 
             
                  url: url,
         | 
| 59 59 | 
             
                  dataType: 'html'
         | 
| 60 60 | 
             
                }).done(function (data) {
         | 
| 61 | 
            -
                   | 
| 61 | 
            +
                  $data = $(data)
         | 
| 62 | 
            +
             | 
| 63 | 
            +
                  var $page = $data.filter('#page')
         | 
| 62 64 | 
             
                  $('#page').replaceWith($page)
         | 
| 63 65 |  | 
| 66 | 
            +
                  var $header_status = $data.find('.status')
         | 
| 67 | 
            +
                  $('.status').replaceWith($header_status)
         | 
| 68 | 
            +
             | 
| 64 69 | 
             
                  $("time").timeago()
         | 
| 65 70 | 
             
                })
         | 
| 66 71 | 
             
              }, parseInt(localStorage.timeInterval) || 2000);
         | 
| @@ -227,14 +227,8 @@ var updateRedisStats = function(data) { | |
| 227 227 | 
             
            }
         | 
| 228 228 |  | 
| 229 229 | 
             
            var pulseBeacon = function(){
         | 
| 230 | 
            -
              $ | 
| 231 | 
            -
             | 
| 232 | 
            -
                $(this).removeClass('pulse');
         | 
| 233 | 
            -
                $(this).dequeue();
         | 
| 234 | 
            -
              });
         | 
| 235 | 
            -
              $beacon.find('.ring').addClass('pulse').delay(1000).queue(function(){
         | 
| 236 | 
            -
                $(this).removeClass('pulse');
         | 
| 237 | 
            -
                $(this).dequeue();
         | 
| 230 | 
            +
              $('.beacon').addClass('pulse').delay(1000).queue(function(){
         | 
| 231 | 
            +
                $(this).removeClass('pulse').dequeue();
         | 
| 238 232 | 
             
              });
         | 
| 239 233 | 
             
            }
         | 
| 240 234 |  | 
| @@ -1,16 +1,16 @@ | |
| 1 | 
            -
            //  | 
| 1 | 
            +
            // Brasilian Portuguese
         | 
| 2 2 | 
             
            jQuery.timeago.settings.strings = {
         | 
| 3 3 | 
             
               suffixAgo: "atrás",
         | 
| 4 | 
            -
               suffixFromNow: " | 
| 5 | 
            -
               seconds: " | 
| 6 | 
            -
               minute: " | 
| 7 | 
            -
               minutes: " | 
| 8 | 
            -
               hour: " | 
| 9 | 
            -
               hours: " | 
| 10 | 
            -
               day: " | 
| 11 | 
            -
               days: " | 
| 12 | 
            -
               month: " | 
| 13 | 
            -
               months: " | 
| 14 | 
            -
               year: " | 
| 15 | 
            -
               years: " | 
| 16 | 
            -
            };
         | 
| 4 | 
            +
               suffixFromNow: "a partir de agora",
         | 
| 5 | 
            +
               seconds: "menos de um minuto",
         | 
| 6 | 
            +
               minute: "cerca de um minuto",
         | 
| 7 | 
            +
               minutes: "%d minutos",
         | 
| 8 | 
            +
               hour: "cerca de uma hora",
         | 
| 9 | 
            +
               hours: "cerca de %d horas",
         | 
| 10 | 
            +
               day: "um dia",
         | 
| 11 | 
            +
               days: "%d dias",
         | 
| 12 | 
            +
               month: "cerca de um mês",
         | 
| 13 | 
            +
               months: "%d meses",
         | 
| 14 | 
            +
               year: "cerca de um ano",
         | 
| 15 | 
            +
               years: "%d anos"
         | 
| 16 | 
            +
            };
         | 
| @@ -181,6 +181,10 @@ form .btn { | |
| 181 181 | 
             
              margin-right: 5px;
         | 
| 182 182 | 
             
            }
         | 
| 183 183 |  | 
| 184 | 
            +
            form .btn-group .btn {
         | 
| 185 | 
            +
              margin-right: 1px;
         | 
| 186 | 
            +
            }
         | 
| 187 | 
            +
             | 
| 184 188 | 
             
            td form {
         | 
| 185 189 | 
             
              margin-bottom: 0;
         | 
| 186 190 | 
             
            }
         | 
| @@ -471,16 +475,22 @@ div.interval-slider input { | |
| 471 475 |  | 
| 472 476 | 
             
            .beacon {
         | 
| 473 477 | 
             
              position: relative;
         | 
| 478 | 
            +
              width: 20px;
         | 
| 474 479 | 
             
              height: 20px;
         | 
| 475 480 | 
             
              display: inline-block;
         | 
| 476 481 | 
             
            }
         | 
| 477 482 |  | 
| 478 | 
            -
            .beacon .dot | 
| 483 | 
            +
            .beacon .dot,
         | 
| 484 | 
            +
            .beacon .ring {
         | 
| 479 485 | 
             
              position: absolute;
         | 
| 480 | 
            -
              top:  | 
| 481 | 
            -
              left:  | 
| 486 | 
            +
              top: 50%;
         | 
| 487 | 
            +
              left: 50%;
         | 
| 488 | 
            +
            }
         | 
| 489 | 
            +
             | 
| 490 | 
            +
            .beacon .dot {
         | 
| 482 491 | 
             
              width: 10px;
         | 
| 483 492 | 
             
              height: 10px;
         | 
| 493 | 
            +
              margin: -5px 0 0 -5px;
         | 
| 484 494 | 
             
              background-color: #80002d;
         | 
| 485 495 | 
             
              border-radius: 10px;
         | 
| 486 496 | 
             
              box-shadow: 0 0 9px #666;
         | 
| @@ -490,140 +500,103 @@ div.interval-slider input { | |
| 490 500 | 
             
              z-index: 10;
         | 
| 491 501 | 
             
            }
         | 
| 492 502 |  | 
| 493 | 
            -
            .beacon .dot | 
| 503 | 
            +
            .beacon.pulse .dot {
         | 
| 494 504 | 
             
              -webkit-animation: beacon-dot-pulse 1s ease-out;
         | 
| 495 505 | 
             
              -moz-animation: beacon-dot-pulse 1s ease-out;
         | 
| 496 506 | 
             
              animation: beacon-dot-pulse 1s ease-out;
         | 
| 497 | 
            -
              -webkit-animation-iteration-count: 1;
         | 
| 498 | 
            -
              -moz-animation-iteration-count: 1;
         | 
| 499 | 
            -
              animation-iteration-count: 1;
         | 
| 500 507 | 
             
            }
         | 
| 501 508 |  | 
| 502 509 | 
             
            @-webkit-keyframes beacon-dot-pulse {
         | 
| 503 510 | 
             
              from {
         | 
| 504 511 | 
             
                background-color: #80002d;
         | 
| 505 512 | 
             
                -webkit-box-shadow: 0 0 9px #666;
         | 
| 506 | 
            -
                -moz-box-shadow: 0 0 9px #666;
         | 
| 507 | 
            -
                box-shadow: 0 0 9px #666;
         | 
| 508 513 | 
             
              }
         | 
| 509 514 | 
             
              50% {
         | 
| 510 515 | 
             
                background-color: #c90047;
         | 
| 511 516 | 
             
                -webkit-box-shadow: 0 0 18px #666;
         | 
| 512 | 
            -
                -moz-box-shadow: 0 0 18px #666;
         | 
| 513 | 
            -
                box-shadow: 0 0 18px #666;
         | 
| 514 517 | 
             
              }
         | 
| 515 518 | 
             
              to {
         | 
| 516 519 | 
             
                background-color: #80002d;
         | 
| 517 520 | 
             
                -webkit-box-shadow: 0 0 9px #666;
         | 
| 518 | 
            -
                -moz-box-shadow: 0 0 9px #666;
         | 
| 519 | 
            -
                box-shadow: 0 0 9px #666;
         | 
| 520 521 | 
             
              }
         | 
| 521 522 | 
             
            }
         | 
| 522 523 |  | 
| 523 524 | 
             
            @-moz-keyframes beacon-dot-pulse {
         | 
| 524 525 | 
             
              from {
         | 
| 525 526 | 
             
                background-color: #80002d;
         | 
| 526 | 
            -
                -webkit-box-shadow: 0 0 9px #666;
         | 
| 527 527 | 
             
                -moz-box-shadow: 0 0 9px #666;
         | 
| 528 | 
            -
                box-shadow: 0 0 9px #666;
         | 
| 529 528 | 
             
              }
         | 
| 530 529 | 
             
              50% {
         | 
| 531 530 | 
             
                background-color: #c90047;
         | 
| 532 | 
            -
                -webkit-box-shadow: 0 0 18px #666;
         | 
| 533 531 | 
             
                -moz-box-shadow: 0 0 18px #666;
         | 
| 534 | 
            -
                box-shadow: 0 0 18px #666;
         | 
| 535 532 | 
             
              }
         | 
| 536 533 | 
             
              to {
         | 
| 537 534 | 
             
                background-color: #80002d;
         | 
| 538 | 
            -
                -webkit-box-shadow: 0 0 9px #666;
         | 
| 539 535 | 
             
                -moz-box-shadow: 0 0 9px #666;
         | 
| 540 | 
            -
                box-shadow: 0 0 9px #666;
         | 
| 541 536 | 
             
              }
         | 
| 542 537 | 
             
            }
         | 
| 543 538 |  | 
| 544 539 | 
             
            @keyframes beacon-dot-pulse {
         | 
| 545 540 | 
             
              from {
         | 
| 546 541 | 
             
                background-color: #80002d;
         | 
| 547 | 
            -
                -webkit-box-shadow: 0 0 9px #666;
         | 
| 548 | 
            -
                -moz-box-shadow: 0 0 9px #666;
         | 
| 549 542 | 
             
                box-shadow: 0 0 9px #666;
         | 
| 550 543 | 
             
              }
         | 
| 551 544 | 
             
              50% {
         | 
| 552 545 | 
             
                background-color: #c90047;
         | 
| 553 | 
            -
                -webkit-box-shadow: 0 0 18px #666;
         | 
| 554 | 
            -
                -moz-box-shadow: 0 0 18px #666;
         | 
| 555 546 | 
             
                box-shadow: 0 0 18px #666;
         | 
| 556 547 | 
             
              }
         | 
| 557 548 | 
             
              to {
         | 
| 558 549 | 
             
                background-color: #80002d;
         | 
| 559 | 
            -
                -webkit-box-shadow: 0 0 9px #666;
         | 
| 560 | 
            -
                -moz-box-shadow: 0 0 9px #666;
         | 
| 561 550 | 
             
                box-shadow: 0 0 9px #666;
         | 
| 562 551 | 
             
              }
         | 
| 563 552 | 
             
            }
         | 
| 564 553 |  | 
| 565 554 | 
             
            .beacon .ring {
         | 
| 566 | 
            -
               | 
| 567 | 
            -
               | 
| 568 | 
            -
               | 
| 569 | 
            -
               | 
| 570 | 
            -
              height: 0;
         | 
| 571 | 
            -
              border-radius: 3px;
         | 
| 555 | 
            +
              width: 28px;
         | 
| 556 | 
            +
              height: 28px;
         | 
| 557 | 
            +
              margin: -14px 0 0 -14px;
         | 
| 558 | 
            +
              border-radius: 28px;
         | 
| 572 559 | 
             
              border: 3px solid #80002d;
         | 
| 573 560 | 
             
              z-index: 5;
         | 
| 561 | 
            +
              opacity: 0;
         | 
| 574 562 | 
             
            }
         | 
| 575 563 |  | 
| 576 | 
            -
            .beacon .ring | 
| 564 | 
            +
            .beacon.pulse .ring {
         | 
| 577 565 | 
             
              -webkit-animation: beacon-ring-pulse 1s;
         | 
| 578 566 | 
             
              -moz-animation: beacon-ring-pulse 1s;
         | 
| 579 567 | 
             
              animation: beacon-ring-pulse 1s;
         | 
| 580 | 
            -
              -webkit-animation-iteration-count: 1;
         | 
| 581 | 
            -
              -moz-animation-iteration-count: 1;
         | 
| 582 | 
            -
              animation-iteration-count: 1;
         | 
| 583 568 | 
             
            }
         | 
| 584 569 |  | 
| 585 570 | 
             
            @-webkit-keyframes beacon-ring-pulse {
         | 
| 586 571 | 
             
              0% {
         | 
| 587 572 | 
             
                  opacity: 1;
         | 
| 588 | 
            -
                  -webkit-transform: scale(0);
         | 
| 573 | 
            +
                  -webkit-transform: scale(0.3);
         | 
| 589 574 | 
             
              }
         | 
| 590 575 | 
             
              100% {
         | 
| 591 576 | 
             
                  opacity: 0;
         | 
| 592 | 
            -
                   | 
| 593 | 
            -
                  padding: 8px;
         | 
| 594 | 
            -
                  top: 0;
         | 
| 595 | 
            -
                  left: 4px;
         | 
| 596 | 
            -
                  -webkit-transform: scale(1.5);
         | 
| 577 | 
            +
                  -webkit-transform: scale(1);
         | 
| 597 578 | 
             
              }
         | 
| 598 579 | 
             
            }
         | 
| 599 580 |  | 
| 600 581 | 
             
            @-moz-keyframes beacon-ring-pulse {
         | 
| 601 582 | 
             
              0% {
         | 
| 602 583 | 
             
                  opacity: 1;
         | 
| 603 | 
            -
                  -moz-transform: scale(0);
         | 
| 584 | 
            +
                  -moz-transform: scale(0.3);
         | 
| 604 585 | 
             
              }
         | 
| 605 586 | 
             
              100% {
         | 
| 606 587 | 
             
                  opacity: 0;
         | 
| 607 | 
            -
                   | 
| 608 | 
            -
                  padding: 8px;
         | 
| 609 | 
            -
                  top: 2px;
         | 
| 610 | 
            -
                  left: 7px;
         | 
| 611 | 
            -
                  -moz-transform: scale(1.6);
         | 
| 588 | 
            +
                  -moz-transform: scale(1);
         | 
| 612 589 | 
             
              }
         | 
| 613 590 | 
             
            }
         | 
| 614 591 |  | 
| 615 592 | 
             
            @keyframes beacon-ring-pulse {
         | 
| 616 593 | 
             
              0% {
         | 
| 617 594 | 
             
                  opacity: 1;
         | 
| 618 | 
            -
                  transform: scale(0);
         | 
| 595 | 
            +
                  transform: scale(0.3);
         | 
| 619 596 | 
             
              }
         | 
| 620 597 | 
             
              100% {
         | 
| 621 598 | 
             
                  opacity: 0;
         | 
| 622 | 
            -
                   | 
| 623 | 
            -
                  padding: 8px;
         | 
| 624 | 
            -
                  top: 0;
         | 
| 625 | 
            -
                  left: 5px;
         | 
| 626 | 
            -
                  transform: scale(1.5);
         | 
| 599 | 
            +
                  transform: scale(1);
         | 
| 627 600 | 
             
              }
         | 
| 628 601 | 
             
            }
         | 
| 629 602 |  | 
| @@ -759,19 +732,23 @@ div.interval-slider input { | |
| 759 732 |  | 
| 760 733 | 
             
            @media (min-width: 992px) {
         | 
| 761 734 | 
             
              .redis-url {
         | 
| 762 | 
            -
                max-width:  | 
| 735 | 
            +
                max-width: 390px;
         | 
| 763 736 | 
             
              }
         | 
| 764 737 |  | 
| 765 738 | 
             
              .redis-namespace {
         | 
| 766 | 
            -
                max-width:  | 
| 739 | 
            +
                max-width: 300px;
         | 
| 767 740 | 
             
              }
         | 
| 768 741 | 
             
            }
         | 
| 769 742 | 
             
            @media (min-width: 1200px) {
         | 
| 770 743 | 
             
              .redis-url {
         | 
| 771 | 
            -
                max-width:  | 
| 744 | 
            +
                max-width: 480px;
         | 
| 772 745 | 
             
              }
         | 
| 773 746 |  | 
| 774 747 | 
             
              .redis-namespace {
         | 
| 775 748 | 
             
                max-width: 350px;
         | 
| 776 749 | 
             
              }
         | 
| 777 750 | 
             
            }
         | 
| 751 | 
            +
             | 
| 752 | 
            +
            .redis-url {
         | 
| 753 | 
            +
              text-overflow: ellipsis;
         | 
| 754 | 
            +
            }
         | 
    
        data/web/locales/de.yml
    CHANGED
    
    
    
        data/web/locales/en.yml
    CHANGED