chalk-remote-call-python 1.10.9__tar.gz → 1.10.11__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 (74) hide show
  1. {chalk_remote_call_python-1.10.9/chalk_remote_call_python.egg-info → chalk_remote_call_python-1.10.11}/PKG-INFO +13 -1
  2. {chalk_remote_call_python-1.10.9 → chalk_remote_call_python-1.10.11}/README.md +12 -0
  3. {chalk_remote_call_python-1.10.9 → chalk_remote_call_python-1.10.11}/chalk-remote-call-rs/Cargo.lock +1 -1
  4. {chalk_remote_call_python-1.10.9 → chalk_remote_call_python-1.10.11}/chalk-remote-call-rs/chalk-remote-call-server/Cargo.toml +1 -1
  5. {chalk_remote_call_python-1.10.9 → chalk_remote_call_python-1.10.11}/chalk-remote-call-rs/chalk-remote-call-server/src/self_consumer.rs +12 -12
  6. chalk_remote_call_python-1.10.11/chalk_remote_call/_version.py +1 -0
  7. {chalk_remote_call_python-1.10.9 → chalk_remote_call_python-1.10.11}/chalk_remote_call/servicer.py +25 -16
  8. {chalk_remote_call_python-1.10.9 → chalk_remote_call_python-1.10.11/chalk_remote_call_python.egg-info}/PKG-INFO +13 -1
  9. chalk_remote_call_python-1.10.9/chalk_remote_call/_version.py +0 -1
  10. {chalk_remote_call_python-1.10.9 → chalk_remote_call_python-1.10.11}/MANIFEST.in +0 -0
  11. {chalk_remote_call_python-1.10.9 → chalk_remote_call_python-1.10.11}/chalk-remote-call-rs/Cargo.toml +0 -0
  12. {chalk_remote_call_python-1.10.9 → chalk_remote_call_python-1.10.11}/chalk-remote-call-rs/chalk-remote-call-proto/Cargo.toml +0 -0
  13. {chalk_remote_call_python-1.10.9 → chalk_remote_call_python-1.10.11}/chalk-remote-call-rs/chalk-remote-call-proto/src/gen/chalk.auth.v1.rs +0 -0
  14. {chalk_remote_call_python-1.10.9 → chalk_remote_call_python-1.10.11}/chalk-remote-call-rs/chalk-remote-call-proto/src/gen/chalk.common.v1.rs +0 -0
  15. {chalk_remote_call_python-1.10.9 → chalk_remote_call_python-1.10.11}/chalk-remote-call-rs/chalk-remote-call-proto/src/gen/chalk.runtime.v1.rs +0 -0
  16. {chalk_remote_call_python-1.10.9 → chalk_remote_call_python-1.10.11}/chalk-remote-call-rs/chalk-remote-call-proto/src/gen/chalk.runtime.v1.tonic.rs +0 -0
  17. {chalk_remote_call_python-1.10.9 → chalk_remote_call_python-1.10.11}/chalk-remote-call-rs/chalk-remote-call-proto/src/gen/chalk.utils.v1.rs +0 -0
  18. {chalk_remote_call_python-1.10.9 → chalk_remote_call_python-1.10.11}/chalk-remote-call-rs/chalk-remote-call-proto/src/gen/descriptor.bin +0 -0
  19. {chalk_remote_call_python-1.10.9 → chalk_remote_call_python-1.10.11}/chalk-remote-call-rs/chalk-remote-call-proto/src/lib.rs +0 -0
  20. {chalk_remote_call_python-1.10.9 → chalk_remote_call_python-1.10.11}/chalk-remote-call-rs/chalk-remote-call-server/build.rs +0 -0
  21. {chalk_remote_call_python-1.10.9 → chalk_remote_call_python-1.10.11}/chalk-remote-call-rs/chalk-remote-call-server/src/async_service.rs +0 -0
  22. {chalk_remote_call_python-1.10.9 → chalk_remote_call_python-1.10.11}/chalk-remote-call-rs/chalk-remote-call-server/src/coalesce.rs +0 -0
  23. {chalk_remote_call_python-1.10.9 → chalk_remote_call_python-1.10.11}/chalk-remote-call-rs/chalk-remote-call-server/src/fnq_client.rs +0 -0
  24. {chalk_remote_call_python-1.10.9 → chalk_remote_call_python-1.10.11}/chalk-remote-call-rs/chalk-remote-call-server/src/lib.rs +0 -0
  25. {chalk_remote_call_python-1.10.9 → chalk_remote_call_python-1.10.11}/chalk-remote-call-rs/chalk-remote-call-server/src/metrics.rs +0 -0
  26. {chalk_remote_call_python-1.10.9 → chalk_remote_call_python-1.10.11}/chalk-remote-call-rs/chalk-remote-call-server/src/python_bridge.rs +0 -0
  27. {chalk_remote_call_python-1.10.9 → chalk_remote_call_python-1.10.11}/chalk-remote-call-rs/chalk-remote-call-server/src/server.rs +0 -0
  28. {chalk_remote_call_python-1.10.9 → chalk_remote_call_python-1.10.11}/chalk-remote-call-rs/chalk-remote-call-server/src/service.rs +0 -0
  29. {chalk_remote_call_python-1.10.9 → chalk_remote_call_python-1.10.11}/chalk-remote-call-rs/rust-toolchain.toml +0 -0
  30. {chalk_remote_call_python-1.10.9 → chalk_remote_call_python-1.10.11}/chalk_remote_call/__init__.py +0 -0
  31. {chalk_remote_call_python-1.10.9 → chalk_remote_call_python-1.10.11}/chalk_remote_call/__main__.py +0 -0
  32. {chalk_remote_call_python-1.10.9 → chalk_remote_call_python-1.10.11}/chalk_remote_call/_gen/__init__.py +0 -0
  33. {chalk_remote_call_python-1.10.9 → chalk_remote_call_python-1.10.11}/chalk_remote_call/_gen/chalk/__init__.py +0 -0
  34. {chalk_remote_call_python-1.10.9 → chalk_remote_call_python-1.10.11}/chalk_remote_call/_gen/chalk/auth/__init__.py +0 -0
  35. {chalk_remote_call_python-1.10.9 → chalk_remote_call_python-1.10.11}/chalk_remote_call/_gen/chalk/auth/v1/__init__.py +0 -0
  36. {chalk_remote_call_python-1.10.9 → chalk_remote_call_python-1.10.11}/chalk_remote_call/_gen/chalk/auth/v1/permissions_pb2.py +0 -0
  37. {chalk_remote_call_python-1.10.9 → chalk_remote_call_python-1.10.11}/chalk_remote_call/_gen/chalk/auth/v1/permissions_pb2_grpc.py +0 -0
  38. {chalk_remote_call_python-1.10.9 → chalk_remote_call_python-1.10.11}/chalk_remote_call/_gen/chalk/common/__init__.py +0 -0
  39. {chalk_remote_call_python-1.10.9 → chalk_remote_call_python-1.10.11}/chalk_remote_call/_gen/chalk/common/v1/__init__.py +0 -0
  40. {chalk_remote_call_python-1.10.9 → chalk_remote_call_python-1.10.11}/chalk_remote_call/_gen/chalk/common/v1/chalk_error_pb2.py +0 -0
  41. {chalk_remote_call_python-1.10.9 → chalk_remote_call_python-1.10.11}/chalk_remote_call/_gen/chalk/common/v1/chalk_error_pb2_grpc.py +0 -0
  42. {chalk_remote_call_python-1.10.9 → chalk_remote_call_python-1.10.11}/chalk_remote_call/_gen/chalk/runtime/__init__.py +0 -0
  43. {chalk_remote_call_python-1.10.9 → chalk_remote_call_python-1.10.11}/chalk_remote_call/_gen/chalk/runtime/v1/__init__.py +0 -0
  44. {chalk_remote_call_python-1.10.9 → chalk_remote_call_python-1.10.11}/chalk_remote_call/_gen/chalk/runtime/v1/fnq_consumer_pb2.py +0 -0
  45. {chalk_remote_call_python-1.10.9 → chalk_remote_call_python-1.10.11}/chalk_remote_call/_gen/chalk/runtime/v1/fnq_consumer_pb2_grpc.py +0 -0
  46. {chalk_remote_call_python-1.10.9 → chalk_remote_call_python-1.10.11}/chalk_remote_call/_gen/chalk/runtime/v1/remote_python_call_pb2.py +0 -0
  47. {chalk_remote_call_python-1.10.9 → chalk_remote_call_python-1.10.11}/chalk_remote_call/_gen/chalk/runtime/v1/remote_python_call_pb2_grpc.py +0 -0
  48. {chalk_remote_call_python-1.10.9 → chalk_remote_call_python-1.10.11}/chalk_remote_call/_gen/chalk/utils/__init__.py +0 -0
  49. {chalk_remote_call_python-1.10.9 → chalk_remote_call_python-1.10.11}/chalk_remote_call/_gen/chalk/utils/v1/__init__.py +0 -0
  50. {chalk_remote_call_python-1.10.9 → chalk_remote_call_python-1.10.11}/chalk_remote_call/_gen/chalk/utils/v1/encoding_pb2.py +0 -0
  51. {chalk_remote_call_python-1.10.9 → chalk_remote_call_python-1.10.11}/chalk_remote_call/_gen/chalk/utils/v1/encoding_pb2_grpc.py +0 -0
  52. {chalk_remote_call_python-1.10.9 → chalk_remote_call_python-1.10.11}/chalk_remote_call/_gen/chalk/utils/v1/field_change_pb2.py +0 -0
  53. {chalk_remote_call_python-1.10.9 → chalk_remote_call_python-1.10.11}/chalk_remote_call/_gen/chalk/utils/v1/field_change_pb2_grpc.py +0 -0
  54. {chalk_remote_call_python-1.10.9 → chalk_remote_call_python-1.10.11}/chalk_remote_call/_gen/chalk/utils/v1/large_pb2.py +0 -0
  55. {chalk_remote_call_python-1.10.9 → chalk_remote_call_python-1.10.11}/chalk_remote_call/_gen/chalk/utils/v1/large_pb2_grpc.py +0 -0
  56. {chalk_remote_call_python-1.10.9 → chalk_remote_call_python-1.10.11}/chalk_remote_call/_gen/chalk/utils/v1/sensitive_pb2.py +0 -0
  57. {chalk_remote_call_python-1.10.9 → chalk_remote_call_python-1.10.11}/chalk_remote_call/_gen/chalk/utils/v1/sensitive_pb2_grpc.py +0 -0
  58. {chalk_remote_call_python-1.10.9 → chalk_remote_call_python-1.10.11}/chalk_remote_call/_native.pyi +0 -0
  59. {chalk_remote_call_python-1.10.9 → chalk_remote_call_python-1.10.11}/chalk_remote_call/arrow_utils.py +0 -0
  60. {chalk_remote_call_python-1.10.9 → chalk_remote_call_python-1.10.11}/chalk_remote_call/cli.py +0 -0
  61. {chalk_remote_call_python-1.10.9 → chalk_remote_call_python-1.10.11}/chalk_remote_call/errors.py +0 -0
  62. {chalk_remote_call_python-1.10.9 → chalk_remote_call_python-1.10.11}/chalk_remote_call/handler_loader.py +0 -0
  63. {chalk_remote_call_python-1.10.9 → chalk_remote_call_python-1.10.11}/chalk_remote_call/input_transform.py +0 -0
  64. {chalk_remote_call_python-1.10.9 → chalk_remote_call_python-1.10.11}/chalk_remote_call/logging.py +0 -0
  65. {chalk_remote_call_python-1.10.9 → chalk_remote_call_python-1.10.11}/chalk_remote_call/server.py +0 -0
  66. {chalk_remote_call_python-1.10.9 → chalk_remote_call_python-1.10.11}/chalk_remote_call/tracing.py +0 -0
  67. {chalk_remote_call_python-1.10.9 → chalk_remote_call_python-1.10.11}/chalk_remote_call_python.egg-info/SOURCES.txt +0 -0
  68. {chalk_remote_call_python-1.10.9 → chalk_remote_call_python-1.10.11}/chalk_remote_call_python.egg-info/dependency_links.txt +0 -0
  69. {chalk_remote_call_python-1.10.9 → chalk_remote_call_python-1.10.11}/chalk_remote_call_python.egg-info/entry_points.txt +0 -0
  70. {chalk_remote_call_python-1.10.9 → chalk_remote_call_python-1.10.11}/chalk_remote_call_python.egg-info/requires.txt +0 -0
  71. {chalk_remote_call_python-1.10.9 → chalk_remote_call_python-1.10.11}/chalk_remote_call_python.egg-info/top_level.txt +0 -0
  72. {chalk_remote_call_python-1.10.9 → chalk_remote_call_python-1.10.11}/pyproject.toml +0 -0
  73. {chalk_remote_call_python-1.10.9 → chalk_remote_call_python-1.10.11}/setup.cfg +0 -0
  74. {chalk_remote_call_python-1.10.9 → chalk_remote_call_python-1.10.11}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: chalk-remote-call-python
