redis-simplify 2.1.2__tar.gz → 2.1.4__tar.gz

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.
Files changed (34) hide show
  1. {redis_simplify-2.1.2/redis_simplify.egg-info → redis_simplify-2.1.4}/PKG-INFO +3 -2
  2. {redis_simplify-2.1.2 → redis_simplify-2.1.4}/README.md +2 -1
  3. {redis_simplify-2.1.2 → redis_simplify-2.1.4}/pyproject.toml +1 -1
  4. {redis_simplify-2.1.2 → redis_simplify-2.1.4}/redis_simplify/mixins/admin.py +5 -3
  5. {redis_simplify-2.1.2 → redis_simplify-2.1.4}/redis_simplify/mixins/batch.py +9 -0
  6. {redis_simplify-2.1.2 → redis_simplify-2.1.4}/redis_simplify/mixins/connection.py +1 -1
  7. {redis_simplify-2.1.2 → redis_simplify-2.1.4}/redis_simplify/mixins/lock.py +13 -4
  8. {redis_simplify-2.1.2 → redis_simplify-2.1.4}/redis_simplify/mixins/pubsub.py +17 -12
  9. {redis_simplify-2.1.2 → redis_simplify-2.1.4/redis_simplify.egg-info}/PKG-INFO +3 -2
  10. {redis_simplify-2.1.2 → redis_simplify-2.1.4}/tests/test_logging.py +2 -2
  11. {redis_simplify-2.1.2 → redis_simplify-2.1.4}/LICENSE +0 -0
  12. {redis_simplify-2.1.2 → redis_simplify-2.1.4}/redis_simplify/__init__.py +0 -0
  13. {redis_simplify-2.1.2 → redis_simplify-2.1.4}/redis_simplify/client.py +0 -0
  14. {redis_simplify-2.1.2 → redis_simplify-2.1.4}/redis_simplify/mixins/__init__.py +0 -0
  15. {redis_simplify-2.1.2 → redis_simplify-2.1.4}/redis_simplify/mixins/cache.py +0 -0
  16. {redis_simplify-2.1.2 → redis_simplify-2.1.4}/redis_simplify/mixins/decorator_metrics.py +0 -0
  17. {redis_simplify-2.1.2 → redis_simplify-2.1.4}/redis_simplify/mixins/decorators.py +0 -0
  18. {redis_simplify-2.1.2 → redis_simplify-2.1.4}/redis_simplify/mixins/hash.py +0 -0
  19. {redis_simplify-2.1.2 → redis_simplify-2.1.4}/redis_simplify/mixins/health.py +0 -0
  20. {redis_simplify-2.1.2 → redis_simplify-2.1.4}/redis_simplify/mixins/json.py +0 -0
  21. {redis_simplify-2.1.2 → redis_simplify-2.1.4}/redis_simplify/mixins/list.py +0 -0
  22. {redis_simplify-2.1.2 → redis_simplify-2.1.4}/redis_simplify/mixins/metrics.py +0 -0
  23. {redis_simplify-2.1.2 → redis_simplify-2.1.4}/redis_simplify/mixins/pipeline.py +0 -0
  24. {redis_simplify-2.1.2 → redis_simplify-2.1.4}/redis_simplify/mixins/ratelimit.py +0 -0
  25. {redis_simplify-2.1.2 → redis_simplify-2.1.4}/redis_simplify/mixins/set.py +0 -0
  26. {redis_simplify-2.1.2 → redis_simplify-2.1.4}/redis_simplify/mixins/sorted_set.py +0 -0
  27. {redis_simplify-2.1.2 → redis_simplify-2.1.4}/redis_simplify/mixins/string.py +0 -0
  28. {redis_simplify-2.1.2 → redis_simplify-2.1.4}/redis_simplify/mixins/utils.py +0 -0
  29. {redis_simplify-2.1.2 → redis_simplify-2.1.4}/redis_simplify.egg-info/SOURCES.txt +0 -0
  30. {redis_simplify-2.1.2 → redis_simplify-2.1.4}/redis_simplify.egg-info/dependency_links.txt +0 -0
  31. {redis_simplify-2.1.2 → redis_simplify-2.1.4}/redis_simplify.egg-info/requires.txt +0 -0
  32. {redis_simplify-2.1.2 → redis_simplify-2.1.4}/redis_simplify.egg-info/top_level.txt +0 -0
  33. {redis_simplify-2.1.2 → redis_simplify-2.1.4}/setup.cfg +0 -0
  34. {redis_simplify-2.1.2 → redis_simplify-2.1.4}/tests/test_client.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: redis-simplify
