by-framework 0.2.2.dev7__py3-none-any.whl → 0.2.2.dev8__py3-none-any.whl

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.
by_framework/admin/cli.py CHANGED
@@ -13,7 +13,8 @@ from rich.console import Console
13
13
  from rich.table import Table
14
14
 
15
15
  from by_framework.admin.worker_manager import WorkerManager
16
- from by_framework.common.redis_client import init_redis_from_url
16
+ from by_framework.common.config import RedisConfig
17
+ from by_framework.common.redis_client import init_redis, init_redis_from_url
17
18
  from by_framework.core.registry import WorkerRegistry
18
19
  from by_framework.metrics.snapshot import (
19
20
  build_observability_snapshot,
@@ -27,7 +28,12 @@ from by_framework.metrics.snapshot import (
27
28
  app = typer.Typer(
28
29
  name="by-admin",
29
30
  no_args_is_help=True,
30
- help="by-framework cluster admin CLI",
31
+ help=(
32
+ "by-framework cluster admin CLI. For Redis Cluster, omit --redis-url "
33
+ "and set REDIS_CLUSTER_HOST (comma-separated host:port list; implies "
34
+ "cluster mode) and REDIS_KEY_SCHEMA_VERSION=v2. REDIS_MODE=cluster + "
35
+ "REDIS_CLUSTER_NODES also still works."
36
+ ),
31
37
  )
32
38
  worker_app = typer.Typer(no_args_is_help=True)
33
39
  type_app = typer.Typer(no_args_is_help=True)
@@ -43,7 +49,8 @@ app.add_typer(metrics_app, name="metrics", help="Metrics and observability")
43
49
 
44
50
  console = Console()
45
51
  err_console = Console(stderr=True)
46
- _redis_url = "redis://localhost:6379/0"
52
+ _DEFAULT_REDIS_URL = "redis://localhost:6379/0"
53
+ _redis_url: Optional[str] = None
47
54
 
48
55
 
49
56
  @app.callback()
@@ -52,13 +59,16 @@ def _global(
52
59
  None,
53
60
  "--redis-url",
54
61
  envvar=["BYAI_REDIS_URL", "REDIS_URL"],
55
- help="Redis connection URL [env: BYAI_REDIS_URL]",
62
+ help=(
63
+ "Standalone Redis connection URL [env: BYAI_REDIS_URL]. "
64
+ "For Redis Cluster, omit this and set REDIS_CLUSTER_HOST "
65
+ "(comma-separated host:port list)."
66
+ ),
56
67
  ),
57
68
  ):
58
69
  """by-framework cluster admin CLI."""
59
70
  global _redis_url
60
- if redis_url:
61
- _redis_url = redis_url
71
+ _redis_url = redis_url
62
72
 
63
73
 
64
74
  def _run(coro): # type: ignore[no-untyped-def]
@@ -70,8 +80,14 @@ def _die(msg: str, code: int = 1) -> None:
70
80
  raise typer.Exit(code)
71
81
 
72
82
 
73
- def _get_redis():
74
- return init_redis_from_url(_redis_url)
83
+ def _get_redis(redis_url: Optional[str] = None):
84
+ configured_url = redis_url if redis_url is not None else _redis_url
85
+ if configured_url:
86
+ return init_redis_from_url(configured_url)
87
+ config = RedisConfig.from_env()
88
+ if config.mode == "cluster":
89
+ return init_redis(config=config)
90
+ return init_redis_from_url(_DEFAULT_REDIS_URL)
75
91
 
76
92
 
77
93
  # --------------------------------------------------------------------------- #
@@ -29,12 +29,22 @@ class RedisConfig:
29
29
 
30
30
  @classmethod
31
31
  def from_env(cls) -> "RedisConfig":
32
- """Load Redis configuration from environment variables."""
32
+ """Load Redis configuration from environment variables.
33
+
34
+ REDIS_CLUSTER_HOST (comma-separated "host:port" list) is the
35
+ preferred way to configure Cluster mode: just setting it is enough
36
+ to switch to cluster mode, no separate REDIS_MODE=cluster needed.
37
+ An explicit REDIS_MODE still takes precedence when set, so existing
38
+ explicit REDIS_MODE=cluster + REDIS_CLUSTER_NODES setups keep working.
39
+ """
33
40
  password = os.environ.get("REDIS_PASSWORD", "")
34
41
  username = os.environ.get("REDIS_USERNAME") or None
35
42
  max_connections = os.environ.get("REDIS_MAX_CONNECTIONS")
36
- mode = os.environ.get("REDIS_MODE", "standalone")
37
- cluster_nodes_str = os.environ.get("REDIS_CLUSTER_NODES")
43
+ cluster_host_str = os.environ.get("REDIS_CLUSTER_HOST")
44
+ cluster_nodes_str = cluster_host_str or os.environ.get("REDIS_CLUSTER_NODES")
45
+ mode = os.environ.get("REDIS_MODE") or (
46
+ "cluster" if cluster_host_str else "standalone"
47
+ )
38
48
  cluster_nodes = None
39
49
  if cluster_nodes_str:
40
50
  cluster_nodes = []
@@ -112,11 +112,11 @@ def init_redis_from_url(url: str) -> Redis:
112
112
  def get_redis() -> Redis:
113
113
  """Get the initialized global Redis client.
114
114
 
115
- If not initialized, will automatically initialize with default config.
115
+ If not initialized, automatically initialize from environment config.
116
116
  """
117
117
  global _redis_client # pylint: disable=global-variable-not-assigned
118
118
  if _redis_client is None:
119
- return init_redis()
119
+ return init_redis(config=RedisConfig.from_env())
120
120
  return _redis_client
121
121
 
122
122
 
@@ -276,11 +276,14 @@ def run_worker(
276
276
  Redis configuration: every redis_* argument defaults to None, meaning
277
277
  "not specified" - when not passed, the value is read from the
278
278
  corresponding REDIS_* environment variable (REDIS_HOST, REDIS_PORT,
279
- REDIS_DB, REDIS_PASSWORD, REDIS_USERNAME, REDIS_MODE,
279
+ REDIS_DB, REDIS_PASSWORD, REDIS_USERNAME, REDIS_MODE, REDIS_CLUSTER_HOST,
280
280
  REDIS_CLUSTER_NODES), falling back to "localhost"/6379/standalone if
281
- neither is set. An explicitly-passed argument always takes precedence
282
- over its env var, for every field, in both standalone and cluster mode
283
- - so either mode can be configured purely programmatically (e.g.
281
+ none is set. Setting REDIS_CLUSTER_HOST (comma-separated "host:port"
282
+ list) alone is enough to switch to cluster mode - no separate
283
+ REDIS_MODE=cluster required, though an explicit REDIS_MODE still wins if
284
+ set. An explicitly-passed argument always takes precedence over its env
285
+ var, for every field, in both standalone and cluster mode - so either
286
+ mode can be configured purely programmatically (e.g.
284
287
  ``redis_mode="cluster", redis_cluster_nodes=[("h1", 6379)]``) or purely
285
288
  via env vars, without the two modes behaving inconsistently.
286
289
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: by-framework
3
- Version: 0.2.2.dev7
3
+ Version: 0.2.2.dev8
4
4
  Summary: 分布式 Agent 调度框架
5
5
  License-File: LICENSE
6
6
  Requires-Python: >=3.12
@@ -1,18 +1,18 @@
1
1
  by_framework/__init__.py,sha256=5Ff4xfX-TNXcp4RMoBLQCWuehPMLpNRHwZrXofgFx5A,5300
2
2
  by_framework/__main__.py,sha256=_vIEieJzSHfZnPp-zna_hbVtWQUgE0I3mrWD41WzXiA,2561
3
3
  by_framework/admin/__init__.py,sha256=MKGQBtKk8YdnMrZ5gkzEemMl4iL8OfeFhEV6HdWR2XI,138
4
- by_framework/admin/cli.py,sha256=jsOYflCGKvSCNmZqA18fOR1mzsz_9XADl5BaEhdQVuM,10850
4
+ by_framework/admin/cli.py,sha256=Ke5Fuvk0vXkN4p2BsgcF_t40CTSvgXmOdBzwXjffd_I,11642
5
5
  by_framework/admin/worker_manager.py,sha256=ihXRMlFJAR74T2JSh3xTNCDjzAElWd0-_yVDAZwSTJU,5924
6
6
  by_framework/client/__init__.py,sha256=kGP7uoXIlTJuiJ2Cgl1Q5wqYjnMA4SZqoa7Q7BhQ5JQ,272
7
7
  by_framework/client/byai_client.py,sha256=bB1NyKLvVW82bXefD_3zymqZ1vk2O925CIbxOho9Qww,2426
8
8
  by_framework/client/client.py,sha256=T_5ahX9enmsaXm-xBGvwpMx-yALzO7wOTgY-qAVj0Q4,40342
9
9
  by_framework/common/__init__.py,sha256=EkfIiVdmb8SCpi7OOUm6Hu84B7Wzekb-TG2hbvD_R1w,1685
10
- by_framework/common/config.py,sha256=KgUJ8s2BI3Rm3JIDa1Yd0i72LthQQua-n7h-Y69QzmU,4075
10
+ by_framework/common/config.py,sha256=TFetdAaHmwMEfsN4llfu93SVWSNTcWP21aSYxHxVeSw,4603
11
11
  by_framework/common/constants.py,sha256=qzWIZcaTg4bGf-dz7bb6xJzlfvGIuw-fXhnB4mmhddc,21481
12
12
  by_framework/common/emitter.py,sha256=Mcp6vglFlS7_JVsLd_KVKvV49TKjoyoN4eCM_tm4I8s,11310
13
13
  by_framework/common/exceptions.py,sha256=NKQC7ueLZ4-gVTRz3SFRZNoPHsayu6jxi3-YlW0n_jg,962
14
14
  by_framework/common/logger.py,sha256=DX6S7U5CLcCQIUQ3IWqeeDnSC7QGuHKYaEhiKvKrBpk,5823
15
- by_framework/common/redis_client.py,sha256=DVMTGoj1RdsFXr9vdE92Y3ZMPdtVZfYQhXosyymbIcA,4640
15
+ by_framework/common/redis_client.py,sha256=JfYE-QutI9G27dbehzvLw0LziTM1gHmG4tdVjxd0IoA,4668
16
16
  by_framework/core/__init__.py,sha256=bEaOfjGoCF0WacR_PoYSb5kUqJv-g59pngdnEE7fJzo,2070
17
17
  by_framework/core/availability.py,sha256=ZME5S002eNzNpzaW_QuWw8AmUN1JelUxwCt2U3PPAeQ,17624
18
18
  by_framework/core/delivery_gate.py,sha256=yijlCOw8zEou1HCyQzwRHDJZtLBsUnXtQ3x1FZsc4yU,2012
@@ -82,7 +82,7 @@ by_framework/worker/__init__.py,sha256=GBkUWYnHc2j3_Wx2AC2P49DzFl0CSrl0SKhdRP5CT
82
82
  by_framework/worker/_control_handling.py,sha256=0bL1Alx8_qaeXQV32Xv4ARSd9q77ySh9LMd7KtZZXu8,8111
83
83
  by_framework/worker/_execution_tracking.py,sha256=AWahfDKTXGrx_JWSCNisjGKkGAQruu9vSlXisof0BYQ,2493
84
84
  by_framework/worker/_message_processing.py,sha256=rgKzJTgPVDFp_HUfMcqJBwNdTCEfspuRAo5IM9VKsxs,2622
85
- by_framework/worker/app.py,sha256=7b3BkKewPjZb5HrzC2xftGTXP59YwMtMUPZsBqbbeUM,13195
85
+ by_framework/worker/app.py,sha256=Q-zBB7yee-VvI-X5Zi1ncO6y388mgIwMKMOcUAruAQ0,13420
86
86
  by_framework/worker/byai_context.py,sha256=DvKw-X8ePZr5c5osdapvzTvH4G23u0J80U-fgMLtge4,2388
87
87
  by_framework/worker/byai_worker.py,sha256=0NoRqzuTG_MPMxVbZ1ueeOrqI0H8-Adxh7dM3vckjJo,1757
88
88
  by_framework/worker/context.py,sha256=XTNeTAhXvzS2OMDRCDKVD0s3uQscE1rFo9eImUw773w,44747
@@ -92,8 +92,8 @@ by_framework/worker/runner.py,sha256=ZuuhzdXB4oIjSaNyJCjOIYhzvw6L5N7X6kPzvrbWET8
92
92
  by_framework/worker/worker.py,sha256=_RmNkvHEN5kDPlqbHtVQhkhgiKx37xjnCxNkf_tvASM,35441
93
93
  by_framework/worker/sandbox/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
94
94
  by_framework/worker/sandbox/hook_sandbox.py,sha256=XXSdH5YGX814LvV03vkq-zn5DVIBPYYt2NhRv1lT1Bk,2329
95
- by_framework-0.2.2.dev7.dist-info/METADATA,sha256=eLdbc4la4ZUqdpLajSt3MQNsNHUV0g3vZABp3zPwYgI,26533
96
- by_framework-0.2.2.dev7.dist-info/WHEEL,sha256=mffPy8wBnZQn2VnJUU5jE99KsxaSfiyMHV9Yt0aLVxs,87
97
- by_framework-0.2.2.dev7.dist-info/entry_points.txt,sha256=5t6kgMjkR0UgJTpOsbuQDo0fOf7zeXjQW9DhkxfAGFc,56
98
- by_framework-0.2.2.dev7.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
99
- by_framework-0.2.2.dev7.dist-info/RECORD,,
95
+ by_framework-0.2.2.dev8.dist-info/METADATA,sha256=h9u-LlTowe63PPo7cXxSbXUVECTtQZEVkHgiGJvP630,26533
96
+ by_framework-0.2.2.dev8.dist-info/WHEEL,sha256=lCkmxWfQsSc9CfIClYeavTdQeEX2toPqufh9gI35EQA,87
97
+ by_framework-0.2.2.dev8.dist-info/entry_points.txt,sha256=5t6kgMjkR0UgJTpOsbuQDo0fOf7zeXjQW9DhkxfAGFc,56
98
+ by_framework-0.2.2.dev8.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
99
+ by_framework-0.2.2.dev8.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: hatchling 1.30.1
2
+ Generator: hatchling 1.31.0
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any