rapidity 0.0.7.369741 → 0.0.8.373806

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b9b41e5968e93c6bcb0d1a323f73890ea6f8ada6e47ff143a7c1fd631083e318
4
- data.tar.gz: d6ec9a04b1c674362757670101dd82fa752c219ade4717a0f08d89cb97f811a2
3
+ metadata.gz: ed5172220150b7969f1df9030b0c721529017407dbc829f3421634fa91bcd2c0
4
+ data.tar.gz: 768ac1fff03adf7c186011bde86d25ec07f7f032b81794c1fe56f8c778304120
5
5
  SHA512:
6
- metadata.gz: 52c1cb448e7769412f83aa7636a1339d28b04288a3af798b3563ed8d1b2f0904077deb211b556b2660d32bda3f24971424df8ccf812f12f1032bb6d4e705234f
7
- data.tar.gz: e8feb958fae4dbf853d669d75f1caa503aab0b2fb23a9df490c3deceea3b7865f17bdb44f89a7918a76f846018f03a76a8c44e0ff8a2d997e455beba4f4b352f
6
+ metadata.gz: 11fdd966c10b8e6202255e1c1f992239066d6593d6b0eab2d81b4d7a1179688272cb1e661a6318e1f4291c410d40b93d56bc270042cdc12ece1604ea7fe1dc57
7
+ data.tar.gz: aef378f5b068cbcef69b5188314b253908a61d1cf1056d1e036609ad3b510b69aab0cb8f9bd450dfed706cd122eaa1725164f1c7a3651001537e363a4e6eb1d0
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- rapidity (0.0.7.369741)
4
+ rapidity (0.0.8.373806)
5
5
  activesupport
6
6
  connection_pool
7
7
  ostruct
@@ -8,12 +8,15 @@ module Rapidity
8
8
  BASE_SCRIPTS = [:list, :info, :reset, :delete]
9
9
  DEFAULT_KEY_TTL = 6000
10
10
 
11
+ MX = Monitor.new
12
+
11
13
  def initialize(pool, ttl: DEFAULT_KEY_TTL.to_i, logger: nil)
12
14
  @pool = pool
13
15
  @ttl = ttl
14
16
  @logger = logger || Logger.new(STDOUT)
15
17
  @logger.level = Logger::DEBUG
16
18
  # load_redis_scripts
19
+ restore_lua_hashes
17
20
  end
18
21
 
19
22
  # Returns a list of limits matching the pattern
@@ -154,15 +157,45 @@ module Rapidity
154
157
  #
155
158
  # @return [void]
156
159
  def load_redis_scripts
157
- @pool.with do |conn|
158
- (BASE_SCRIPTS + self.class::LUA_SCRIPTS).each do |script|
159
- instance_variable_set("@lua_#{script}".to_sym,
160
- conn.with {|r| r.script(:load, File.read(File.join(__dir__, 'lua_scripts', "#{script.to_s}.lua"))) }
161
- )
160
+ cls = self.class
161
+ MX.synchronize do
162
+ @pool.with do |conn|
163
+ list_lua_scripts.each do |script|
164
+ cls.instance_variable_set(lua_script_var(script),
165
+ conn.with {|r| r.script(:load, File.read(File.join(__dir__, 'lua_scripts', "#{script.to_s}.lua"))) }
166
+ )
167
+ end
162
168
  end
163
169
  end
170
+ restore_lua_hashes
171
+ end
172
+
173
+ # Restore instance script hashes from class cache
174
+ def restore_lua_hashes
175
+ cls = self.class
176
+ list_lua_scripts.each do |script|
177
+ instance_variable_set(lua_script_var(script), cls.instance_variable_get(lua_script_var(script)))
178
+ end
164
179
  end
165
180
 
181
+
182
+ # это для тестов чтобы проверить перезугрузку сриптов
183
+ def reset_lua_scripts
184
+ cls = self.class
185
+ list_lua_scripts.each do |script|
186
+ instance_variable_set(lua_script_var(script), nil)
187
+ end
188
+ end
189
+
190
+ def list_lua_scripts
191
+ (BASE_SCRIPTS + self.class::LUA_SCRIPTS)
192
+ end
193
+
194
+ def lua_script_var(script)
195
+ "@lua_#{script}".to_sym
196
+ end
197
+
198
+
166
199
  end