3
- Version: 1.10.9
3
+ Version: 1.10.11
4
4
  Summary: Chalk remote call Python runtime interface client
5
5
  Author: Chalk AI, Inc.
6
6
  Project-URL: Homepage, https://chalk.ai
@@ -186,6 +186,18 @@ def handler(event, context):
186
186
  serve(handler=handler, port=8080)
187
187
  ```
188
188
 
189
+ ### Invocation context
190
+
191
+ Each Python bridge invocation runs in a fresh `contextvars.Context`. Handler
192
+ changes to context variables stay within that invocation, including across
193
+ awaits and generator iteration, and are discarded on return or error. Incoming
194
+ request metadata still supplies the tracing parent. A coalesced batch has one
195
+ invocation context for the whole batch.
196
+
197
+ Workers retain their Python thread state for compatibility with native
198
+ extensions. This context boundary does not reset process globals or
199
+ `threading.local()` storage, whose lifetime follows the worker thread.
200
+
189
201
  ## Local Testing
190
202
 
191
203
  Use `grpcurl` to verify the server is running:
@@ -147,6 +147,18 @@ def handler(event, context):
147
147
  serve(handler=handler, port=8080)
148
148
  ```
149
149
 
150
+ ### Invocation context
151
+
152
+ Each Python bridge invocation runs in a fresh `contextvars.Context`. Handler
153
+ changes to context variables stay within that invocation, including across
154
+ awaits and generator iteration, and are discarded on return or error. Incoming
155
+ request metadata still supplies the tracing parent. A coalesced batch has one
156
+ invocation context for the whole batch.
157
+
158
+ Workers retain their Python thread state for compatibility with native
159
+ extensions. This context boundary does not reset process globals or
160
+ `threading.local()` storage, whose lifetime follows the worker thread.
161
+
150
162
  ## Local Testing