3
- Version: 2.1.2
3
+ Version: 2.1.4
4
4
  Summary: Convenience wrapper for Redis - connection, JSON helpers, and automatic reconnection
5
5
  Author-email: Paulo Ricardo Tebet Lyrio <tebetpaulo91@yahoo.com>
6
6
  License: MIT
@@ -383,6 +383,7 @@ DEBUG:redis_simplify.client:Get test: hello world...
383
383
  | `rate_limit_check(key, max_requests, window_seconds)` | Check if action is allowed |
384
384
  | `rate_limit_remaining(key, max_requests, window_seconds)` | Get remaining requests |
385
385
  | `rate_limit_reset(key, window_seconds)` | Get seconds until reset |
386
+ | `run_with_rate_limit(operation, rate_key, max_requests, window_seconds, *args, **kwargs)` | Execute operation with automatic rate limit |
386
387
 
387
388
  ### Distributed Lock
388
389
  | Method | Description |
@@ -433,7 +434,7 @@ DEBUG:redis_simplify.client:Get test: hello world...
433
434
  | `ping()` | Verify connectivity |
434
435
  | `pipeline()` | Create a Redis pipeline |
435
436
  | `scan(cursor=0, match=None, count=None)` | Iterate keys using SCAN |
436
- | `flush_all()` | Remove all Redis databases |
437
+ | `flushall()` | Remove all Redis databases |
437
438
  | `close()` | Close the connection |
438
439
  | `set_log_level(level)` | Change log level at runtime|
439
440
 
@@ -351,6 +351,7 @@ DEBUG:redis_simplify.client:Get test: hello world...
351
351
  | `rate_limit_check(key, max_requests, window_seconds)` | Check if action is allowed |
352
352
  | `rate_limit_remaining(key, max_requests, window_seconds)` | Get remaining requests |
353
353
  | `rate_limit_reset(key, window_seconds)` | Get seconds until reset |
354
+ | `run_with_rate_limit(operation, rate_key, max_requests, window_seconds, *args, **kwargs)` | Execute operation with automatic rate limit |
354
355
 
355
356
  ### Distributed Lock
356
357
  | Method | Description |
@@ -401,7 +402,7 @@ DEBUG:redis_simplify.client:Get test: hello world...
401
402
  | `ping()` | Verify connectivity |
402
403
  | `pipeline()` | Create a Redis pipeline |
403
404
  | `scan(cursor=0, match=None, count=None)` | Iterate keys using SCAN |
404
- | `flush_all()` | Remove all Redis databases |
405
+ | `flushall()` | Remove all Redis databases |
405
406
  | `close()` | Close the connection |
406
407
  | `set_log_level(level)` | Change log level at runtime|
407
408
 
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "redis-simplify"
7
- version = "2.1.2"
7
+ version = "2.1.4"
8
8
  description = "Convenience wrapper for Redis - connection, JSON helpers, and automatic reconnection"
9
9
  readme = "README.md"
10
10
  authors = [
@@ -17,12 +17,14 @@ class AdminMixin:
17
17
  return 0, []
18
18
 
19
19
  @recorded()
20
- def flush_all(self):
20
+ def flushall(self):
21
21
  """Limpa tudo (CUIDADO: apenas para testes!)"""
22
22
  if not self._ensure_connection():
23
- return
23
+ return False
24
24
  try:
25
25
  self.client.flushall()
26
26
  logger.warning("Redis flushall executed!")
27
+ return True
27
28
  except Exception as e:
28
- logger.error(f"Error on flushall: {e}")
29
+ logger.error(f"Error on flushall: {e}")
30
+ return False
@@ -16,6 +16,9 @@ class BatchMixin:
16
16
 
17
17
  try:
18
18
  pipe = self.pipeline()
19
+ if pipe is None:
20
+ logger.error("Failed to create pipeline")
21
+ return [None] * len(keys)
19
22
  for key in keys:
20
23
  pipe.get(key)
21
24
  return pipe.execute()
@@ -33,6 +36,9 @@ class BatchMixin:
33
36
 
34
37
  try:
35
38
  pipe = self.pipeline()
39
+ if pipe is None:
40
+ logger.error("Failed to create pipeline")
41
+ return False
36
42
  for key, value in items:
37
43
  if expire_seconds:
38
44
  pipe.setex(key, expire_seconds, value)
@@ -54,6 +60,9 @@ class BatchMixin:
54
60
 
55
61
  try:
56
62
  pipe = self.pipeline()
63
+ if pipe is None:
64
+ logger.error("Failed to create pipeline")
65
+ return 0
57
66
  for key in keys:
58
67
  pipe.delete(key)
59
68
  results = pipe.execute()
@@ -16,7 +16,7 @@ class ConnectionMixin:
16
16
  socket_keepalive=self.socket_keepalive,
17
17
  health_check_interval=self.health_check_interval
18
18
  )
19
- # Testa conexão
19
+ # Testa conexão
20
20
  self.client.ping()
21
21
  logger.info(f"RedisClient connected: {self.host}:{self.port}")
22
22
  except Exception as e:
@@ -21,6 +21,7 @@ class RedisLock:
21
21
  self.timeout = timeout
22
22
  self.blocking_timeout = blocking_timeout
23
23
  self.token = None
24
+ self.acquired = False
24
25
 
25
26
  def __enter__(self):
26
27
  self.acquire()
@@ -33,6 +34,7 @@ class RedisLock:
33
34
  while True:
34
35
  self.token = str(uuid.uuid4())
35
36
  if self.client.set(self.name, self.token, self.timeout, nx=True):
37
+ self.acquired = True
36
38
  return True
37
39
 
38
40
  if self.blocking_timeout is None:
@@ -47,10 +49,11 @@ class RedisLock:
47
49
  if exc_type:
48
50
  logger.error(f"Error on lock: {exc_type.__name__}: {exc_val}")
49
51
  logger.error(f"Traceback: {''.join(traceback.format_tb(exc_tb))}")
50
-
51
- # Libera o lock normalmente
52
+ if not self.acquired:
53
+ return False
54
+
52
55
  if not self.client._ensure_connection():
53
- return
56
+ return False
54
57
  script = """
55
58
  if redis.call("get", KEYS[1]) == ARGV[1] then
56
59
  return redis.call("del", KEYS[1])
@@ -58,4 +61,10 @@ class RedisLock:
58
61
  return 0
59
62
  end
60
63
  """
61
- self.client.client.eval(script, 1, self.name, self.token)
64
+ try:
65
+ self.client.client.eval(script, 1, self.name, self.token)
66
+ except Exception as e:
67
+ logger.error(f"Error releasing lock '{self.name}': {e}")
68
+ return False
69
+
70
+ return None
@@ -1,5 +1,6 @@
1
1
  import logging
2
2
  import threading
3
+ import json
3
4
  from typing import Callable
4
5
 
5
6
  from redis_simplify.mixins.decorator_metrics import recorded
@@ -27,7 +28,6 @@ class PubSubMixin:
27
28
 
28
29
  def publish_json(self, channel: str, data: dict) -> int:
29
30
  """Publica JSON em canal"""
30
- import json
31
31
  return self.publish(channel, json.dumps(data))
32
32
 
33
33
  def subscribe(self, channel: str, callback: Callable, pattern: bool = False):
