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.
- {redis_allocator-0.4.1/redis_allocator.egg-info → redis_allocator-0.4.3}/PKG-INFO +1 -1
- {redis_allocator-0.4.1 → redis_allocator-0.4.3}/pyproject.toml +1 -1
- redis_allocator-0.4.3/redis_allocator/_version.py +1 -0
- {redis_allocator-0.4.1 → redis_allocator-0.4.3}/redis_allocator/allocator.py +62 -16
- {redis_allocator-0.4.1 → redis_allocator-0.4.3/redis_allocator.egg-info}/PKG-INFO +1 -1
- {redis_allocator-0.4.1 → redis_allocator-0.4.3}/tests/test_allocator.py +2 -7
- redis_allocator-0.4.1/redis_allocator/_version.py +0 -1
- {redis_allocator-0.4.1 → redis_allocator-0.4.3}/LICENSE +0 -0
- {redis_allocator-0.4.1 → redis_allocator-0.4.3}/README.md +0 -0
- {redis_allocator-0.4.1 → redis_allocator-0.4.3}/redis_allocator/__init__.py +0 -0
- {redis_allocator-0.4.1 → redis_allocator-0.4.3}/redis_allocator/lock.py +0 -0
- {redis_allocator-0.4.1 → redis_allocator-0.4.3}/redis_allocator/task_queue.py +0 -0
- {redis_allocator-0.4.1 → redis_allocator-0.4.3}/redis_allocator.egg-info/SOURCES.txt +0 -0
- {redis_allocator-0.4.1 → redis_allocator-0.4.3}/redis_allocator.egg-info/dependency_links.txt +0 -0
- {redis_allocator-0.4.1 → redis_allocator-0.4.3}/redis_allocator.egg-info/requires.txt +0 -0
- {redis_allocator-0.4.1 → redis_allocator-0.4.3}/redis_allocator.egg-info/top_level.txt +0 -0
- {redis_allocator-0.4.1 → redis_allocator-0.4.3}/setup.cfg +0 -0
- {redis_allocator-0.4.1 → redis_allocator-0.4.3}/setup.py +0 -0
- {redis_allocator-0.4.1 → redis_allocator-0.4.3}/tests/__init__.py +0 -0
- {redis_allocator-0.4.1 → redis_allocator-0.4.3}/tests/conftest.py +0 -0
- {redis_allocator-0.4.1 → redis_allocator-0.4.3}/tests/test_lock.py +0 -0
- {redis_allocator-0.4.1 → redis_allocator-0.4.3}/tests/test_task_queue.py +0 -0
@@ -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
|
-
|
231
|
-
|
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
|
-
|
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
|
-
|
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,
|
697
|
+
local nextVal = redis.call("HGET", poolItemsKey, headNext)
|
674
698
|
local nextPrev, nextNext, nextExpiry = split_pool_value(nextVal)
|
675
|
-
redis.call("HSET", poolItemsKey,
|
676
|
-
redis.call("SET", headKey,
|
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",
|
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
|
@@ -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
|
-
|
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
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{redis_allocator-0.4.1 → redis_allocator-0.4.3}/redis_allocator.egg-info/dependency_links.txt
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|