redis-allocator 0.4.2__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.2/redis_allocator.egg-info → redis_allocator-0.4.3}/PKG-INFO +1 -1
  2. {redis_allocator-0.4.2 → 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.2 → redis_allocator-0.4.3}/redis_allocator/allocator.py +57 -13
  5. {redis_allocator-0.4.2 → redis_allocator-0.4.3/redis_allocator.egg-info}/PKG-INFO +1 -1
  6. redis_allocator-0.4.2/redis_allocator/_version.py +0 -1
  7. {redis_allocator-0.4.2 → redis_allocator-0.4.3}/LICENSE +0 -0
  8. {redis_allocator-0.4.2 → redis_allocator-0.4.3}/README.md +0 -0
  9. {redis_allocator-0.4.2 → redis_allocator-0.4.3}/redis_allocator/__init__.py +0 -0
  10. {redis_allocator-0.4.2 → redis_allocator-0.4.3}/redis_allocator/lock.py +0 -0
  11. {redis_allocator-0.4.2 → redis_allocator-0.4.3}/redis_allocator/task_queue.py +0 -0
  12. {redis_allocator-0.4.2 → redis_allocator-0.4.3}/redis_allocator.egg-info/SOURCES.txt +0 -0
  13. {redis_allocator-0.4.2 → redis_allocator-0.4.3}/redis_allocator.egg-info/dependency_links.txt +0 -0
  14. {redis_allocator-0.4.2 → redis_allocator-0.4.3}/redis_allocator.egg-info/requires.txt +0 -0
  15. {redis_allocator-0.4.2 → redis_allocator-0.4.3}/redis_allocator.egg-info/top_level.txt +0 -0
  16. {redis_allocator-0.4.2 → redis_allocator-0.4.3}/setup.cfg +0 -0
  17. {redis_allocator-0.4.2 → redis_allocator-0.4.3}/setup.py +0 -0
  18. {redis_allocator-0.4.2 → redis_allocator-0.4.3}/tests/__init__.py +0 -0
  19. {redis_allocator-0.4.2 → redis_allocator-0.4.3}/tests/conftest.py +0 -0
  20. {redis_allocator-0.4.2 → redis_allocator-0.4.3}/tests/test_allocator.py +0 -0
  21. {redis_allocator-0.4.2 → redis_allocator-0.4.3}/tests/test_lock.py +0 -0
  22. {redis_allocator-0.4.2 → 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.2
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.2"
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'
@@ -634,6 +634,7 @@ class RedisAllocator(RedisLockPool, Generic[U]):
634
634
  local tailKey = pool_pointer_str(false)
635
635
  local function push_to_tail(itemName, expiry) -- push the item to the free list
636
636
  local tail = redis.call("GET", tailKey)
637
+ local head = redis.call("GET", headKey)
637
638
  if not tail then
638
639
  tail = ""
639
640
  end
@@ -643,11 +644,33 @@ class RedisAllocator(RedisLockPool, Generic[U]):
643
644
  else
644
645
  local tailVal = redis.call("HGET", poolItemsKey, tail)
645
646
  local prev, next, expiry = split_pool_value(tailVal)
646
- 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")
647
648
  redis.call("HSET", poolItemsKey, tail, join_pool_value(prev, itemName, expiry))
648
649
  end
649
650
  redis.call("SET", tailKey, itemName) -- set the tail point to the new item
650
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
651
674
  local function pop_from_head() -- pop the item from the free list
652
675
  local head = redis.call("GET", headKey)
653
676
  if not head or head == "" then -- the free list is empty
@@ -660,29 +683,33 @@ class RedisAllocator(RedisLockPool, Generic[U]):
660
683
  if is_expiry_invalid(headExpiry) then -- the item has expired
661
684
  redis.call("HDEL", poolItemsKey, head)
662
685
  redis.call("SET", headKey, headNext)
686
+ set_item_head_nil(headNext)
663
687
  return pop_from_head()
664
- end
665
- 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
666
689
  redis.call("HSET", poolItemsKey, head, join_pool_value("#ALLOCATED", "#ALLOCATED", headExpiry))
667
690
  redis.call("SET", headKey, headNext)
691
+ set_item_head_nil(headNext)
668
692
  return pop_from_head()
669
- end
670
- local prev, next, expiry = split_pool_value(headVal)
671
- 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
672
694
  redis.call("SET", headKey, "")
673
695
  redis.call("SET", tailKey, "")
674
696
  else
675
- local nextVal = redis.call("HGET", poolItemsKey, next)
697
+ local nextVal = redis.call("HGET", poolItemsKey, headNext)
676
698
  local nextPrev, nextNext, nextExpiry = split_pool_value(nextVal)
677
- redis.call("HSET", poolItemsKey, next, join_pool_value("", nextNext, nextExpiry))
678
- 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 "")
679
707
  end
680
- redis.call("HSET", poolItemsKey, head, join_pool_value("#ALLOCATED", "#ALLOCATED", expiry))
681
708
  return head, headExpiry
682
709
  end
683
710
  local function set_item_allocated(itemName, val)
684
711
  if not val then
685
- val = redis.call("HGET", poolItemsKey, itemName)
712
+ val = redis.call("HGET", pool_str(), itemName)
686
713
  end
687
714
  if val then
688
715
  local prev, next, expiry = split_pool_value(val)
@@ -709,6 +736,22 @@ class RedisAllocator(RedisLockPool, Generic[U]):
709
736
  redis.call("SET", tailKey, prev or "")
710
737
  end
711
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
712
755
  end
713
756
  end
714
757
  end
@@ -719,8 +762,9 @@ class RedisAllocator(RedisLockPool, Generic[U]):
719
762
  assert(value, "value should not be nil")
720
763
  local prev, next, expiry = split_pool_value(value)
721
764
  if is_expiry_invalid(expiry) then -- Check if the item has expired
722
- set_item_allocated(itemName)
765
+ set_item_allocated(itemName, value)
723
766
  redis.call("HDEL", poolItemsKey, itemName)
767
+ return
724
768
  end
725
769
  local locked = redis.call("EXISTS", key_str(itemName)) > 0
726
770
  if prev == "#ALLOCATED" then
@@ -729,7 +773,7 @@ class RedisAllocator(RedisLockPool, Generic[U]):
729
773
  end
730
774
  else
731
775
  if locked then
732
- set_item_allocated(itemName)
776
+ set_item_allocated(itemName, value)
733
777
  end
734
778
  end
735
779
  end
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: redis-allocator
3
- Version: 0.4.2
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
@@ -1 +0,0 @@
1
- __version__ = '0.4.2'
File without changes