chalk-remote-call-python 1.8.1__tar.gz → 1.8.2__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 (66) hide show
  1. {chalk_remote_call_python-1.8.1/chalk_remote_call_python.egg-info → chalk_remote_call_python-1.8.2}/PKG-INFO +1 -1
  2. {chalk_remote_call_python-1.8.1 → chalk_remote_call_python-1.8.2}/chalk-remote-call-rs/Cargo.lock +19 -19
  3. {chalk_remote_call_python-1.8.1 → chalk_remote_call_python-1.8.2}/chalk-remote-call-rs/chalk-remote-call-server/Cargo.toml +3 -3
  4. {chalk_remote_call_python-1.8.1 → chalk_remote_call_python-1.8.2}/chalk-remote-call-rs/chalk-remote-call-server/src/async_service.rs +15 -2
  5. {chalk_remote_call_python-1.8.1 → chalk_remote_call_python-1.8.2}/chalk-remote-call-rs/chalk-remote-call-server/src/coalesce.rs +60 -3
  6. {chalk_remote_call_python-1.8.1 → chalk_remote_call_python-1.8.2}/chalk-remote-call-rs/chalk-remote-call-server/src/lib.rs +29 -16
  7. {chalk_remote_call_python-1.8.1 → chalk_remote_call_python-1.8.2}/chalk-remote-call-rs/chalk-remote-call-server/src/metrics.rs +6 -4
  8. {chalk_remote_call_python-1.8.1 → chalk_remote_call_python-1.8.2}/chalk-remote-call-rs/chalk-remote-call-server/src/self_consumer.rs +63 -15
  9. {chalk_remote_call_python-1.8.1 → chalk_remote_call_python-1.8.2}/chalk-remote-call-rs/chalk-remote-call-server/src/server.rs +24 -8
  10. {chalk_remote_call_python-1.8.1 → chalk_remote_call_python-1.8.2}/chalk-remote-call-rs/chalk-remote-call-server/src/service.rs +37 -2
  11. chalk_remote_call_python-1.8.2/chalk_remote_call/_version.py +1 -0
  12. {chalk_remote_call_python-1.8.1 → chalk_remote_call_python-1.8.2/chalk_remote_call_python.egg-info}/PKG-INFO +1 -1
  13. chalk_remote_call_python-1.8.1/chalk_remote_call/_version.py +0 -1
  14. {chalk_remote_call_python-1.8.1 → chalk_remote_call_python-1.8.2}/MANIFEST.in +0 -0
  15. {chalk_remote_call_python-1.8.1 → chalk_remote_call_python-1.8.2}/README.md +0 -0
  16. {chalk_remote_call_python-1.8.1 → chalk_remote_call_python-1.8.2}/chalk-remote-call-rs/Cargo.toml +0 -0
  17. {chalk_remote_call_python-1.8.1 → chalk_remote_call_python-1.8.2}/chalk-remote-call-rs/chalk-remote-call-proto/Cargo.toml +0 -0
  18. {chalk_remote_call_python-1.8.1 → chalk_remote_call_python-1.8.2}/chalk-remote-call-rs/chalk-remote-call-proto/src/gen/chalk.auth.v1.rs +0 -0
  19. {chalk_remote_call_python-1.8.1 → chalk_remote_call_python-1.8.2}/chalk-remote-call-rs/chalk-remote-call-proto/src/gen/chalk.common.v1.rs +0 -0
  20. {chalk_remote_call_python-1.8.1 → chalk_remote_call_python-1.8.2}/chalk-remote-call-rs/chalk-remote-call-proto/src/gen/chalk.runtime.v1.rs +0 -0
  21. {chalk_remote_call_python-1.8.1 → chalk_remote_call_python-1.8.2}/chalk-remote-call-rs/chalk-remote-call-proto/src/gen/chalk.runtime.v1.tonic.rs +0 -0
  22. {chalk_remote_call_python-1.8.1 → chalk_remote_call_python-1.8.2}/chalk-remote-call-rs/chalk-remote-call-proto/src/gen/chalk.utils.v1.rs +0 -0
  23. {chalk_remote_call_python-1.8.1 → chalk_remote_call_python-1.8.2}/chalk-remote-call-rs/chalk-remote-call-proto/src/gen/descriptor.bin +0 -0
  24. {chalk_remote_call_python-1.8.1 → chalk_remote_call_python-1.8.2}/chalk-remote-call-rs/chalk-remote-call-proto/src/lib.rs +0 -0
  25. {chalk_remote_call_python-1.8.1 → chalk_remote_call_python-1.8.2}/chalk-remote-call-rs/chalk-remote-call-server/src/python_bridge.rs +0 -0
  26. {chalk_remote_call_python-1.8.1 → chalk_remote_call_python-1.8.2}/chalk-remote-call-rs/rust-toolchain.toml +0 -0
  27. {chalk_remote_call_python-1.8.1 → chalk_remote_call_python-1.8.2}/chalk_remote_call/__init__.py +0 -0
  28. {chalk_remote_call_python-1.8.1 → chalk_remote_call_python-1.8.2}/chalk_remote_call/__main__.py +0 -0
  29. {chalk_remote_call_python-1.8.1 → chalk_remote_call_python-1.8.2}/chalk_remote_call/_gen/__init__.py +0 -0
  30. {chalk_remote_call_python-1.8.1 → chalk_remote_call_python-1.8.2}/chalk_remote_call/_gen/chalk/__init__.py +0 -0
  31. {chalk_remote_call_python-1.8.1 → chalk_remote_call_python-1.8.2}/chalk_remote_call/_gen/chalk/auth/__init__.py +0 -0
  32. {chalk_remote_call_python-1.8.1 → chalk_remote_call_python-1.8.2}/chalk_remote_call/_gen/chalk/auth/v1/__init__.py +0 -0
  33. {chalk_remote_call_python-1.8.1 → chalk_remote_call_python-1.8.2}/chalk_remote_call/_gen/chalk/auth/v1/permissions_pb2.py +0 -0
  34. {chalk_remote_call_python-1.8.1 → chalk_remote_call_python-1.8.2}/chalk_remote_call/_gen/chalk/auth/v1/permissions_pb2_grpc.py +0 -0
  35. {chalk_remote_call_python-1.8.1 → chalk_remote_call_python-1.8.2}/chalk_remote_call/_gen/chalk/common/__init__.py +0 -0
  36. {chalk_remote_call_python-1.8.1 → chalk_remote_call_python-1.8.2}/chalk_remote_call/_gen/chalk/common/v1/__init__.py +0 -0
  37. {chalk_remote_call_python-1.8.1 → chalk_remote_call_python-1.8.2}/chalk_remote_call/_gen/chalk/common/v1/chalk_error_pb2.py +0 -0
  38. {chalk_remote_call_python-1.8.1 → chalk_remote_call_python-1.8.2}/chalk_remote_call/_gen/chalk/common/v1/chalk_error_pb2_grpc.py +0 -0
  39. {chalk_remote_call_python-1.8.1 → chalk_remote_call_python-1.8.2}/chalk_remote_call/_gen/chalk/runtime/__init__.py +0 -0
  40. {chalk_remote_call_python-1.8.1 → chalk_remote_call_python-1.8.2}/chalk_remote_call/_gen/chalk/runtime/v1/__init__.py +0 -0
  41. {chalk_remote_call_python-1.8.1 → chalk_remote_call_python-1.8.2}/chalk_remote_call/_gen/chalk/runtime/v1/remote_python_call_pb2.py +0 -0
  42. {chalk_remote_call_python-1.8.1 → chalk_remote_call_python-1.8.2}/chalk_remote_call/_gen/chalk/runtime/v1/remote_python_call_pb2_grpc.py +0 -0
  43. {chalk_remote_call_python-1.8.1 → chalk_remote_call_python-1.8.2}/chalk_remote_call/_gen/chalk/utils/__init__.py +0 -0
  44. {chalk_remote_call_python-1.8.1 → chalk_remote_call_python-1.8.2}/chalk_remote_call/_gen/chalk/utils/v1/__init__.py +0 -0
  45. {chalk_remote_call_python-1.8.1 → chalk_remote_call_python-1.8.2}/chalk_remote_call/_gen/chalk/utils/v1/encoding_pb2.py +0 -0
  46. {chalk_remote_call_python-1.8.1 → chalk_remote_call_python-1.8.2}/chalk_remote_call/_gen/chalk/utils/v1/encoding_pb2_grpc.py +0 -0
  47. {chalk_remote_call_python-1.8.1 → chalk_remote_call_python-1.8.2}/chalk_remote_call/_gen/chalk/utils/v1/field_change_pb2.py +0 -0
  48. {chalk_remote_call_python-1.8.1 → chalk_remote_call_python-1.8.2}/chalk_remote_call/_gen/chalk/utils/v1/field_change_pb2_grpc.py +0 -0
  49. {chalk_remote_call_python-1.8.1 → chalk_remote_call_python-1.8.2}/chalk_remote_call/_gen/chalk/utils/v1/sensitive_pb2.py +0 -0
  50. {chalk_remote_call_python-1.8.1 → chalk_remote_call_python-1.8.2}/chalk_remote_call/_gen/chalk/utils/v1/sensitive_pb2_grpc.py +0 -0
  51. {chalk_remote_call_python-1.8.1 → chalk_remote_call_python-1.8.2}/chalk_remote_call/_native.pyi +0 -0
  52. {chalk_remote_call_python-1.8.1 → chalk_remote_call_python-1.8.2}/chalk_remote_call/arrow_utils.py +0 -0
  53. {chalk_remote_call_python-1.8.1 → chalk_remote_call_python-1.8.2}/chalk_remote_call/cli.py +0 -0
  54. {chalk_remote_call_python-1.8.1 → chalk_remote_call_python-1.8.2}/chalk_remote_call/handler_loader.py +0 -0
  55. {chalk_remote_call_python-1.8.1 → chalk_remote_call_python-1.8.2}/chalk_remote_call/input_transform.py +0 -0
  56. {chalk_remote_call_python-1.8.1 → chalk_remote_call_python-1.8.2}/chalk_remote_call/server.py +0 -0
  57. {chalk_remote_call_python-1.8.1 → chalk_remote_call_python-1.8.2}/chalk_remote_call/servicer.py +0 -0
  58. {chalk_remote_call_python-1.8.1 → chalk_remote_call_python-1.8.2}/chalk_remote_call/tracing.py +0 -0
  59. {chalk_remote_call_python-1.8.1 → chalk_remote_call_python-1.8.2}/chalk_remote_call_python.egg-info/SOURCES.txt +0 -0
  60. {chalk_remote_call_python-1.8.1 → chalk_remote_call_python-1.8.2}/chalk_remote_call_python.egg-info/dependency_links.txt +0 -0
  61. {chalk_remote_call_python-1.8.1 → chalk_remote_call_python-1.8.2}/chalk_remote_call_python.egg-info/entry_points.txt +0 -0
  62. {chalk_remote_call_python-1.8.1 → chalk_remote_call_python-1.8.2}/chalk_remote_call_python.egg-info/requires.txt +0 -0
  63. {chalk_remote_call_python-1.8.1 → chalk_remote_call_python-1.8.2}/chalk_remote_call_python.egg-info/top_level.txt +0 -0
  64. {chalk_remote_call_python-1.8.1 → chalk_remote_call_python-1.8.2}/pyproject.toml +0 -0
  65. {chalk_remote_call_python-1.8.1 → chalk_remote_call_python-1.8.2}/setup.cfg +0 -0
  66. {chalk_remote_call_python-1.8.1 → chalk_remote_call_python-1.8.2}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: chalk-remote-call-python