151
163
 
152
164
  Use `grpcurl` to verify the server is running:
@@ -511,7 +511,7 @@ dependencies = [
511
511
  [[package]]
512
512
  name = "chalk-queue"
513
513
  version = "0.0.0"
514
- source = "git+https://github.com/chalk-ai/chalk-private.git?rev=1460144ea659debbaee9dccadcd4d7dbf383ccf8#1460144ea659debbaee9dccadcd4d7dbf383ccf8"
514
+ source = "git+https://github.com/chalk-ai/chalk-private.git?rev=6156b025245e28f409bd6c115cfa158ed60203ea#6156b025245e28f409bd6c115cfa158ed60203ea"
515
515
  dependencies = [
516
516
  "base64 0.22.1",
517
517
  "redis",
@@ -45,7 +45,7 @@ futures-util = "0.3"
45
45
  # `[patch.crates-io]` here it builds against vanilla crates.io redis (it only
46
46
  # uses standard APIs). Metrics and StatsD share a revision so their client types agree.
47
47
  [target.'cfg(target_os = "linux")'.dependencies]
48
- chalk-queue = { git = "https://github.com/chalk-ai/chalk-private.git", rev = "1460144ea659debbaee9dccadcd4d7dbf383ccf8" }
48
+ chalk-queue = { git = "https://github.com/chalk-ai/chalk-private.git", rev = "6156b025245e28f409bd6c115cfa158ed60203ea" }
49
49
  chalk_metrics = { git = "https://github.com/chalk-ai/chalk-private.git", rev = "a0f8932ec10d3b8340af3e98cf63b800d60b4926" }
50
50
  chalk_statsd = { git = "https://github.com/chalk-ai/chalk-private.git", rev = "a0f8932ec10d3b8340af3e98cf63b800d60b4926" }
51
51
 
@@ -42,7 +42,7 @@ use std::str::FromStr;
42
42
  use std::sync::{Arc, Mutex};
43
43
  use std::time::{Duration, Instant};
44
44
 
45
- use chalk_queue::semaphore::renew_many;
45
+ use chalk_queue::semaphore::{release_many, renew_many};
46
46
  use chalk_queue::stream_writer;
47
47
  use chalk_queue::types::{DeliveryAttempt, QueuedCall};
48
48
  use chalk_queue::{
@@ -802,7 +802,7 @@ async fn run_stream_dispatch_loop(
802
802
  input_queue: BoundFunctionQueue,
803
803
  legacy_queue: Option<BoundFunctionQueue>,
804
804
  sem: chalk_queue::DistributedSemaphore,
805
- conn: ConnectionManager,
805
+ mut conn: ConnectionManager,
806
806
  consumer_name: String,
807
807
  live_calls: LiveCalls,
808
808
  handler: Arc<PythonHandler>,
@@ -877,23 +877,23 @@ async fn run_stream_dispatch_loop(
877
877
  }
878
878
  }
879
879
 
880
+ // Return unused reservations in one round-trip before dispatching work.
881
+ // Transferring the tokens prevents Drop from also releasing each lease.
882
+ let used = deliveries.len().min(leases.len());
883
+ let unused_tokens = leases
884
+ .split_off(used)
885
+ .into_iter()
886
+ .map(SemaphoreLease::into_token)
887
+ .collect::<Vec<_>>();
888
+ let _ = release_many(&mut conn, sem.key(), &unused_tokens).await;
889
+
880
890
  if deliveries.is_empty() {
881
- for lease in leases {
882
- let _ = lease.release().await;
883
- }
884
891
  tokio::time::sleep(backoff).await;
885
892
  backoff = (backoff * 2).min(config.poll_backoff_max);
886
893
  continue;
887
894
  }
888
895
 
889
896
  backoff = config.poll_backoff_initial;
890
- // `dequeue_many` can return fewer records than requested. Only retain
891
- // one lease per record and immediately return the unneeded capacity.
892
- let used = deliveries.len().min(leases.len());
893
- let unused = leases.split_off(used);
894
- for lease in unused {
895
- let _ = lease.release().await;
896
- }
897
897
  for (delivery, lease) in deliveries.into_iter().zip(leases) {
898
898
  dispatch_delivery(
899
899
  queue.clone(),
@@ -0,0 +1 @@
1
+ __version__ = "1.10.11"
@@ -4,7 +4,9 @@ import asyncio
4
4
  import dataclasses
5
5
  import inspect
6
6
  from collections.abc import Callable
7
- from typing import Any
7
+ from contextvars import Context
8
+ from functools import wraps
9
+ from typing import Any, ParamSpec, TypeVar
8
10
 
9
11
  import pyarrow as pa
10
12
  import pyarrow.ipc as ipc
@@ -13,6 +15,18 @@ from chalk_remote_call.arrow_utils import decode_ipc_stream, encode_record_batch
13
15
  from chalk_remote_call.input_transform import resolve_column_names, transform
14
16
  from chalk_remote_call.tracing import remote_function_invocation_span
15
17
 
18
+ _Params = ParamSpec("_Params")
19
+ _Result = TypeVar("_Result")
20
+
21
+
22
+ def _isolated_context(function: Callable[_Params, _Result]) -> Callable[_Params, _Result]:
23
+ @wraps(function)
24
+ def invoke(*args: _Params.args, **kwargs: _Params.kwargs) -> _Result:
25
+ # Keep native thread state reusable while request ContextVars start empty.
26
+ return Context().run(function, *args, **kwargs)
27
+
28
+ return invoke
29
+
16
30
 
17
31
  def _is_structured(obj: Any) -> bool:
18
32
  """Return True if *obj* is a recognised structured-type instance."""
@@ -124,27 +138,19 @@ def _coerce_to_record_batch(result: Any) -> pa.RecordBatch:
124
138
  raise TypeError(f"Cannot convert handler result of type {type(result).__name__} to RecordBatch: {e}") from e
125
139
 
126
140
 
127
- def _get_or_create_event_loop() -> asyncio.AbstractEventLoop:
128
- """Get the running event loop or create a new one."""
141
+ def _run_async(coro):
142
+ """Run a coroutine synchronously and close its owned event loop."""
129
143
  try:
130
- return asyncio.get_running_loop()
144
+ asyncio.get_running_loop()
131
145
  except RuntimeError:
132
- loop = asyncio.new_event_loop()
133
- asyncio.set_event_loop(loop)
134
- return loop
135
-
136
-
137
- def _run_async(coro):
138
- """Run a coroutine synchronously."""
139
- loop = _get_or_create_event_loop()
140
- if loop.is_running():
141
- # Already inside an async context — can't use run_until_complete.
142
- # Create a new loop in a thread.
146
+ pass
147
+ else:
148
+ # A caller's running loop stays on its own thread and remains open.
143
149
  import concurrent.futures
144
150
 
145
151
  with concurrent.futures.ThreadPoolExecutor(max_workers=1) as pool:
146
152
  return pool.submit(asyncio.run, coro).result()
147
- return loop.run_until_complete(coro)
153
+ return asyncio.run(coro)
148
154
 
149
155
 
150
156
  def _drain_async_gen(agen, emit: Callable[[bytes], None]) -> None:
@@ -157,6 +163,7 @@ def _drain_async_gen(agen, emit: Callable[[bytes], None]) -> None:
157
163
  _run_async(_drain())
158
164
 
159
165
 
166
+ @_isolated_context
160
167
  def process_batches(
161
168
  ipc_bytes: bytes,
162
169
  handler: Callable[..., Any],
@@ -210,6 +217,7 @@ def _concat_batches(batches: list[pa.RecordBatch]) -> pa.RecordBatch:
210
217
  return pa.Table.from_batches(batches).combine_chunks().to_batches()[0]
211
218
 
212
219
 
220
+ @_isolated_context
213
221
  def process_batches_coalesced(
214
222
  items_ipc_bytes: list[bytes],
215
223
  handler: Callable[..., Any],
@@ -292,6 +300,7 @@ def process_batches_coalesced(
292
300
  return output
293
301
 
294
302
 
303
+ @_isolated_context
295
304
  def process_batches_coalesced_combined(
296
305
  items_ipc_bytes: list[bytes],
297
306
  handler: Callable[..., Any],
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: chalk-remote-call-python
3
- Version: 1.10.9
3
+ Version: 1.10.11
4
4
  Summary: Chalk remote call Python runtime interface client
5
5
  Author: Chalk AI, Inc.
6
6
  Project-URL: Homepage, https://chalk.ai
@@ -186,6 +186,18 @@ def handler(event, context):
186
186
  serve(handler=handler, port=8080)
187
187
  ```
188
188
 
189
+ ### Invocation context
190
+
191
+ Each Python bridge invocation runs in a fresh `contextvars.Context`. Handler
192
+ changes to context variables stay within that invocation, including across
193
+ awaits and generator iteration, and are discarded on return or error. Incoming
194
+ request metadata still supplies the tracing parent. A coalesced batch has one
195
+ invocation context for the whole batch.
196
+
197
+ Workers retain their Python thread state for compatibility with native
198
+ extensions. This context boundary does not reset process globals or
199
+ `threading.local()` storage, whose lifetime follows the worker thread.
200
+
189
201
  ## Local Testing
190
202
 
191
203
  Use `grpcurl` to verify the server is running:
@@ -1 +0,0 @@
1
- __version__ = "1.10.9"