167
200
  end
168
201
  end
@@ -169,8 +169,8 @@ local function process_all_limits(limit_keys, requested, current_time)
169
169
  limit:save()
170
170
 
171
171
  -- Продлеваем жизнь ключу, чтобы он не удалился, если к нему активно обращаются.
172
- -- "GT" обновляет TTL только если новый TTL больше текущего.
173
- redis.call("EXPIRE", limit.key, key_ttl, "GT")
172
+ -- раньше был GT, но он только с версии 7 (GT - только если новый TTL больше текущего остатка)
173
+ redis.call("EXPIRE", limit.key, key_ttl)
174
174
  end
175
175
 
176
176
  return { "result", "true", "keys", limit_keys }
@@ -134,8 +134,9 @@ local function process_all_queues(limit_keys, req_tokens, ttl)
134
134
  limit:acquire(bottleneck_tokens)
135
135
  limit:save()
136
136
 
137
- -- Продлеваем жизнь ключу (GT - только если новый TTL больше текущего остатка)
138
- redis.call("EXPIRE", limit.key, ttl, "GT")
137
+ -- Продлеваем жизнь ключу
138
+ -- раньше был GT, но он только с версии 7 (GT - только если новый TTL больше текущего остатка)
139
+ redis.call("EXPIRE", limit.key, ttl)
139
140
  end
140
141
 
141
142
  -- Возвращаем успешный результат: сколько реально удалось захватить (tokens)
@@ -17,7 +17,7 @@
17
17
  -- 4. Поиск "узкого горлышка" (Bottleneck): Поскольку для успешной операции (в acquire.lua) нужны
18
18
  -- токены из всех переданных лимитов одновременно, общим временем ожидания будет являться
19
19
  -- максимальное время ожидания среди всех проверенных корзин (math.max(unpack(wait_times))).
20
- -- 5. Поддержка TTL: В процессе проверки скрипт продлевает время жизни ключей (EXPIRE ... GT),
20
+ -- 5. Поддержка TTL: В процессе проверки скрипт продлевает время жизни ключей (EXPIRE ...),
21
21
  -- чтобы корзины не удалялись из Redis, пока за ними наблюдают ожидающие
22
22
  -- процессы.
23
23
  -- Обратите внимание: скрипт не изменяет количество токенов (не списывает их), а лишь "смотрит" на состояние.
@@ -132,7 +132,8 @@ local function process_all_limits(limit_keys, needed, time_now)
132
132
  limit:update(time_now)
133
133
 
134
134
  -- Продлеваем жизнь ключу, так как идет активная проверка лимита
135
- redis.call("EXPIRE", limit.key, key_ttl, "GT")
135
+ -- раньше был GT, но он только с версии 7 (GT - только если новый TTL больше текущего остатка)
136
+ redis.call("EXPIRE", limit.key, key_ttl)
136
137
 
137
138
  -- Сохраняем время ожидания для текущего лимита
138
139
  table.insert(wait_times, limit:available_in(needed))
@@ -36,9 +36,10 @@ local function check_queue()
36
36
 
37
37
  local semaphore = tonumber(semaphore_str) or 0
38
38
 
39
- -- Продлеваем жизнь ключу (GT - только если новый TTL больше текущего остатка),
39
+ -- Продлеваем жизнь ключу
40
+ -- раньше был GT, но он только с версии 7 (GT - только если новый TTL больше текущего остатка)
40
41
  -- так как идет активная проверка лимита.
41
- redis.call("EXPIRE", limit_key, key_ttl, "GT")
42
+ redis.call("EXPIRE", limit_key, key_ttl)
42
43
 
43
44
  -- Возвращаем успешный результат и текущее доступное количество мест
