redis-allocator 0.4.1__tar.gz → 0.4.3__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 (22) hide show
  1. {redis_allocator-0.4.1/redis_allocator.egg-info → redis_allocator-0.4.3}/PKG-INFO +1 -1
  2. {redis_allocator-0.4.1 → redis_allocator-0.4.3}/pyproject.toml +1 -1
  3. redis_allocator-0.4.3/redis_allocator/_version.py +1 -0
  4. {redis_allocator-0.4.1 → redis_allocator-0.4.3}/redis_allocator/allocator.py +62 -16
  5. {redis_allocator-0.4.1 → redis_allocator-0.4.3/redis_allocator.egg-info}/PKG-INFO +1 -1
  6. {redis_allocator-0.4.1 → redis_allocator-0.4.3}/tests/test_allocator.py +2 -7
  7. redis_allocator-0.4.1/redis_allocator/_version.py +0 -1
  8. {redis_allocator-0.4.1 → redis_allocator-0.4.3}/LICENSE +0 -0
  9. {redis_allocator-0.4.1 → redis_allocator-0.4.3}/README.md +0 -0
  10. {redis_allocator-0.4.1 → redis_allocator-0.4.3}/redis_allocator/__init__.py +0 -0
  11. {redis_allocator-0.4.1 → redis_allocator-0.4.3}/redis_allocator/lock.py +0 -0
  12. {redis_allocator-0.4.1 → redis_allocator-0.4.3}/redis_allocator/task_queue.py +0 -0
  13. {redis_allocator-0.4.1 → redis_allocator-0.4.3}/redis_allocator.egg-info/SOURCES.txt +0 -0
  14. {redis_allocator-0.4.1 → redis_allocator-0.4.3}/redis_allocator.egg-info/dependency_links.txt +0 -0
  15. {redis_allocator-0.4.1 → redis_allocator-0.4.3}/redis_allocator.egg-info/requires.txt +0 -0
  16. {redis_allocator-0.4.1 → redis_allocator-0.4.3}/redis_allocator.egg-info/top_level.txt +0 -0
  17. {redis_allocator-0.4.1 → redis_allocator-0.4.3}/setup.cfg +0 -0
  18. {redis_allocator-0.4.1 → redis_allocator-0.4.3}/setup.py +0 -0
  19. {redis_allocator-0.4.1 → redis_allocator-0.4.3}/tests/__init__.py +0 -0
  20. {redis_allocator-0.4.1 → redis_allocator-0.4.3}/tests/conftest.py +0 -0
  21. {redis_allocator-0.4.1 → redis_allocator-0.4.3}/tests/test_lock.py +0 -0
  22. {redis_allocator-0.4.1 → redis_allocator-0.4.3}/tests/test_task_queue.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: redis-allocator
3
- Version: 0.4.1
3
+ Version: 0.4.3
4
4
  Summary: Redis-based resource allocation system.
5
5
  Home-page: https://github.com/invoker-bot/RedisAllocator-python
6
6
  Author: Invoker Bot
@@ -4,7 +4,7 @@ build-backend = 'setuptools.build_meta'
4
4
 
5
5
  [tool.commitizen]
6
6
  name = "cz_conventional_commits"
7
- version = "0.4.1"
7
+ version = "0.4.3"
8
8
  tag_format = "v$version"
9
9
 
10
10
  [tool.commitizen.version_files]
@@ -0,0 +1 @@
1
+ __version__ = '0.4.3'
@@ -199,6 +199,8 @@ class RedisAllocatorObject(Generic[U]):
199
199
  self.key = new_obj.key
200
200
  self.params = new_obj.params
201
201
  self.open()
202
+ elif self.obj is not None:
203
+ logger.error("Failed to refresh the object %s", self.key)
202
204
 
203
205
  def refresh_until_healthy(self, timeout: Timeout = 120, max_attempts: int = 10, lock_duration: Timeout = 3600, cache_timeout: Timeout = 3600):
204
206
  """Refresh the object until it is healthy."""
@@ -226,9 +228,9 @@ class RedisAllocatorObject(Generic[U]):
226
228
  return None
227
229
  return self.obj.name
228
230
 
229
- def __del__(self):
230
- """Delete the object."""
231
- self.close()
231
+ # def __del__(self):
232
+ # """Delete the object."""
233
+ # self.close()
232
234
 
233
235
 
234
236
  class RedisAllocatorUpdater:
@@ -632,6 +634,7 @@ class RedisAllocator(RedisLockPool, Generic[U]):
632
634
  local tailKey = pool_pointer_str(false)
633
635
  local function push_to_tail(itemName, expiry) -- push the item to the free list
634
636
  local tail = redis.call("GET", tailKey)
637
+ local head = redis.call("GET", headKey)
635
638
  if not tail then
636
639
  tail = ""
637
640
  end
@@ -641,11 +644,33 @@ class RedisAllocator(RedisLockPool, Generic[U]):
641
644
  else
642
645
  local tailVal = redis.call("HGET", poolItemsKey, tail)
643
646
  local prev, next, expiry = split_pool_value(tailVal)
644
- assert(next == "", "tail is not the last item in the free list")
647
+ assert(next == "" or next == '#ALLOCATED', "tail is not the last item in the free list")
645
648
  redis.call("HSET", poolItemsKey, tail, join_pool_value(prev, itemName, expiry))
646
649
  end
647
650
  redis.call("SET", tailKey, itemName) -- set the tail point to the new item
648
651
  end
652
+ -- Ensure the new head node is well-formed (prev="") and update tail/head
653
+ local function set_item_head_nil(nextItemName)
654
+ if nextItemName == "" then
655
+ -- list becomes empty
656
+ redis.call("SET", headKey, "")
657
+ redis.call("SET", tailKey, "")
658
+ return
659
+ end
660
+
661
+ local nextVal = redis.call("HGET", poolItemsKey, nextItemName)
662
+ if not nextVal then
663
+ -- corrupted pointer, clear list
664
+ redis.call("SET", headKey, "")
665
+ redis.call("SET", tailKey, "")
666
+ return
667
+ end
668
+
669
+ local _prev, nextNext, nextExpiry = split_pool_value(nextVal)
670
+ if _prev ~= "" then
671
+ redis.call("HSET", poolItemsKey, nextItemName, join_pool_value("", nextNext, nextExpiry))
672
+ end
673
+ end
649
674
  local function pop_from_head() -- pop the item from the free list
650
675
  local head = redis.call("GET", headKey)
651
676
  if not head or head == "" then -- the free list is empty
@@ -658,29 +683,33 @@ class RedisAllocator(RedisLockPool, Generic[U]):
658
683
  if is_expiry_invalid(headExpiry) then -- the item has expired
659
684
  redis.call("HDEL", poolItemsKey, head)
660
685
  redis.call("SET", headKey, headNext)
686
+ set_item_head_nil(headNext)
661
687
  return pop_from_head()
662
- end
663
- if redis.call("EXISTS", key_str(head)) > 0 then -- the item is locked
688
+ elseif redis.call("EXISTS", key_str(head)) > 0 then -- the item is locked
664
689
  redis.call("HSET", poolItemsKey, head, join_pool_value("#ALLOCATED", "#ALLOCATED", headExpiry))
665
690
  redis.call("SET", headKey, headNext)
691
+ set_item_head_nil(headNext)
666
692
  return pop_from_head()
667
- end
668
- local prev, next, expiry = split_pool_value(headVal)
669
- if next == "" then -- the item is the last in the free list
693
+ elseif headNext == "" then -- the item is the last in the free list
670
694
  redis.call("SET", headKey, "")
671
695
  redis.call("SET", tailKey, "")
672
696
  else
673
- local nextVal = redis.call("HGET", poolItemsKey, next)
697
+ local nextVal = redis.call("HGET", poolItemsKey, headNext)
674
698
  local nextPrev, nextNext, nextExpiry = split_pool_value(nextVal)