@@ -43,13 +43,13 @@ class PubSubMixin:
43
43
  else:
44
44
  pubsub.subscribe(channel)
45
45
 
46
- # Flag para controlar o loop
47
- running = True
46
+ # Variável para controlar o loop
47
+ stop_event = threading.Event()
48
48
 
49
49
  def listener():
50
50
  try:
51
51
  for message in pubsub.listen():
52
- if not running:
52
+ if stop_event.is_set():
53
53
  break
54
54
  if message['type'] in ('message', 'pmessage'):
55
55
  data = message.get('data')
@@ -69,25 +69,30 @@ class PubSubMixin:
69
69
 
70
70
  # Armazena para fechar depois
71
71
  self._pubsubs.append(pubsub)
72
- self._pubsub_threads.append((thread, pubsub, lambda: running))
72
+ self._pubsub_threads.append((thread, pubsub, stop_event))
73
73
 
74
74
  logger.info(f"Subscribed to {channel}")
75
75
  return pubsub
76
76
 
77
77
  def close_pubsubs(self):
78
78
  """Fecha todas as subscriptions ativas"""
79
- for pubsub in self._pubsubs:
80
- try:
81
- pubsub.close()
82
- except:
83
- pass
84
- self._pubsubs.clear()
79
+ for thread, pubsub, stop_event in self._pubsub_threads:
80
+ stop_event.set() # Sinaliza para parar
85
81
 
86
82
  # Aguarda threads terminarem
87
- for thread, pubsub, _ in self._pubsub_threads:
83
+ for thread, pubsub, stop_event in self._pubsub_threads:
88
84
  try:
89
85
  if thread.is_alive():
90
86
  thread.join(timeout=0.5)
91
87
  except:
92
88
  pass
89
+
90
+ # Fecha pubsubs
91
+ for pubsub in self._pubsubs:
92
+ try:
93
+ pubsub.close()
94
+ except:
95
+ pass
96
+
97
+ self._pubsubs.clear()
93
98
  self._pubsub_threads.clear()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: redis-simplify
3
- Version: 2.1.2
3
+ Version: 2.1.4
4
4
  Summary: Convenience wrapper for Redis - connection, JSON helpers, and automatic reconnection
5
5
  Author-email: Paulo Ricardo Tebet Lyrio <tebetpaulo91@yahoo.com>
6
6
  License: MIT
@@ -383,6 +383,7 @@ DEBUG:redis_simplify.client:Get test: hello world...
383
383
  | `rate_limit_check(key, max_requests, window_seconds)` | Check if action is allowed |
384
384
  | `rate_limit_remaining(key, max_requests, window_seconds)` | Get remaining requests |
385
385
  | `rate_limit_reset(key, window_seconds)` | Get seconds until reset |
386
+ | `run_with_rate_limit(operation, rate_key, max_requests, window_seconds, *args, **kwargs)` | Execute operation with automatic rate limit |
386
387
 
387
388
  ### Distributed Lock
388
389
  | Method | Description |
@@ -433,7 +434,7 @@ DEBUG:redis_simplify.client:Get test: hello world...
433
434
  | `ping()` | Verify connectivity |
434
435
  | `pipeline()` | Create a Redis pipeline |
435
436
  | `scan(cursor=0, match=None, count=None)` | Iterate keys using SCAN |
436
- | `flush_all()` | Remove all Redis databases |
437
+ | `flushall()` | Remove all Redis databases |
437
438
  | `close()` | Close the connection |
438
439
  | `set_log_level(level)` | Change log level at runtime|
439
440
 
@@ -136,8 +136,8 @@ class TestRedisClientLogging:
136
136
 
137
137
  caplog.clear()
138
138
 
139
- # flush_all gera warning
140
- client.flush_all()
139
+ # flushall gera warning
140
+ client.flushall()
141
141
 
142
142
  # Deve ter pelo menos uma mensagem WARNING
143
143
  warning_messages = [r for r in caplog.records if r.levelno == logging.WARNING]
File without changes
File without changes