3
- Version: 1.8.1
3
+ Version: 1.8.2
4
4
  Summary: Chalk remote call Python runtime interface client
5
5
  Author: Chalk AI, Inc.
6
6
  Project-URL: Homepage, https://chalk.ai
@@ -483,8 +483,8 @@ dependencies = [
483
483
 
484
484
  [[package]]
485
485
  name = "chalk-core"
486
- version = "0.1.0"
487
- source = "git+https://github.com/chalk-ai/chalk-private.git?rev=44c26fd738fabd7e2223854618d1f9ccb1b08a71#44c26fd738fabd7e2223854618d1f9ccb1b08a71"
486
+ version = "0.0.0"
487
+ source = "git+https://github.com/chalk-ai/chalk-private.git?rev=ae8e792f746f77253f682ee0c56b246cfdd88f51#ae8e792f746f77253f682ee0c56b246cfdd88f51"
488
488
  dependencies = [
489
489
  "anyhow",
490
490
  "envconfig",
@@ -498,8 +498,8 @@ dependencies = [
498
498
 
499
499
  [[package]]
500
500
  name = "chalk-protos"
501
- version = "0.1.0"
502
- source = "git+https://github.com/chalk-ai/chalk-private.git?rev=44c26fd738fabd7e2223854618d1f9ccb1b08a71#44c26fd738fabd7e2223854618d1f9ccb1b08a71"
501
+ version = "0.0.0"
502
+ source = "git+https://github.com/chalk-ai/chalk-private.git?rev=ae8e792f746f77253f682ee0c56b246cfdd88f51#ae8e792f746f77253f682ee0c56b246cfdd88f51"
503
503
  dependencies = [
504
504
  "prost 0.11.9",
505
505
  "prost-build",
@@ -510,8 +510,8 @@ dependencies = [
510
510
 
511
511
  [[package]]
512
512
  name = "chalk-queue"
513
- version = "0.1.0"
514
- source = "git+https://github.com/chalk-ai/chalk-private.git?rev=44c26fd738fabd7e2223854618d1f9ccb1b08a71#44c26fd738fabd7e2223854618d1f9ccb1b08a71"
513
+ version = "0.0.0"
514
+ source = "git+https://github.com/chalk-ai/chalk-private.git?rev=ae8e792f746f77253f682ee0c56b246cfdd88f51#ae8e792f746f77253f682ee0c56b246cfdd88f51"
515
515
  dependencies = [
516
516
  "base64 0.22.1",
517
517
  "redis",
@@ -559,8 +559,8 @@ dependencies = [
559
559
 
560
560
  [[package]]
561
561
  name = "chalk_metric_definitions"
562
- version = "0.1.0"
563
- source = "git+https://github.com/chalk-ai/chalk-private.git?rev=44c26fd738fabd7e2223854618d1f9ccb1b08a71#44c26fd738fabd7e2223854618d1f9ccb1b08a71"
562
+ version = "0.0.0"
563
+ source = "git+https://github.com/chalk-ai/chalk-private.git?rev=ae8e792f746f77253f682ee0c56b246cfdd88f51#ae8e792f746f77253f682ee0c56b246cfdd88f51"
564
564
  dependencies = [
565
565
  "chalk-protos",
566
566
  "metrics-generator",
@@ -569,8 +569,8 @@ dependencies = [
569
569
 
570
570
  [[package]]
571
571
  name = "chalk_metrics"
572
- version = "0.1.0"
573
- source = "git+https://github.com/chalk-ai/chalk-private.git?rev=44c26fd738fabd7e2223854618d1f9ccb1b08a71#44c26fd738fabd7e2223854618d1f9ccb1b08a71"
572
+ version = "0.0.0"
573
+ source = "git+https://github.com/chalk-ai/chalk-private.git?rev=ae8e792f746f77253f682ee0c56b246cfdd88f51#ae8e792f746f77253f682ee0c56b246cfdd88f51"
574
574
  dependencies = [
575
575
  "async-trait",
576
576
  "chalk-core",
@@ -603,8 +603,8 @@ dependencies = [
603
603
 
604
604
  [[package]]
605
605
  name = "chalk_statsd"
606
- version = "0.1.0"
607
- source = "git+https://github.com/chalk-ai/chalk-private.git?rev=44c26fd738fabd7e2223854618d1f9ccb1b08a71#44c26fd738fabd7e2223854618d1f9ccb1b08a71"
606
+ version = "0.0.0"
607
+ source = "git+https://github.com/chalk-ai/chalk-private.git?rev=ae8e792f746f77253f682ee0c56b246cfdd88f51#ae8e792f746f77253f682ee0c56b246cfdd88f51"
608
608
  dependencies = [
609
609
  "chalk-core",
610
610
  "chrono",
@@ -874,7 +874,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
874
874
  checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
875
875
  dependencies = [
876
876
  "libc",
877
- "windows-sys 0.52.0",
877
+ "windows-sys 0.61.2",
878
878
  ]
879
879
 
880
880
  [[package]]
@@ -1472,7 +1472,7 @@ dependencies = [
1472
1472
  "libc",
1473
1473
  "percent-encoding",
1474
1474
  "pin-project-lite",
1475
- "socket2 0.5.10",
1475
+ "socket2 0.6.3",
1476
1476
  "tokio",
1477
1477
  "tower-service",
1478
1478
  "tracing",
@@ -1867,7 +1867,7 @@ dependencies = [
1867
1867
  [[package]]
1868
1868
  name = "metrics-generator"
1869
1869
  version = "0.1.0"
1870
- source = "git+https://github.com/chalk-ai/chalk-private.git?rev=44c26fd738fabd7e2223854618d1f9ccb1b08a71#44c26fd738fabd7e2223854618d1f9ccb1b08a71"
1870
+ source = "git+https://github.com/chalk-ai/chalk-private.git?rev=ae8e792f746f77253f682ee0c56b246cfdd88f51#ae8e792f746f77253f682ee0c56b246cfdd88f51"
1871
1871
  dependencies = [
1872
1872
  "codegen",
1873
1873
  "serde",
@@ -2100,7 +2100,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
2100
2100
  checksum = "7d8fae84b431384b68627d0f9b3b1245fcf9f46f6c0e3dc902e9dce64edd1967"
2101
2101
  dependencies = [
2102
2102
  "libc",
2103
- "windows-sys 0.52.0",
2103
+ "windows-sys 0.61.2",
2104
2104
  ]
2105
2105
 
2106
2106
  [[package]]
@@ -2761,7 +2761,7 @@ dependencies = [
2761
2761
  "errno",
2762
2762
  "libc",
2763
2763
  "linux-raw-sys 0.12.1",
2764
- "windows-sys 0.52.0",
2764
+ "windows-sys 0.61.2",
2765
2765
  ]
2766
2766
 
2767
2767
  [[package]]
@@ -3128,10 +3128,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
3128
3128
  checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd"
3129
3129
  dependencies = [
3130
3130
  "fastrand",
3131
- "getrandom 0.3.4",
3131
+ "getrandom 0.4.2",
3132
3132
  "once_cell",
3133
3133
  "rustix 1.1.4",
3134
- "windows-sys 0.52.0",
3134
+ "windows-sys 0.61.2",
3135
3135
  ]
3136
3136
 
3137
3137
  [[package]]
@@ -36,6 +36,6 @@ futures-util = "0.3"
36
36
  # `[patch.crates-io]` here it builds against vanilla crates.io redis (it only
37
37
  # uses standard APIs). Same rev across all three so cargo reuses one checkout.
38
38
  [target.'cfg(target_os = "linux")'.dependencies]
39
- chalk-queue = { git = "https://github.com/chalk-ai/chalk-private.git", rev = "44c26fd738fabd7e2223854618d1f9ccb1b08a71" }
40
- chalk_metrics = { git = "https://github.com/chalk-ai/chalk-private.git", rev = "44c26fd738fabd7e2223854618d1f9ccb1b08a71" }
41
- chalk_statsd = { git = "https://github.com/chalk-ai/chalk-private.git", rev = "44c26fd738fabd7e2223854618d1f9ccb1b08a71" }
39
+ chalk-queue = { git = "https://github.com/chalk-ai/chalk-private.git", rev = "ae8e792f746f77253f682ee0c56b246cfdd88f51" }
40
+ chalk_metrics = { git = "https://github.com/chalk-ai/chalk-private.git", rev = "ae8e792f746f77253f682ee0c56b246cfdd88f51" }
41
+ chalk_statsd = { git = "https://github.com/chalk-ai/chalk-private.git", rev = "ae8e792f746f77253f682ee0c56b246cfdd88f51" }
@@ -10,7 +10,7 @@ use chalk_remote_call_proto::chalk::runtime::v1::{
10
10
  PollRemoteCallResponse, PurgeQueueRequest, PurgeQueueResponse, RemoteCallStatus,
11
11
  };
12
12
  use tonic::{Request, Response, Status};
13
- use tracing::{debug, error, info, instrument};
13
+ use tracing::{debug, error, info, instrument, warn};
14
14
 
15
15
  use crate::python_bridge::{ChunkBuffer, PythonHandler};
16
16
  use crate::service::extract_metadata;
@@ -87,10 +87,15 @@ pub struct AsyncRemoteCallServiceImpl {
87
87
  /// the per-call dispatch does not satisfy, so async enqueue is refused
88
88
  /// rather than silently calling the handler with the wrong shape.
89
89
  batching_enabled: bool,
90
+ is_remote_function: bool,
90
91
  }
91
92
 
92
93
  impl AsyncRemoteCallServiceImpl {
93
- pub fn new(python_handler: Arc<PythonHandler>, batching_enabled: bool) -> Self {
94
+ pub fn new(
95
+ python_handler: Arc<PythonHandler>,
96
+ batching_enabled: bool,
97
+ is_remote_function: bool,
98
+ ) -> Self {
94
99
  let registry: Registry = Arc::new(Mutex::new(HashMap::new()));
95
100
  // Runs inside the server's tokio runtime (the service is constructed
96
101
  // within `run_server`); reclaims orphaned terminal entries.
@@ -100,6 +105,7 @@ impl AsyncRemoteCallServiceImpl {
100
105
  registry,
101
106
  next_id: AtomicU64::new(1),
102
107
  batching_enabled,
108
+ is_remote_function,
103
109
  }
104
110
  }
105
111
  }
@@ -125,6 +131,13 @@ impl AsyncRemoteCallService for AsyncRemoteCallServiceImpl {
125
131
  let req = request.into_inner();
126
132
  let function_name = req.name;
127
133
 
134
+ if self.is_remote_function {
135
+ warn!(
136
+ function_name = %function_name,
137
+ "this enqueue is not fronted by the fnq server (CHALK_REMOTE_FUNCTION is set to true)"
138
+ );
139
+ }
140
+
128
141
  // Only inline feather bytes are supported today; the object-store
129
142
  // variant is reserved for large payloads and not wired up here.
130
143
  let ipc_bytes = match req.args.and_then(|a| a.args) {
@@ -13,6 +13,8 @@ use tokio::task::JoinHandle;
13
13
  use tonic::Status;
14
14
  use tracing::error;
15
15
 
16
+ #[cfg(target_os = "linux")]
17
+ use chalk_metrics::PublishingMetricsPipeline;
16
18
  use chalk_remote_call_proto::chalk::runtime::v1::CallFunctionResponse;
17
19
 
18
20
  use crate::python_bridge::{CallerInput, PythonHandler};
@@ -35,10 +37,17 @@ pub struct CoalescingQueue {
35
37
  max_size: usize,
36
38
  max_duration: Duration,
37
39
  state: Mutex<QueueState>,
40
+ #[cfg(target_os = "linux")]
41
+ pipeline: Option<Arc<PublishingMetricsPipeline>>,
38
42
  }
39
43
 
40
44
  impl CoalescingQueue {
41
- pub fn new(handler: Arc<PythonHandler>, max_size: usize, max_duration_ms: u64) -> Arc<Self> {
45
+ pub fn new(
46
+ handler: Arc<PythonHandler>,
47
+ max_size: usize,
48
+ max_duration_ms: u64,
49
+ #[cfg(target_os = "linux")] pipeline: Option<Arc<PublishingMetricsPipeline>>,
50
+ ) -> Arc<Self> {
42
51
  Arc::new(Self {
43
52
  handler,
44
53
  max_size,
@@ -47,6 +56,8 @@ impl CoalescingQueue {
47
56
  items: Vec::new(),
48
57
  flush_task: None,
49
58
  }),
59
+ #[cfg(target_os = "linux")]
60
+ pipeline,
50
61
  })
51
62
  }
52
63
 
@@ -90,17 +101,33 @@ impl CoalescingQueue {
90
101
  // Dispatch off the queue's critical section — don't block further
91
102
  // submissions while Python runs.
92
103
  let handler = Arc::clone(&self.handler);
104
+ #[cfg(target_os = "linux")]
105
+ let pipeline = self.pipeline.clone();
93
106
  tokio::spawn(async move {
94
- Self::dispatch(handler, items).await;
107
+ Self::dispatch(
108
+ handler,
109
+ items,
110
+ #[cfg(target_os = "linux")]
111
+ pipeline,
112
+ )
113
+ .await;
95
114
  });
96
115
  }
97
116
 
98
- async fn dispatch(handler: Arc<PythonHandler>, items: Vec<BufferedCall>) {
117
+ async fn dispatch(
118
+ handler: Arc<PythonHandler>,
119
+ items: Vec<BufferedCall>,
120
+ #[cfg(target_os = "linux")] pipeline: Option<Arc<PublishingMetricsPipeline>>,
121
+ ) {
99
122
  // Split each BufferedCall into its input (for the bridge) and its
100
123
  // response channel (for routing the reply back).
101
124
  let n = items.len();
102
125
  let mut callers: Vec<CallerInput> = Vec::with_capacity(n);
103
126
  let mut response_txs = Vec::with_capacity(n);
127
+ #[cfg(target_os = "linux")]
128
+ let function_name = items[0].input.function_name.clone();
129
+ #[cfg(target_os = "linux")]
130
+ let started = std::time::Instant::now();
104
131
  for item in items {
105
132
  callers.push(item.input);
106
133
  response_txs.push(item.response_tx);
@@ -116,11 +143,31 @@ impl CoalescingQueue {
116
143
  n
117
144
  );
118
145
  error!("{}", msg);
146
+ #[cfg(target_os = "linux")]
147
+ if let Some(p) = &pipeline {
148
+ crate::metrics::record_completed_call(
149
+ p,
150
+ &function_name,
151
+ /* success = */ false,
152
+ started.elapsed(),
153
+ chalk_metrics::metrics::tags::Mode::Sync,
154
+ );
155
+ }
119
156
  for tx in &response_txs {
120
157
  let _ = tx.send(Err(Status::unknown(msg.clone()))).await;
121
158
  }
122
159
  return;
123
160
  }
161
+ #[cfg(target_os = "linux")]
162
+ if let Some(p) = &pipeline {
163
+ crate::metrics::record_completed_call(
164
+ p,
165
+ &function_name,
166
+ /* success = */ true,
167
+ started.elapsed(),
168
+ chalk_metrics::metrics::tags::Mode::Sync,
169
+ );
170
+ }
124
171
  for (tx, chunk) in response_txs.into_iter().zip(per_caller_bytes) {
125
172
  let msg = CallFunctionResponse {
126
173
  feather_stream: chunk.into(),
@@ -132,6 +179,16 @@ impl CoalescingQueue {
132
179
  error!("Coalesced handler error: {}", e);
133
180
  // IPC decode errors are already caught by the service's
134
181
  // pre-validation; anything reaching here is a handler error.
182
+ #[cfg(target_os = "linux")]
183
+ if let Some(p) = &pipeline {
184
+ crate::metrics::record_completed_call(
185
+ p,
186
+ &function_name,
187
+ /* success = */ false,
188
+ started.elapsed(),
189
+ chalk_metrics::metrics::tags::Mode::Sync,
190
+ );
191
+ }
135
192
  let status =
136
193
  Status::unknown(format!("Exception raised during handler execution: {e}"));
137
194
  for tx in response_txs {
@@ -53,16 +53,6 @@ fn start_server(
53
53
 
54
54
  let python_handler = Arc::new(PythonHandler::new(handler, process_fn, arg_names));
55
55
 
56
- let coalescing_queue = if max_batching_size > 0 {
57
- Some(CoalescingQueue::new(
58
- Arc::clone(&python_handler),
59
- max_batching_size,
60
- max_buffer_duration_ms,
61
- ))
62
- } else {
63
- None
64
- };
65
-
66
56
  // Release the GIL while the Rust server runs
67
57
  py.detach(|| {
68
58
  let rt = tokio::runtime::Builder::new_multi_thread()
@@ -75,12 +65,35 @@ fn start_server(
75
65
  ))
76
66
  })?;
77
67
 
78
- rt.block_on(server::run_server(
79
- host,
80
- port,
81
- python_handler,
82
- coalescing_queue,
83
- ))
68
+ rt.block_on(async {
69
+ // Linux-only: the self-consumer + its metrics pipeline depend on
70
+ // chalk-queue / chalk_metrics, since these don't compile on macos
71
+ // and windows. Built inside the runtime since it needs to `.await`.
72
+ #[cfg(target_os = "linux")]
73
+ let pipeline = crate::metrics::init_pipeline().await;
74
+
75
+ let coalescing_queue = if max_batching_size > 0 {
76
+ Some(CoalescingQueue::new(
77
+ Arc::clone(&python_handler),
78
+ max_batching_size,
79
+ max_buffer_duration_ms,
80
+ #[cfg(target_os = "linux")]
81
+ pipeline.clone(),
82
+ ))
83
+ } else {
84
+ None
85
+ };
86
+
87
+ server::run_server(
88
+ host,
89
+ port,
90
+ python_handler,
91
+ coalescing_queue,
92
+ #[cfg(target_os = "linux")]
93
+ pipeline,
94
+ )
95
+ .await
96
+ })
84
97
  .map_err(|e| pyo3::exceptions::PyRuntimeError::new_err(format!("Server error: {e}")))
85
98
  })
86
99
  }
@@ -10,7 +10,7 @@
10
10
  use std::sync::Arc;
11
11
  use std::time::Duration;
12
12
 
13
- use chalk_metrics::metrics::tags::{FunctionName, Status as MetricStatus, TagValue};
13
+ use chalk_metrics::metrics::tags::{FunctionName, Mode, Status as MetricStatus, TagValue};
14
14
  use chalk_metrics::metrics::well_known_metrics::WellKnownMetricName;
15
15
  use chalk_metrics::{
16
16
  make_pubsub_publisher, BatchConfig, BusPublisher, MetricsPipeline, PublishingMetricsPipeline,
@@ -30,7 +30,7 @@ const BATCH_MAX_LATENCY: Duration = Duration::from_millis(100);
30
30
  /// The bus publisher is what reaches the metrics store (and thus the dashboard);
31
31
  /// statsd alone only reaches Datadog. An empty `METRICS_BUS_TOPIC` therefore
32
32
  /// means the dashboard won't move — surfaced as a warning, not an error.
33
- pub async fn init_pipeline() -> Option<Arc<dyn MetricsPipeline>> {
33
+ pub async fn init_pipeline() -> Option<Arc<PublishingMetricsPipeline>> {
34
34
  let environment_id = std::env::var("CHALK_ENVIRONMENT_ID").unwrap_or_default();
35
35
 
36
36
  let statsd = Arc::new(
@@ -45,7 +45,7 @@ pub async fn init_pipeline() -> Option<Arc<dyn MetricsPipeline>> {
45
45
  warn!("no metrics bus publisher configured; function call metrics will not reach the dashboard");
46
46
  }
47
47
 
48
- let metrics_pipeline: Arc<dyn MetricsPipeline> =
48
+ let metrics_pipeline: Arc<PublishingMetricsPipeline> =
49
49
  Arc::new(PublishingMetricsPipeline::new_with_env_var_defaults(
50
50
  environment_id,
51
51
  String::new(),
@@ -111,10 +111,11 @@ async fn build_bus_publisher() -> Option<Arc<dyn BusPublisher>> {
111
111
  /// carry the scaling-group revision tag used by the legacy catalog consumer;
112
112
  /// the dashboard filters by function name.
113
113
  pub fn record_completed_call(
114
- pipeline: &Arc<dyn MetricsPipeline>,
114
+ pipeline: &Arc<PublishingMetricsPipeline>,
115
115
  function_name: &str,
116
116
  success: bool,
117
117
  elapsed: Duration,
118
+ mode: Mode,
118
119
  ) {
119
120
  let status = if success {
120
121
  MetricStatus::Success
@@ -124,6 +125,7 @@ pub fn record_completed_call(
124
125
  let tags = vec![
125
126
  TagValue::FunctionName(FunctionName(function_name.to_string())),
126
127
  TagValue::Status(status.clone()),
128
+ TagValue::Mode(mode.clone()),
127
129
  ];
128
130
 
129
131
  if let Err(e) = pipeline.count(WellKnownMetricName::FunctionCallDequeued, 1.0, tags.clone()) {
@@ -28,6 +28,7 @@
28
28
  //! caller. The semaphore still admits one slot per call, so it remains the
29
29
  //! producer of the concurrency the coalescer batches.
30
30
 
31
+ use std::collections::HashMap;
31
32
  use std::panic::AssertUnwindSafe;
32
33
  use std::sync::{Arc, Mutex};
33
34
  use std::time::{Duration, Instant};
@@ -44,7 +45,8 @@ use tokio::sync::mpsc;
44
45
  use tracing::{error, info, warn};
45
46
  use uuid::Uuid;
46
47
 
47
- use chalk_metrics::MetricsPipeline;
48
+ use chalk_metrics::metrics::tags::Mode;
49
+ use chalk_metrics::PublishingMetricsPipeline;
48
50
 
49
51
  use crate::coalesce::{BufferedCall, CoalescingQueue};
50
52
  use crate::python_bridge::{CallerInput, ChunkBuffer, PythonHandler};
@@ -186,7 +188,7 @@ type LiveTokens = Arc<DashSet<String>>;
186
188
  pub async fn run(
187
189
  config: SelfConsumerConfig,
188
190
  handler: Arc<PythonHandler>,
189
- metrics_pipeline: Option<Arc<dyn MetricsPipeline>>,
191
+ metrics_pipeline: Option<Arc<PublishingMetricsPipeline>>,
190
192
  coalescing_queue: Option<Arc<CoalescingQueue>>,
191
193
  ) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
192
194
  let client = Client::open(config.redis_url.clone())?;
@@ -310,7 +312,7 @@ async fn run_one_call(
310
312
  lease: SemaphoreLease,
311
313
  live_tokens: LiveTokens,
312
314
  flush_timeout: Duration,
313
- metrics_pipeline: Option<Arc<dyn MetricsPipeline>>,
315
+ metrics_pipeline: Option<Arc<PublishingMetricsPipeline>>,
314
316
  ) {
315
317
  let call_id = work.call_id.clone();
316
318
  match AssertUnwindSafe(execute_and_write(
@@ -362,7 +364,7 @@ async fn run_one_coalesced_call(
362
364
  work: QueuedCall,
363
365
  lease: SemaphoreLease,
364
366
  live_tokens: LiveTokens,
365
- metrics_pipeline: Option<Arc<dyn MetricsPipeline>>,
367
+ metrics_pipeline: Option<Arc<PublishingMetricsPipeline>>,
366
368
  ) {
367
369
  let call_id = work.call_id.clone();
368
370
  if let Err(e) = coalesced_execute_and_write(
@@ -397,13 +399,14 @@ async fn coalesced_execute_and_write(
397
399
  queue: &FunctionQueue,
398
400
  conn: &mut ConnectionManager,
399
401
  work: QueuedCall,
400
- metrics_pipeline: Option<&Arc<dyn MetricsPipeline>>,
402
+ metrics_pipeline: Option<&Arc<PublishingMetricsPipeline>>,
401
403
  ) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
402
404
  let call_uuid = Uuid::parse_str(&work.call_id)?;
403
405
  let stream_key = queue.stream_key_for(call_uuid);
404
406
  let ipc_bytes = work.call.feather_bytes()?;
405
407
  let function_name = work.call.name.clone();
406
- let metadata = work.metadata.otel_headers.clone();
408
+ let mut metadata = work.metadata.otel_headers.clone();
409
+ let processing_trace_id = ensure_traceparent(&mut metadata);
407
410
  let started = Instant::now();
408
411
 
409
412
  let _ = queue.update_status(call_uuid, "running").await;
@@ -430,7 +433,13 @@ async fn coalesced_execute_and_write(
430
433
  // stream writes below — parity with the streaming path.
431
434
  let success = matches!(response, Some(Ok(_)));
432
435
  if let Some(p) = metrics_pipeline {
433
- crate::metrics::record_completed_call(p, &function_name, success, started.elapsed());
436
+ crate::metrics::record_completed_call(
437
+ p,
438
+ &function_name,
439
+ success,
440
+ started.elapsed(),
441
+ Mode::Async,
442
+ );
434
443
  }
435
444
 
436
445
  match response {
@@ -438,7 +447,12 @@ async fn coalesced_execute_and_write(
438
447
  stream_writer::write_chunk(conn, &stream_key, 1, &resp.feather_stream).await?;
439
448
  stream_writer::write_end(conn, &stream_key, 2).await?;
440
449
  let _ = queue
441
- .complete_status(call_uuid, "completed", "1 chunk(s)")
450
+ .complete_status(
451
+ call_uuid,
452
+ "completed",
453
+ "1 chunk(s)",
454
+ Some(processing_trace_id),
455
+ )
442
456
  .await;
443
457
  info!(call_id = %work.call_id, "coalesced queued call completed");
444
458
  }
@@ -455,7 +469,9 @@ async fn coalesced_execute_and_write(
455
469
  )
456
470
  .await?;
457
471
  let summary: String = status.message().chars().take(200).collect();
458
- let _ = queue.complete_status(call_uuid, "failed", &summary).await;
472
+ let _ = queue
473
+ .complete_status(call_uuid, "failed", &summary, Some(processing_trace_id))
474
+ .await;
459
475
  error!(call_id = %work.call_id, error = %status, "coalesced queued call failed");
460
476
  }
461
477
  None => {
@@ -465,13 +481,31 @@ async fn coalesced_execute_and_write(
465
481
  let msg = "coalesced dispatch produced no response";
466
482
  stream_writer::write_error(conn, &stream_key, 1, "RemoteFunctionError", msg, None)
467
483
  .await?;
468
- let _ = queue.complete_status(call_uuid, "failed", msg).await;
484
+ let _ = queue
485
+ .complete_status(call_uuid, "failed", msg, Some(processing_trace_id))
486
+ .await;
469
487
  error!(call_id = %work.call_id, "{msg}");
470
488
  }
471
489
  }
472
490
  Ok(())
473
491
  }
474
492
 
493
+ // Insert trace ID into headers if none already present
494
+ fn ensure_traceparent(headers: &mut HashMap<String, String>) -> String {
495
+ if let Some(tp) = headers.get("traceparent") {
496
+ if let Some(trace_id) = tp.split('-').nth(1).filter(|s| s.len() == 32) {
497
+ return trace_id.to_string();
498
+ }
499
+ }
500
+ let trace_id = Uuid::new_v4().simple().to_string();
501
+ let span_id = &Uuid::new_v4().simple().to_string()[..16];
502
+ headers.insert(
503
+ "traceparent".to_string(),
504
+ format!("00-{trace_id}-{span_id}-01"),
505
+ );
506
+ trace_id
507
+ }
508
+
475
509
  /// Decode the payload, invoke the handler, and write the outcome (chunks then
476
510
  /// `end`, or `error`) to the call's result stream, updating meta status along
477
511
  /// the way.
@@ -481,13 +515,14 @@ async fn execute_and_write(
481
515
  conn: &mut ConnectionManager,
482
516
  work: QueuedCall,
483
517
  flush_timeout: Duration,
484
- metrics_pipeline: Option<&Arc<dyn MetricsPipeline>>,
518
+ metrics_pipeline: Option<&Arc<PublishingMetricsPipeline>>,
485
519
  ) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
486
520
  let call_uuid = Uuid::parse_str(&work.call_id)?;
487
521
  let stream_key = queue.stream_key_for(call_uuid);
488
522
  let ipc_bytes = work.call.feather_bytes()?;
489
523
  let function_name = work.call.name.clone();
490
- let metadata = work.metadata.otel_headers.clone();
524
+ let mut metadata = work.metadata.otel_headers.clone();
525
+ let processing_trace_id = ensure_traceparent(&mut metadata);
491
526
  let started = Instant::now();
492
527
 
493
528
  let _ = queue.update_status(call_uuid, "running").await;
@@ -543,7 +578,13 @@ async fn execute_and_write(
543
578
  // so every executed call is recorded regardless of downstream Redis write
544
579
  // failure. Mirrors the catalog consumer's per-call emission.
545
580
  if let Some(p) = metrics_pipeline {
546
- crate::metrics::record_completed_call(p, &function_name, result.is_ok(), started.elapsed());
581
+ crate::metrics::record_completed_call(
582
+ p,
583
+ &function_name,
584
+ result.is_ok(),
585
+ started.elapsed(),
586
+ Mode::Async,
587
+ );
547
588
  }
548
589
 
549
590
  // Flush whatever the handler produced after the loop exits (on the fast path
@@ -558,7 +599,12 @@ async fn execute_and_write(
558
599
  Ok(()) => {
559
600
  stream_writer::write_end(conn, &stream_key, seq).await?;
560
601
  let _ = queue
561
- .complete_status(call_uuid, "completed", &format!("{flushed} chunk(s)"))
602
+ .complete_status(
603
+ call_uuid,
604
+ "completed",
605
+ &format!("{flushed} chunk(s)"),
606
+ Some(processing_trace_id),
607
+ )
562
608
  .await;
563
609
  info!(call_id = %work.call_id, chunks = flushed, "queued call completed");
564
610
  }
@@ -569,7 +615,9 @@ async fn execute_and_write(
569
615
  stream_writer::write_error(conn, &stream_key, seq, "RemoteFunctionError", &e.0, None)
570
616
  .await?;
571
617
  let summary: String = e.0.chars().take(200).collect();
572
- let _ = queue.complete_status(call_uuid, "failed", &summary).await;
618
+ let _ = queue
619
+ .complete_status(call_uuid, "failed", &summary, Some(processing_trace_id))
620
+ .await;
573
621
  error!(call_id = %work.call_id, error = %e, "queued call failed");
574
622
  }
575
623
  }
@@ -1,6 +1,8 @@
1
1
  use std::net::SocketAddr;
2
2
  use std::sync::Arc;
3
3
 
4
+ #[cfg(target_os = "linux")]
5
+ use chalk_metrics::PublishingMetricsPipeline;
4
6
  use chalk_remote_call_proto::chalk::runtime::v1::async_remote_call_service_server::AsyncRemoteCallServiceServer;
5
7
  use chalk_remote_call_proto::chalk::runtime::v1::remote_call_service_server::RemoteCallServiceServer;
6
8
  use chalk_remote_call_proto::chalk::runtime::v1::FILE_DESCRIPTOR_SET;
@@ -14,11 +16,14 @@ use crate::service::RemoteCallServiceImpl;
14
16
 
15
17
  const MAX_MESSAGE_SIZE: usize = 32 * 1024 * 1024; // 32 MB
16
18
 
19
+ const ENV_REMOTE_FUNCTION: &str = "CHALK_REMOTE_FUNCTION";
20
+
17
21
  pub async fn run_server(
18
22
  host: String,
19
23
  port: u16,
20
24
  python_handler: Arc<PythonHandler>,
21
25
  coalescing_queue: Option<Arc<CoalescingQueue>>,
26
+ #[cfg(target_os = "linux")] pipeline: Option<Arc<PublishingMetricsPipeline>>,
22
27
  ) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
23
28
  // Parse host — ensure IPv6 addresses are bracketed for SocketAddr parsing
24
29
  let addr_str = if host.contains(':') && !host.starts_with('[') {
@@ -57,7 +62,14 @@ pub async fn run_server(
57
62
  // coalescing flag before `coalescing_queue` is moved into the streaming
58
63
  // service below; the async path refuses enqueue when batching is on.
59
64
  let batching_enabled = coalescing_queue.is_some();
60
- let async_svc = AsyncRemoteCallServiceImpl::new(python_handler.clone(), batching_enabled);
65
+ // Checks if remote function env var is set or not
66
+ let is_remote_function: bool = std::env::var(ENV_REMOTE_FUNCTION)
67
+ .is_ok_and(|v| v.eq_ignore_ascii_case("true") || v == "1");
68
+ let async_svc = AsyncRemoteCallServiceImpl::new(
69
+ python_handler.clone(),
70
+ batching_enabled,
71
+ is_remote_function,
72
+ );
61
73
 
62
74
  // Self-consume the Redis fn queue when this pod was provisioned with a
63
75
  // Redis URL (gRPC-only otherwise). The self-consumer shares the gRPC
@@ -65,20 +77,22 @@ pub async fn run_server(
65
77
  // inbound gRPC calls feed the same queue so they batch together against the
66
78
  // single batch-size/duration the user configured. When batching is off the
67
79
  // queue is `None` and the self-consumer dispatches per-call (streaming).
68
- //
69
- // Linux-only: the self-consumer + its metrics pipeline depend on chalk-queue
70
- // / chalk_metrics, since these don't compile on macos and windows.
80
+
71
81
  #[cfg(target_os = "linux")]
72
82
  if let Some(cfg) = crate::self_consumer::SelfConsumerConfig::from_env() {
73
83
  // Build the chalk_metrics pipeline once (mirrors the fnq-server/cc
74
84
  // main init) so the self-consumer can emit function-call metrics.
75
- let pipeline = crate::metrics::init_pipeline().await;
76
85
  let consumer_handler = python_handler.clone();
86
+ let consumer_pipeline = pipeline.clone();
77
87
  let consumer_coalescing = coalescing_queue.clone();
78
88
  tokio::spawn(async move {
79
- if let Err(e) =
80
- crate::self_consumer::run(cfg, consumer_handler, pipeline, consumer_coalescing)
81
- .await
89
+ if let Err(e) = crate::self_consumer::run(
90
+ cfg,
91
+ consumer_handler,
92
+ consumer_pipeline,
93
+ consumer_coalescing,
94
+ )
95
+ .await
82
96
  {
83
97
  tracing::error!(error = %e, "fnq self-consumer failed to start");
84
98
  }
@@ -89,6 +103,8 @@ pub async fn run_server(
89
103
  let svc = RemoteCallServiceImpl {
90
104
  python_handler,
91
105
  coalescing_queue,
106
+ #[cfg(target_os = "linux")]
107
+ metrics_pipeline: pipeline,
92
108
  };
93
109
 
94
110
  info!("Server starting on {}", addr);
@@ -1,6 +1,12 @@
1
1
  use std::collections::HashMap;
2
2
  use std::sync::Arc;
3
+ #[cfg(target_os = "linux")]
4
+ use std::time::Instant;
3
5
 
6
+ #[cfg(target_os = "linux")]
7
+ use chalk_metrics::metrics::tags::Mode;
8
+ #[cfg(target_os = "linux")]
9
+ use chalk_metrics::PublishingMetricsPipeline;
4
10
  use chalk_remote_call_proto::chalk::runtime::v1::remote_call_service_server::RemoteCallService;
5
11
  use chalk_remote_call_proto::chalk::runtime::v1::{CallFunctionRequest, CallFunctionResponse};
6
12
  use tokio_stream::wrappers::ReceiverStream;
@@ -18,6 +24,9 @@ pub struct RemoteCallServiceImpl {
18
24
  /// Optional coalescing queue. When `Some`, incoming calls are buffered and
19
25
  /// dispatched as a single batched handler invocation.
20
26
  pub coalescing_queue: Option<Arc<CoalescingQueue>>,
27
+ // Linux-gated metrics pipeline
28
+ #[cfg(target_os = "linux")]
29
+ pub metrics_pipeline: Option<Arc<PublishingMetricsPipeline>>,
21
30
  }
22
31
 
23
32
  #[tonic::async_trait]
@@ -90,14 +99,40 @@ impl RemoteCallService for RemoteCallServiceImpl {
90
99
 
91
100
  // Single-request path.
92
101
  let handler = self.python_handler.clone();
102
+ #[cfg(target_os = "linux")]
103
+ let metrics_pipeline = self.metrics_pipeline.clone();
93
104
  tokio::spawn(async move {
105
+ #[cfg(target_os = "linux")]
106
+ let started = Instant::now();
107
+
94
108
  let error_tx = tx.clone();
95
109
  match handler
96
- .call_streaming(all_bytes, function_name, metadata, peer, tx)
110
+ .call_streaming(all_bytes, function_name.clone(), metadata, peer, tx)
97
111
  .await
98
112
  {
99
- Ok(()) => {}
113
+ Ok(()) => {
114
+ #[cfg(target_os = "linux")]
115
+ if let Some(p) = &metrics_pipeline {
116
+ crate::metrics::record_completed_call(
117
+ p,
118
+ &function_name,
119
+ /* success = */ true,
120
+ started.elapsed(),
121
+ Mode::Sync,
122
+ )
123
+ }
124
+ }
100
125
  Err(e) => {
126
+ #[cfg(target_os = "linux")]
127
+ if let Some(p) = &metrics_pipeline {
128
+ crate::metrics::record_completed_call(
129
+ p,
130
+ &function_name,
131
+ /* success = */ false,
132
+ started.elapsed(),
133
+ Mode::Sync,
134
+ )
135
+ }
101
136
  if error_tx.is_closed() {
102
137
  // The only reason blocking_send fails is a dropped
103
138
  // receiver — the client went away mid-stream. Not a
@@ -0,0 +1 @@
1
+ __version__ = "1.8.2"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: chalk-remote-call-python
3
- Version: 1.8.1
3
+ Version: 1.8.2
4
4
  Summary: Chalk remote call Python runtime interface client
5
5
  Author: Chalk AI, Inc.
6
6
  Project-URL: Homepage, https://chalk.ai
@@ -1 +0,0 @@
1
- __version__ = "1.8.1"