44
45
  return {
@@ -6,7 +6,7 @@
6
6
  -- Описание логики работы:
7
7
  -- 1. Скрипт принимает ключ лимита и время его жизни (TTL).
8
8
  -- 2. Если ключ существует, возвращает все его поля (HGETALL).
9
- -- 3. При успешном чтении продлевает время жизни ключа (EXPIRE ... GT),
9
+ -- 3. При успешном чтении продлевает время жизни ключа (EXPIRE ...),
10
10
  -- чтобы предотвратить удаление активно используемых данных.
11
11
  -------------------------------------------------------------------------------
12
12
 
@@ -28,8 +28,9 @@ local function info()
28
28
  return {"result", "false", "error", "key_not_found"}
29
29
  end
30
30
 
31
- -- Продлеваем жизнь ключу (GT - только если новый TTL больше текущего остатка)
32
- redis.call("EXPIRE", limit_key, key_ttl, "GT")
31
+ -- Продлеваем жизнь ключу
32
+ -- раньше был GT, но он только с версии 7 (GT - только если новый TTL больше текущего остатка)
33
+ redis.call("EXPIRE", limit_key, key_ttl)
33
34
 
34
35
  return {"result", "true", "info", {limit_key, data}}
35
36
  end
@@ -14,7 +14,7 @@
14
14
  -- Это критически важно: если мы просто обновляем настройки лимита "на лету",
15
15
  -- мы не должны сбрасывать текущие ограничения и уже списанные пользователями токены.
16
16
  -- 2. Расчет скорости (Rate): Скорость пополнения (rate) предрасчитывается прямо в Lua (max_tokens / interval) и кэшируется в Redis. Это избавляет от необходимости каждый раз высчитывать дроби при проверке (в скрипте acquire.lua).
17
- -- 3. Управление временем жизни (TTL): Назначает ключу время жизни. Если ключ уже существовал, TTL продлевается только в том случае, если новое значение больше текущего (EXPIRE ... GT).
17
+ -- 3. Управление временем жизни (TTL): Назначает ключу время жизни. Если ключ уже существовал, TTL продлевается (EXPIRE ...).
18
18
  -- 4. Возврат данных: Скрипт возвращает имя ключа и все его сохраненные поля (HGETALL). В Ruby эта структура затем используется для сборки (гидратации) объекта Limit.
19
19
  -------------------------------------------------------------------------------
20
20
 
@@ -55,8 +55,9 @@ local function init()
55
55
  "rate", rate
56
56
  )
57
57
 
58
- -- Продлеваем жизнь ключу (GT - только если новый TTL больше текущего остатка)
59
- redis.call("EXPIRE", limit_key, key_ttl, "GT")
58
+ -- Продлеваем жизнь ключу
59
+ -- раньше был GT, но он только с версии 7 (GT - только если новый TTL больше текущего остатка)
60
+ redis.call("EXPIRE", limit_key, key_ttl)
60
61
  else
61
62
  -- Создание нового лимита.
62
63
  -- Корзина инициализируется как полностью заполненная (tokens = max_tokens).
@@ -120,8 +120,9 @@ local function process_all_queues(limit_keys, released_tokens, ttl)
120
120
  end
121
121
  end
122
122
 
123
- -- Продлеваем жизнь ключу (GT - только если новый TTL больше текущего остатка)
124
- redis.call("EXPIRE", limit.key, ttl, "GT")
123
+ -- Продлеваем жизнь ключу
124
+ -- раньше был GT, но он только с версии 7 (GT - только если новый TTL больше текущего остатка)
125
+ redis.call("EXPIRE", limit.key, ttl)
125
126
  end
126
127
 
127
128
  -- Если ни у одного лимита очередь не включена, вернем 0
@@ -51,8 +51,9 @@ local function reset()
51
51
  "last_used", current_time
52
52
  )
53
53
 
54
- -- Продлеваем жизнь ключу (GT - только если новый TTL больше текущего остатка)
55
- redis.call("EXPIRE", limit_key, key_ttl, "GT")
54
+ -- Продлеваем жизнь ключу
55
+ -- раньше был GT, но он только с версии 7 (GT - только если новый TTL больше текущего остатка)
56
+ redis.call("EXPIRE", limit_key, key_ttl)
56
57
 
57
58
  -- Возвращаем успешный результат и обновленные данные
58
59
  return {"result", "true", "info", {limit_key, redis.call("HGETALL", limit_key)}}
@@ -1,6 +1,6 @@
1
1
  module Rapidity
2
2
 
3
- VERSION = '0.0.7'.freeze
3
+ VERSION = '0.0.8'.freeze
4
4
 
5
5
  end
6
6
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rapidity
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.7.369741
4
+ version: 0.0.8.373806
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yurusov Vlad
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2026-04-22 00:00:00.000000000 Z
12
+ date: 2026-05-07 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport