wurk 1.7.6 → 1.8.1
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.
- checksums.yaml +4 -4
- data/README.md +26 -5
- data/app/controllers/concerns/wurk/sse_streaming.rb +2 -1
- data/app/controllers/concerns/wurk/stream_concurrency_guard.rb +33 -9
- data/app/controllers/wurk/api/pagination.rb +25 -7
- data/app/controllers/wurk/api_controller.rb +49 -25
- data/app/controllers/wurk/extensions_controller.rb +8 -2
- data/app/controllers/wurk/profiles_controller.rb +45 -9
- data/config/routes.rb +31 -10
- data/lib/generators/wurk/install/templates/wurk.rb +1 -1
- data/lib/sidekiq/capsule.rb +4 -0
- data/lib/sidekiq/component.rb +4 -0
- data/lib/sidekiq/config.rb +4 -0
- data/lib/sidekiq/deploy.rb +4 -0
- data/lib/sidekiq/embedded.rb +4 -0
- data/lib/sidekiq/fetch.rb +4 -0
- data/lib/sidekiq/iterable_job.rb +4 -0
- data/lib/sidekiq/job/interrupt_handler.rb +4 -0
- data/lib/sidekiq/job/iterable/active_record_enumerator.rb +4 -0
- data/lib/sidekiq/job/iterable/csv_enumerator.rb +4 -0
- data/lib/sidekiq/job/iterable.rb +4 -0
- data/lib/sidekiq/job_logger.rb +4 -0
- data/lib/sidekiq/job_util.rb +4 -0
- data/lib/sidekiq/loader.rb +4 -0
- data/lib/sidekiq/logger.rb +4 -0
- data/lib/sidekiq/metrics/query.rb +4 -0
- data/lib/sidekiq/middleware/current_attributes.rb +7 -0
- data/lib/sidekiq/middleware/i18n.rb +6 -0
- data/lib/sidekiq/middleware/modules.rb +4 -0
- data/lib/sidekiq/pro/web.rb +5 -0
- data/lib/sidekiq/profiler.rb +4 -0
- data/lib/sidekiq/redis_client_adapter.rb +4 -0
- data/lib/sidekiq/test_api.rb +5 -0
- data/lib/sidekiq/testing/inline.rb +8 -0
- data/lib/sidekiq/transaction_aware_client.rb +4 -0
- data/lib/sidekiq/worker_compatibility_alias.rb +4 -0
- data/lib/sidekiq-ent/periodic/testing.rb +5 -0
- data/lib/sidekiq-ent/web.rb +5 -0
- data/lib/sidekiq-ent.rb +7 -0
- data/lib/sidekiq-pro.rb +7 -0
- data/lib/wurk/api/fast.rb +8 -33
- data/lib/wurk/api/idempotency.rb +28 -5
- data/lib/wurk/api/swarm.rb +1 -1
- data/lib/wurk/batch/callbacks.rb +143 -92
- data/lib/wurk/batch/death_handler.rb +19 -8
- data/lib/wurk/batch/server_middleware.rb +37 -24
- data/lib/wurk/batch/status.rb +49 -15
- data/lib/wurk/batch.rb +164 -65
- data/lib/wurk/capsule.rb +0 -2
- data/lib/wurk/client/buffered.rb +227 -106
- data/lib/wurk/client.rb +33 -13
- data/lib/wurk/compat.rb +13 -0
- data/lib/wurk/configuration.rb +155 -24
- data/lib/wurk/cpu_count.rb +97 -0
- data/lib/wurk/cron.rb +97 -34
- data/lib/wurk/dead_set.rb +6 -7
- data/lib/wurk/encryption.rb +46 -13
- data/lib/wurk/fetcher/many_queues.rb +65 -0
- data/lib/wurk/fetcher/orphan_grace.rb +67 -0
- data/lib/wurk/fetcher/private_list_key.rb +76 -0
- data/lib/wurk/fetcher/reaper.rb +55 -74
- data/lib/wurk/fetcher/reliable.rb +23 -17
- data/lib/wurk/fetcher/unit_of_work.rb +19 -1
- data/lib/wurk/fetcher/unparseable_keys.rb +56 -0
- data/lib/wurk/flow/completion.rb +28 -3
- data/lib/wurk/flow/creation.rb +24 -4
- data/lib/wurk/flow.rb +24 -2
- data/lib/wurk/health.rb +182 -40
- data/lib/wurk/heartbeat.rb +37 -14
- data/lib/wurk/history.rb +7 -1
- data/lib/wurk/import/sidekiq_cron.rb +248 -0
- data/lib/wurk/job/options.rb +22 -3
- data/lib/wurk/job_logger.rb +13 -3
- data/lib/wurk/job_record.rb +68 -19
- data/lib/wurk/job_retry.rb +12 -6
- data/lib/wurk/job_set.rb +99 -51
- data/lib/wurk/job_util.rb +27 -8
- data/lib/wurk/launcher.rb +84 -40
- data/lib/wurk/leader.rb +53 -28
- data/lib/wurk/limiter/base.rb +11 -30
- data/lib/wurk/limiter/bucket.rb +14 -5
- data/lib/wurk/limiter/server_middleware.rb +2 -1
- data/lib/wurk/limiter.rb +1 -1
- data/lib/wurk/loader.rb +48 -0
- data/lib/wurk/lua/batch_ack_complete.lua +28 -0
- data/lib/wurk/lua/batch_ack_failed.lua +18 -0
- data/lib/wurk/lua/batch_ack_success.lua +35 -0
- data/lib/wurk/lua/batch_append_callback.lua +66 -0
- data/lib/wurk/lua/batch_delete.lua +31 -0
- data/lib/wurk/lua/batch_hold.lua +17 -0
- data/lib/wurk/lua/batch_invalidate.lua +14 -0
- data/lib/wurk/lua/batch_kid_done.lua +14 -0
- data/lib/wurk/lua/batch_push.lua +47 -0
- data/lib/wurk/lua/batch_remove_jobs.lua +29 -0
- data/lib/wurk/lua/batch_schedule.lua +27 -0
- data/lib/wurk/lua/fetch_first.lua +27 -0
- data/lib/wurk/lua/flow_abandon.lua +16 -21
- data/lib/wurk/lua/flow_advance.lua +41 -26
- data/lib/wurk/lua/flow_create.lua +24 -9
- data/lib/wurk/lua/flow_fail.lua +3 -3
- data/lib/wurk/lua/leader_campaign.lua +19 -0
- data/lib/wurk/lua/limiter_bucket_acquire.lua +3 -2
- data/lib/wurk/lua/limiter_list_sweep.lua +8 -9
- data/lib/wurk/lua/loader.rb +36 -23
- data/lib/wurk/lua/throttle_slot.lua +13 -26
- data/lib/wurk/lua.rb +31 -244
- data/lib/wurk/manager.rb +25 -18
- data/lib/wurk/metrics/accumulator.rb +31 -10
- data/lib/wurk/metrics/dashboard_series.rb +163 -0
- data/lib/wurk/metrics/histogram.rb +46 -0
- data/lib/wurk/metrics/history.rb +49 -57
- data/lib/wurk/metrics/prometheus.rb +232 -0
- data/lib/wurk/metrics/query.rb +127 -155
- data/lib/wurk/metrics/rollup.rb +2 -2
- data/lib/wurk/metrics/statsd.rb +1 -1
- data/lib/wurk/middleware/interrupt_handler.rb +6 -2
- data/lib/wurk/middleware/poison_pill.rb +5 -4
- data/lib/wurk/middleware/timeout.rb +8 -8
- data/lib/wurk/process_set.rb +5 -5
- data/lib/wurk/processor.rb +69 -31
- data/lib/wurk/profile_set.rb +19 -24
- data/lib/wurk/profiler.rb +48 -50
- data/lib/wurk/queue.rb +36 -19
- data/lib/wurk/rails_boot.rb +43 -1
- data/lib/wurk/railtie.rb +2 -0
- data/lib/wurk/rake_tasks.rb +18 -0
- data/lib/wurk/redact.rb +39 -0
- data/lib/wurk/redis_connection.rb +6 -3
- data/lib/wurk/redis_options.rb +21 -4
- data/lib/wurk/redis_pool.rb +119 -21
- data/lib/wurk/scheduled.rb +44 -11
- data/lib/wurk/sentry/error_handler.rb +53 -7
- data/lib/wurk/sentry/middleware.rb +7 -8
- data/lib/wurk/shutdown_gate.rb +24 -1
- data/lib/wurk/sorted_entry.rb +16 -5
- data/lib/wurk/stats.rb +9 -4
- data/lib/wurk/status.rb +2 -2
- data/lib/wurk/swarm/child_boot.rb +48 -38
- data/lib/wurk/swarm/liveness.rb +153 -0
- data/lib/wurk/swarm/restart.rb +24 -3
- data/lib/wurk/swarm.rb +115 -24
- data/lib/wurk/telemetry/server_middleware.rb +2 -5
- data/lib/wurk/testing.rb +15 -5
- data/lib/wurk/throttle.rb +16 -1
- data/lib/wurk/topology.rb +1 -5
- data/lib/wurk/unique.rb +1 -1
- data/lib/wurk/version.rb +1 -1
- data/lib/wurk/watchdog.rb +2 -2
- data/lib/wurk/web/config.rb +56 -20
- data/lib/wurk/web/enterprise.rb +21 -18
- data/lib/wurk/web/extension.rb +98 -22
- data/lib/wurk/web/rack_app.rb +12 -11
- data/lib/wurk/web/search.rb +18 -8
- data/lib/wurk/worker/setter.rb +17 -14
- data/lib/wurk/worker.rb +6 -67
- data/lib/wurk.rb +2 -3
- data/vendor/assets/dashboard/assets/ArgsValue-_MYkd_vA.js +1 -0
- data/vendor/assets/dashboard/assets/BatchDetail-DPmg-hle.js +1 -0
- data/vendor/assets/dashboard/assets/Batches-NTgqSlvD.js +1 -0
- data/vendor/assets/dashboard/assets/Busy-2rxcLJMq.js +1 -0
- data/vendor/assets/dashboard/assets/Cron-BFpJgKYb.js +1 -0
- data/vendor/assets/dashboard/assets/Dashboard-C8VOE2S7.js +1 -0
- data/vendor/assets/dashboard/assets/Dead-Dse2YEbZ.js +1 -0
- data/vendor/assets/dashboard/assets/Extension-BIc2c1zG.js +1 -0
- data/vendor/assets/dashboard/assets/FilterBox-BfZm8ZzH.js +1 -0
- data/vendor/assets/dashboard/assets/FlowDetail-BWddOtgf.js +1 -0
- data/vendor/assets/dashboard/assets/FlowState-6lGsojxE.js +1 -0
- data/vendor/assets/dashboard/assets/Flows-BgKTlYwI.js +1 -0
- data/vendor/assets/dashboard/assets/JobDetailModal-BrjmO98c.js +2 -0
- data/vendor/assets/dashboard/assets/Limiters-DeUkfbcg.js +1 -0
- data/vendor/assets/dashboard/assets/Metrics-DzmAgBFG.js +1 -0
- data/vendor/assets/dashboard/assets/NotFound-CQLLXIfa.js +1 -0
- data/vendor/assets/dashboard/assets/PageHeader-CeSaqysY.js +1 -0
- data/vendor/assets/dashboard/assets/Profiles-CI2i2tl8.js +1 -0
- data/vendor/assets/dashboard/assets/Queues-DUCQ_3St.js +1 -0
- data/vendor/assets/dashboard/assets/Retries-Dc2RFuTf.js +1 -0
- data/vendor/assets/dashboard/assets/Scheduled-B8zOKCLC.js +1 -0
- data/vendor/assets/dashboard/assets/Search-x0eS-V-U.js +1 -0
- data/vendor/assets/dashboard/assets/charts-VggSMFGc.js +1 -0
- data/vendor/assets/dashboard/assets/i18n-B6AbnmJn.js +1 -0
- data/vendor/assets/dashboard/assets/index-CTWV8VL4.js +141 -0
- data/vendor/assets/dashboard/assets/index-WpZjU076.css +1 -0
- data/vendor/assets/dashboard/assets/useResetPageOnEmpty-BsYWeStI.js +1 -0
- data/vendor/assets/dashboard/assets/useSort-BWWfpnZH.js +1 -0
- data/vendor/assets/dashboard/assets/utils-DnzJXljj.js +1 -0
- data/vendor/assets/dashboard/index.html +3 -3
- data/vendor/assets/dashboard/wurk-manifest.json +2 -2
- metadata +90 -34
- data/config/locales/en.yml +0 -15
- data/vendor/assets/dashboard/assets/ArgsValue-D-x_ifLY.js +0 -1
- data/vendor/assets/dashboard/assets/BatchDetail-C39NJuew.js +0 -1
- data/vendor/assets/dashboard/assets/Batches-CSwo7Asa.js +0 -1
- data/vendor/assets/dashboard/assets/Busy-BOFMu-sq.js +0 -1
- data/vendor/assets/dashboard/assets/Cron-Dy8RQzDI.js +0 -1
- data/vendor/assets/dashboard/assets/Dashboard-BuTHI-O1.js +0 -1
- data/vendor/assets/dashboard/assets/Dead-B9KRvQ0N.js +0 -1
- data/vendor/assets/dashboard/assets/Extension-BnBVHfux.js +0 -1
- data/vendor/assets/dashboard/assets/FilterBox-DC24zite.js +0 -1
- data/vendor/assets/dashboard/assets/FlowDetail-DyLuzUvt.js +0 -1
- data/vendor/assets/dashboard/assets/FlowState-DAPKUahm.js +0 -1
- data/vendor/assets/dashboard/assets/Flows-Fr3rjZM_.js +0 -1
- data/vendor/assets/dashboard/assets/JobDetailModal-N6kiJXq3.js +0 -2
- data/vendor/assets/dashboard/assets/Limiters-kbFA7uS1.js +0 -1
- data/vendor/assets/dashboard/assets/Metrics-Dj2uoZ3o.js +0 -1
- data/vendor/assets/dashboard/assets/PageHeader-B_F94azl.js +0 -1
- data/vendor/assets/dashboard/assets/Profiles-D_DjEezN.js +0 -1
- data/vendor/assets/dashboard/assets/Queues-CO4V9hAz.js +0 -1
- data/vendor/assets/dashboard/assets/Retries-DCWnzeLa.js +0 -1
- data/vendor/assets/dashboard/assets/Scheduled-BebDUjLU.js +0 -1
- data/vendor/assets/dashboard/assets/Search-Cvr5fy4Y.js +0 -1
- data/vendor/assets/dashboard/assets/Skeleton-Bu3Ke6rV.js +0 -1
- data/vendor/assets/dashboard/assets/charts-BCs9bQKz.js +0 -1
- data/vendor/assets/dashboard/assets/index-BIwyOC5Q.js +0 -141
- data/vendor/assets/dashboard/assets/index-DBQN6Jk8.css +0 -1
- data/vendor/assets/dashboard/assets/useResetPageOnEmpty-Bzh-BJyL.js +0 -1
- data/vendor/assets/dashboard/assets/useSort-COA3fVJ5.js +0 -1
- data/vendor/assets/dashboard/assets/utils-BIrvZ1hi.js +0 -1
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Drop-in require path (see lib/sidekiq.rb): defines Sidekiq::CurrentAttributes
|
|
4
|
+
# (`persist`, `Save`, `Load`). Nothing is registered until `persist` is called,
|
|
5
|
+
# as upstream.
|
|
6
|
+
require 'wurk'
|
|
7
|
+
require 'wurk/middleware/current_attributes'
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Drop-in require path, deprecated upstream exactly like sidekiq/testing.
|
|
4
|
+
require 'wurk'
|
|
5
|
+
|
|
6
|
+
Wurk.testing!(:inline)
|
|
7
|
+
warn('⛔️ `require "sidekiq/testing/inline"` is deprecated and will be removed in Sidekiq 9.0. ' \
|
|
8
|
+
'Use `Sidekiq.testing!(:inline)` instead.')
|
data/lib/sidekiq-ent.rb
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# rubocop:disable Naming/FileName -- the gem's own require name, hyphen included
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
# Drop-in require path (sidekiq-ent.md, top): Wurk ships every Enterprise
|
|
5
|
+
# feature in the one gem, so this only has to load it.
|
|
6
|
+
require 'wurk'
|
|
7
|
+
# rubocop:enable Naming/FileName
|
data/lib/sidekiq-pro.rb
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# rubocop:disable Naming/FileName -- the gem's own require name, hyphen included
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
# Drop-in require path (sidekiq-pro.md, top): Wurk ships every Pro feature in
|
|
5
|
+
# the one gem, so this only has to load it.
|
|
6
|
+
require 'wurk'
|
|
7
|
+
# rubocop:enable Naming/FileName
|
data/lib/wurk/api/fast.rb
CHANGED
|
@@ -1,23 +1,22 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require_relative '../lua'
|
|
4
|
-
require_relative '../job_record'
|
|
5
4
|
|
|
6
5
|
module Wurk
|
|
7
6
|
module API
|
|
8
7
|
# Pro parity (§11): Lua-backed O(1)-round-trip replacements for the
|
|
9
|
-
# ruby-side LRANGE
|
|
10
|
-
#
|
|
11
|
-
#
|
|
12
|
-
# with Pro consumer code that drops in on a one-line require swap.
|
|
8
|
+
# ruby-side LRANGE loops in Queue. Mixed into the existing data API class
|
|
9
|
+
# so the surface is `Sidekiq::Queue#delete_job(jid)` — wire-compat with Pro
|
|
10
|
+
# consumer code that drops in on a one-line require swap.
|
|
13
11
|
#
|
|
14
12
|
# We don't reimplement `Queue#size` (already LLEN, unchanged per spec).
|
|
15
13
|
module Fast
|
|
16
14
|
# Extension to Wurk::Queue. Pure server-side delete by jid / class — no
|
|
17
|
-
# network round-trips per match.
|
|
15
|
+
# network round-trips per match.
|
|
18
16
|
module QueueExt
|
|
19
|
-
# @return [
|
|
20
|
-
# the
|
|
17
|
+
# @return [String, nil] the deleted job's JSON, or nil when no job in
|
|
18
|
+
# the queue has that jid — Pro's contract, so `if q.delete_job(jid)`
|
|
19
|
+
# branches on whether anything was removed.
|
|
21
20
|
def delete_job(jid)
|
|
22
21
|
raise ArgumentError, 'jid required' if jid.nil? || jid.to_s.empty?
|
|
23
22
|
|
|
@@ -28,7 +27,7 @@ module Wurk
|
|
|
28
27
|
keys: [Keys.queue(name)],
|
|
29
28
|
argv: [jid.to_s]
|
|
30
29
|
)
|
|
31
|
-
end
|
|
30
|
+
end
|
|
32
31
|
end
|
|
33
32
|
|
|
34
33
|
# @param klass [Class, String, Symbol]
|
|
@@ -47,32 +46,8 @@ module Wurk
|
|
|
47
46
|
end.to_i
|
|
48
47
|
end
|
|
49
48
|
end
|
|
50
|
-
|
|
51
|
-
# Extension to Wurk::SortedSet / JobSet. The base `scan(match, count)`
|
|
52
|
-
# already yields `(value, score)` pairs via ZSCAN — Pro promotes the
|
|
53
|
-
# surface to yield `JobRecord` directly so callers can `entry.delete`
|
|
54
|
-
# / `entry.retry` without re-parsing JSON.
|
|
55
|
-
#
|
|
56
|
-
# The new behavior is enabled by *block arity*: a 1-arg block (or
|
|
57
|
-
# block.lambda? + a 1-param signature) receives `JobRecord`; legacy
|
|
58
|
-
# 2-arg blocks (`|value, score|`) keep the raw shape. This preserves
|
|
59
|
-
# the existing two-arg contract used by JobSet#find_job internally.
|
|
60
|
-
module SortedSetExt
|
|
61
|
-
def scan(match, count = 100, &block)
|
|
62
|
-
return enum_for(:scan, match, count) unless block
|
|
63
|
-
|
|
64
|
-
if block.arity == 1
|
|
65
|
-
super do |value, score|
|
|
66
|
-
block.call(Wurk::SortedEntry.new(self, score, value))
|
|
67
|
-
end
|
|
68
|
-
else
|
|
69
|
-
super
|
|
70
|
-
end
|
|
71
|
-
end
|
|
72
|
-
end
|
|
73
49
|
end
|
|
74
50
|
end
|
|
75
51
|
end
|
|
76
52
|
|
|
77
53
|
Wurk::Queue.include(Wurk::API::Fast::QueueExt)
|
|
78
|
-
Wurk::SortedSet.prepend(Wurk::API::Fast::SortedSetExt)
|
data/lib/wurk/api/idempotency.rb
CHANGED
|
@@ -95,17 +95,40 @@ module Wurk
|
|
|
95
95
|
reserved ? nil : existing.to_s
|
|
96
96
|
end
|
|
97
97
|
|
|
98
|
+
# Errors that prove the write they interrupted never applied: refused
|
|
99
|
+
# while dialing, a starved checkout, or a reply in which Redis itself
|
|
100
|
+
# rejected the command.
|
|
101
|
+
PRE_APPLY_ERRORS = [
|
|
102
|
+
::RedisClient::CannotConnectError, ::RedisClient::FailoverError,
|
|
103
|
+
::RedisClient::CommandError, ::ConnectionPool::TimeoutError
|
|
104
|
+
].freeze
|
|
105
|
+
|
|
98
106
|
# Only a success is worth replaying. A rejected body is a request the
|
|
99
|
-
# client should be able to correct and send again under the same key,
|
|
100
|
-
#
|
|
101
|
-
#
|
|
107
|
+
# client should be able to correct and send again under the same key, so
|
|
108
|
+
# it releases. A raise releases only when nothing can have reached Redis
|
|
109
|
+
# — before any write went out, or on an error that proves the one in
|
|
110
|
+
# flight never applied. Anything else (a lost reply, a bulk request that
|
|
111
|
+
# died after an earlier slice landed) is an outcome nobody knows: the key
|
|
112
|
+
# stays pending until its TTL, so the client's retry is told "in flight"
|
|
113
|
+
# instead of enqueueing a second copy.
|
|
102
114
|
def settle(slot, fingerprint)
|
|
115
|
+
Thread.current[::Wurk::Client::WRITE_STATE_KEY] = :clean
|
|
103
116
|
response = yield
|
|
104
117
|
response[0] < 300 ? record(slot, fingerprint, response) : release(slot)
|
|
105
118
|
response
|
|
106
|
-
rescue StandardError
|
|
107
|
-
release(slot)
|
|
119
|
+
rescue StandardError => e
|
|
120
|
+
release(slot) unless outcome_unknown?(e)
|
|
108
121
|
raise
|
|
122
|
+
ensure
|
|
123
|
+
Thread.current[::Wurk::Client::WRITE_STATE_KEY] = nil
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def outcome_unknown?(error)
|
|
127
|
+
case Thread.current[::Wurk::Client::WRITE_STATE_KEY]
|
|
128
|
+
when :applied then true
|
|
129
|
+
when :attempted then PRE_APPLY_ERRORS.none? { |klass| error.is_a?(klass) }
|
|
130
|
+
else false
|
|
131
|
+
end
|
|
109
132
|
end
|
|
110
133
|
|
|
111
134
|
# KEEPTTL so the window is the first request's, not this write's, and XX
|
data/lib/wurk/api/swarm.rb
CHANGED
|
@@ -134,7 +134,7 @@ module Wurk
|
|
|
134
134
|
def limiters(request)
|
|
135
135
|
query = Page.query!(request)
|
|
136
136
|
window = Page.window(query)
|
|
137
|
-
names = ::Wurk::Web::Enterprise::Limits.list(filter: filter!(query))
|
|
137
|
+
names = ::Wurk::Web::Enterprise::Limits.list(filter: filter!(query), sweep: !ReadOnly.enabled?(request))
|
|
138
138
|
rows = Page.slice(names, window) { |name| limiter_row(name) }
|
|
139
139
|
Response.json(200, total: names.size, page: window.page, count: window.count, limiters: rows)
|
|
140
140
|
end
|