streamlit-octostar-utils 0.5.0.dev19__tar.gz → 0.5.1.dev1__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.
- {streamlit_octostar_utils-0.5.0.dev19 → streamlit_octostar_utils-0.5.1.dev1}/PKG-INFO +1 -1
- {streamlit_octostar_utils-0.5.0.dev19 → streamlit_octostar_utils-0.5.1.dev1}/pyproject.toml +1 -1
- {streamlit_octostar_utils-0.5.0.dev19 → streamlit_octostar_utils-0.5.1.dev1}/streamlit_octostar_utils/api_crafter/celery.py +68 -32
- {streamlit_octostar_utils-0.5.0.dev19 → streamlit_octostar_utils-0.5.1.dev1}/LICENSE +0 -0
- {streamlit_octostar_utils-0.5.0.dev19 → streamlit_octostar_utils-0.5.1.dev1}/README.md +0 -0
- {streamlit_octostar_utils-0.5.0.dev19 → streamlit_octostar_utils-0.5.1.dev1}/streamlit_octostar_utils/__init__.py +0 -0
- {streamlit_octostar_utils-0.5.0.dev19 → streamlit_octostar_utils-0.5.1.dev1}/streamlit_octostar_utils/api_crafter/__init__.py +0 -0
- {streamlit_octostar_utils-0.5.0.dev19 → streamlit_octostar_utils-0.5.1.dev1}/streamlit_octostar_utils/api_crafter/contents.py +0 -0
- {streamlit_octostar_utils-0.5.0.dev19 → streamlit_octostar_utils-0.5.1.dev1}/streamlit_octostar_utils/api_crafter/fastapi.py +0 -0
- {streamlit_octostar_utils-0.5.0.dev19 → streamlit_octostar_utils-0.5.1.dev1}/streamlit_octostar_utils/api_crafter/nifi.py +0 -0
- {streamlit_octostar_utils-0.5.0.dev19 → streamlit_octostar_utils-0.5.1.dev1}/streamlit_octostar_utils/api_crafter/parallelism.py +0 -0
- {streamlit_octostar_utils-0.5.0.dev19 → streamlit_octostar_utils-0.5.1.dev1}/streamlit_octostar_utils/api_crafter/parser/__init__.py +0 -0
- {streamlit_octostar_utils-0.5.0.dev19 → streamlit_octostar_utils-0.5.1.dev1}/streamlit_octostar_utils/api_crafter/parser/combine_fields.py +0 -0
- {streamlit_octostar_utils-0.5.0.dev19 → streamlit_octostar_utils-0.5.1.dev1}/streamlit_octostar_utils/api_crafter/parser/entities_parser.py +0 -0
- {streamlit_octostar_utils-0.5.0.dev19 → streamlit_octostar_utils-0.5.1.dev1}/streamlit_octostar_utils/api_crafter/parser/generics.py +0 -0
- {streamlit_octostar_utils-0.5.0.dev19 → streamlit_octostar_utils-0.5.1.dev1}/streamlit_octostar_utils/api_crafter/parser/info.py +0 -0
- {streamlit_octostar_utils-0.5.0.dev19 → streamlit_octostar_utils-0.5.1.dev1}/streamlit_octostar_utils/api_crafter/parser/linkchart_functions.py +0 -0
- {streamlit_octostar_utils-0.5.0.dev19 → streamlit_octostar_utils-0.5.1.dev1}/streamlit_octostar_utils/api_crafter/parser/matches.py +0 -0
- {streamlit_octostar_utils-0.5.0.dev19 → streamlit_octostar_utils-0.5.1.dev1}/streamlit_octostar_utils/api_crafter/parser/parameters.py +0 -0
- {streamlit_octostar_utils-0.5.0.dev19 → streamlit_octostar_utils-0.5.1.dev1}/streamlit_octostar_utils/api_crafter/parser/rules.py +0 -0
- {streamlit_octostar_utils-0.5.0.dev19 → streamlit_octostar_utils-0.5.1.dev1}/streamlit_octostar_utils/api_crafter/parser/signals.py +0 -0
- {streamlit_octostar_utils-0.5.0.dev19 → streamlit_octostar_utils-0.5.1.dev1}/streamlit_octostar_utils/core/__init__.py +0 -0
- {streamlit_octostar_utils-0.5.0.dev19 → streamlit_octostar_utils-0.5.1.dev1}/streamlit_octostar_utils/core/dict.py +0 -0
- {streamlit_octostar_utils-0.5.0.dev19 → streamlit_octostar_utils-0.5.1.dev1}/streamlit_octostar_utils/core/filetypes.py +0 -0
- {streamlit_octostar_utils-0.5.0.dev19 → streamlit_octostar_utils-0.5.1.dev1}/streamlit_octostar_utils/core/threading/__init__.py +0 -0
- {streamlit_octostar_utils-0.5.0.dev19 → streamlit_octostar_utils-0.5.1.dev1}/streamlit_octostar_utils/core/threading/key_queue.py +0 -0
- {streamlit_octostar_utils-0.5.0.dev19 → streamlit_octostar_utils-0.5.1.dev1}/streamlit_octostar_utils/core/timestamp.py +0 -0
- {streamlit_octostar_utils-0.5.0.dev19 → streamlit_octostar_utils-0.5.1.dev1}/streamlit_octostar_utils/nlp/__init__.py +0 -0
- {streamlit_octostar_utils-0.5.0.dev19 → streamlit_octostar_utils-0.5.1.dev1}/streamlit_octostar_utils/nlp/custom_recognizers.py +0 -0
- {streamlit_octostar_utils-0.5.0.dev19 → streamlit_octostar_utils-0.5.1.dev1}/streamlit_octostar_utils/nlp/language.py +0 -0
- {streamlit_octostar_utils-0.5.0.dev19 → streamlit_octostar_utils-0.5.1.dev1}/streamlit_octostar_utils/nlp/ner.py +0 -0
- {streamlit_octostar_utils-0.5.0.dev19 → streamlit_octostar_utils-0.5.1.dev1}/streamlit_octostar_utils/octostar/__init__.py +0 -0
- {streamlit_octostar_utils-0.5.0.dev19 → streamlit_octostar_utils-0.5.1.dev1}/streamlit_octostar_utils/octostar/client.py +0 -0
- {streamlit_octostar_utils-0.5.0.dev19 → streamlit_octostar_utils-0.5.1.dev1}/streamlit_octostar_utils/octostar/context.py +0 -0
- {streamlit_octostar_utils-0.5.0.dev19 → streamlit_octostar_utils-0.5.1.dev1}/streamlit_octostar_utils/octostar/permissions.py +0 -0
- {streamlit_octostar_utils-0.5.0.dev19 → streamlit_octostar_utils-0.5.1.dev1}/streamlit_octostar_utils/ontology/__init__.py +0 -0
- {streamlit_octostar_utils-0.5.0.dev19 → streamlit_octostar_utils-0.5.1.dev1}/streamlit_octostar_utils/ontology/inheritance.py +0 -0
- {streamlit_octostar_utils-0.5.0.dev19 → streamlit_octostar_utils-0.5.1.dev1}/streamlit_octostar_utils/ontology/relationships.py +0 -0
- {streamlit_octostar_utils-0.5.0.dev19 → streamlit_octostar_utils-0.5.1.dev1}/streamlit_octostar_utils/ontology/validation.py +0 -0
- {streamlit_octostar_utils-0.5.0.dev19 → streamlit_octostar_utils-0.5.1.dev1}/streamlit_octostar_utils/style/__init__.py +0 -0
- {streamlit_octostar_utils-0.5.0.dev19 → streamlit_octostar_utils-0.5.1.dev1}/streamlit_octostar_utils/style/common.py +0 -0
- {streamlit_octostar_utils-0.5.0.dev19 → streamlit_octostar_utils-0.5.1.dev1}/streamlit_octostar_utils/threading/__init__.py +0 -0
- {streamlit_octostar_utils-0.5.0.dev19 → streamlit_octostar_utils-0.5.1.dev1}/streamlit_octostar_utils/threading/async_task_manager.py +0 -0
- {streamlit_octostar_utils-0.5.0.dev19 → streamlit_octostar_utils-0.5.1.dev1}/streamlit_octostar_utils/threading/session_callback_manager.py +0 -0
- {streamlit_octostar_utils-0.5.0.dev19 → streamlit_octostar_utils-0.5.1.dev1}/streamlit_octostar_utils/threading/session_state_hot_swapper.py +0 -0
|
@@ -48,6 +48,65 @@ class RedisFileLock:
|
|
|
48
48
|
return self.lock.__exit__(exc_type, exc_val, exc_tb)
|
|
49
49
|
|
|
50
50
|
|
|
51
|
+
def _install_queue_limit_patch(queue_limits):
|
|
52
|
+
"""Monkey-patch kombu's Redis Channel._put for atomic queue limits.
|
|
53
|
+
|
|
54
|
+
The original _put does a bare LPUSH. The patched version wraps
|
|
55
|
+
limited queues in a Lua script (LLEN check + LPUSH) so the
|
|
56
|
+
"is there room?" test and the "enqueue" are a single atomic
|
|
57
|
+
Redis operation. Queues without a configured limit are
|
|
58
|
+
forwarded to the original _put unchanged.
|
|
59
|
+
"""
|
|
60
|
+
from kombu.transport.redis import Channel
|
|
61
|
+
from kombu.utils.json import dumps as kombu_dumps
|
|
62
|
+
|
|
63
|
+
_ATOMIC_ENQUEUE_LUA = """
|
|
64
|
+
local total = 0
|
|
65
|
+
for i = 1, #KEYS do
|
|
66
|
+
total = total + redis.call('LLEN', KEYS[i])
|
|
67
|
+
end
|
|
68
|
+
if total >= tonumber(ARGV[1]) then
|
|
69
|
+
return 0
|
|
70
|
+
end
|
|
71
|
+
redis.call('LPUSH', KEYS[1], ARGV[2])
|
|
72
|
+
return 1
|
|
73
|
+
"""
|
|
74
|
+
|
|
75
|
+
if not hasattr(Channel, "_queue_limits"):
|
|
76
|
+
Channel._queue_limits = {}
|
|
77
|
+
Channel._queue_limits.update(queue_limits)
|
|
78
|
+
|
|
79
|
+
if getattr(Channel, "_queue_limit_patched", False):
|
|
80
|
+
return
|
|
81
|
+
|
|
82
|
+
_original_put = Channel._put
|
|
83
|
+
|
|
84
|
+
def _put_with_limit(self, queue, message, **kwargs):
|
|
85
|
+
max_tasks = Channel._queue_limits.get(queue)
|
|
86
|
+
if max_tasks is not None:
|
|
87
|
+
pri = self._get_message_priority(message, reverse=False)
|
|
88
|
+
target_key = self._q_for_pri(queue, pri)
|
|
89
|
+
all_keys = [self._q_for_pri(queue, p) for p in self.priority_steps]
|
|
90
|
+
if target_key in all_keys:
|
|
91
|
+
all_keys.remove(target_key)
|
|
92
|
+
all_keys.insert(0, target_key)
|
|
93
|
+
with self.conn_or_acquire() as client:
|
|
94
|
+
accepted = client.eval(
|
|
95
|
+
_ATOMIC_ENQUEUE_LUA, len(all_keys), *all_keys,
|
|
96
|
+
max_tasks, kombu_dumps(message),
|
|
97
|
+
)
|
|
98
|
+
if not accepted:
|
|
99
|
+
from streamlit_octostar_utils.api_crafter.celery import CeleryExecutor
|
|
100
|
+
raise CeleryExecutor.QueueFullException(
|
|
101
|
+
f"Queue '{queue}' has reached its limit of {max_tasks} tasks!"
|
|
102
|
+
)
|
|
103
|
+
else:
|
|
104
|
+
_original_put(self, queue, message, **kwargs)
|
|
105
|
+
|
|
106
|
+
Channel._put = _put_with_limit
|
|
107
|
+
Channel._queue_limit_patched = True
|
|
108
|
+
|
|
109
|
+
|
|
51
110
|
class CeleryQueueConfig:
|
|
52
111
|
def __init__(
|
|
53
112
|
self,
|
|
@@ -201,10 +260,11 @@ class CeleryExecutor(object):
|
|
|
201
260
|
self.get_thread_pool = None
|
|
202
261
|
self.set_thread_pool = None
|
|
203
262
|
self.io_thread_pool = None
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
263
|
+
|
|
264
|
+
# Atomic queue-depth limits
|
|
265
|
+
queue_limits = {k: v.max_tasks_in_queue for k, v in self.queue_config.items() if v.max_tasks_in_queue}
|
|
266
|
+
if queue_limits:
|
|
267
|
+
_install_queue_limit_patch(queue_limits)
|
|
208
268
|
|
|
209
269
|
# Folder setup
|
|
210
270
|
self.base_folder = Path(base_folder).resolve()
|
|
@@ -720,17 +780,6 @@ class CeleryExecutor(object):
|
|
|
720
780
|
self.preload_on_worker_init()
|
|
721
781
|
self.app.conf.dev_preload = True
|
|
722
782
|
|
|
723
|
-
def _check_queue_llen(queue_name):
|
|
724
|
-
if self._queue_stalled.get(queue_name, False):
|
|
725
|
-
raise CeleryExecutor.QueueStalledException(
|
|
726
|
-
f"Queue '{queue_name}' is stalled. Service temporarily unavailable."
|
|
727
|
-
)
|
|
728
|
-
if self.redis_client.llen(queue_name) >= self.queue_config[queue_name].max_tasks_in_queue:
|
|
729
|
-
raise CeleryExecutor.QueueFullException(
|
|
730
|
-
f"Queue '{queue_name}' has reached its limit of "
|
|
731
|
-
f"{self.queue_config[queue_name].max_tasks_in_queue} tasks!"
|
|
732
|
-
)
|
|
733
|
-
|
|
734
783
|
def _write_task_data(in_folder, task_args, task_kwargs, task_id):
|
|
735
784
|
serialized_data = CelerySerialized(
|
|
736
785
|
folder=in_folder,
|
|
@@ -754,22 +803,12 @@ class CeleryExecutor(object):
|
|
|
754
803
|
queue_name = getattr(task_fn, "queue", queue_name)
|
|
755
804
|
queue_name = options.get("queue", queue_name)
|
|
756
805
|
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
raise CeleryExecutor.QueueFullException(
|
|
762
|
-
f"Queue '{queue_name}' has reached its limit of "
|
|
763
|
-
f"{self.queue_config[queue_name].max_tasks_in_queue} tasks!"
|
|
764
|
-
)
|
|
765
|
-
acquired = True
|
|
806
|
+
if self._queue_stalled.get(queue_name, False):
|
|
807
|
+
raise CeleryExecutor.QueueStalledException(
|
|
808
|
+
f"Queue '{queue_name}' is stalled. Service temporarily unavailable."
|
|
809
|
+
)
|
|
766
810
|
|
|
767
811
|
try:
|
|
768
|
-
if acquired:
|
|
769
|
-
await asyncio.get_running_loop().run_in_executor(
|
|
770
|
-
self.set_thread_pool, _check_queue_llen, queue_name
|
|
771
|
-
)
|
|
772
|
-
|
|
773
812
|
if part is not None:
|
|
774
813
|
await self._write_task_data_with_part(
|
|
775
814
|
task_id, args, kwargs, part
|
|
@@ -800,9 +839,6 @@ class CeleryExecutor(object):
|
|
|
800
839
|
except Exception:
|
|
801
840
|
pass
|
|
802
841
|
raise
|
|
803
|
-
finally:
|
|
804
|
-
if acquired:
|
|
805
|
-
sem.release()
|
|
806
842
|
return task_id
|
|
807
843
|
|
|
808
844
|
async def _write_task_data_with_part(self, task_id, args, kwargs, part):
|
|
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
|
|
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
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|