675
- redis.call("HSET", poolItemsKey, next, join_pool_value("", nextNext, nextExpiry))
676
- redis.call("SET", headKey, next)
699
+ redis.call("HSET", poolItemsKey, headNext, join_pool_value("", nextNext, nextExpiry))
700
+ redis.call("SET", headKey, headNext)
701
+ end
702
+ redis.call("HSET", poolItemsKey, head, join_pool_value("#ALLOCATED", "#ALLOCATED", headExpiry))
703
+ -- If we removed the current head, update head pointer
704
+ local savedHead = redis.call("GET", headKey)
705
+ if savedHead == itemName then
706
+ redis.call("SET", headKey, next or "")
677
707
  end
678
- redis.call("HSET", poolItemsKey, head, join_pool_value("#ALLOCATED", "#ALLOCATED", expiry))
679
708
  return head, headExpiry
680
709
  end
681
710
  local function set_item_allocated(itemName, val)
682
711
  if not val then
683
- val = redis.call("HGET", poolItemsKey, itemName)
712
+ val = redis.call("HGET", pool_str(), itemName)
684
713
  end
685
714
  if val then
686
715
  local prev, next, expiry = split_pool_value(val)
@@ -707,6 +736,22 @@ class RedisAllocator(RedisLockPool, Generic[U]):
707
736
  redis.call("SET", tailKey, prev or "")
708
737
  end
709
738
  redis.call("HSET", poolItemsKey, itemName, join_pool_value("#ALLOCATED", "#ALLOCATED", expiry))
739
+ -- If we removed the current head, update head pointer
740
+ local savedHead = redis.call("GET", headKey)
741
+ if savedHead == itemName then
742
+ redis.call("SET", headKey, next or "")
743
+ end
744
+ end
745
+ end
746
+ -- Invariant fix: ensure current head's prev pointer is always "".
747
+ local currentHead = redis.call("GET", headKey)
748
+ if currentHead and currentHead ~= "" then
749
+ local currentHeadVal = redis.call("HGET", poolItemsKey, currentHead)
750
+ if currentHeadVal then
751
+ local curPrev, curNext, curExpiry = split_pool_value(currentHeadVal)
752
+ if curPrev ~= "" then
753
+ redis.call("HSET", poolItemsKey, currentHead, join_pool_value("", curNext, curExpiry))
754
+ end
710
755
  end
711
756
  end
712
757
  end
@@ -717,8 +762,9 @@ class RedisAllocator(RedisLockPool, Generic[U]):
717
762
  assert(value, "value should not be nil")
718
763
  local prev, next, expiry = split_pool_value(value)
719
764
  if is_expiry_invalid(expiry) then -- Check if the item has expired
720
- set_item_allocated(itemName)
765
+ set_item_allocated(itemName, value)
721
766
  redis.call("HDEL", poolItemsKey, itemName)
767
+ return
722
768
  end
723
769
  local locked = redis.call("EXISTS", key_str(itemName)) > 0
724
770
  if prev == "#ALLOCATED" then
@@ -727,7 +773,7 @@ class RedisAllocator(RedisLockPool, Generic[U]):
727
773
  end
728
774
  else
729
775
  if locked then
730
- set_item_allocated(itemName)
776
+ set_item_allocated(itemName, value)
731
777
  end
732
778
  end
733
779
  end
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: redis-allocator
3
- Version: 0.4.1
3
+ Version: 0.4.3
4
4
  Summary: Redis-based resource allocation system.
5
5
  Home-page: https://github.com/invoker-bot/RedisAllocator-python
6
6
  Author: Invoker Bot
@@ -214,13 +214,8 @@ class TestRedisAllocatorObject:
214
214
  obj.close()
215
215
  assert test_object.closed
216
216
  obj.close() # Should not raise
217
-
218
- def test_del(self, redis_allocator: RedisAllocator, test_object: _TestObject, mocker: MockFixture):
219
- """Test the __del__ method."""
220
- obj = RedisAllocatorObject(redis_allocator, "test_key", test_object, {})
221
- obj.close = mocker.MagicMock()
222
- obj.__del__()
223
- obj.close.assert_called_once()
217
+ obj.refresh()
218
+ assert not test_object.closed
224
219
 
225
220
 
226
221
  class TestRedisAllocator:
@@ -1 +0,0 @@
1
- __version__ = '0.4.1'
File without changes