chalk-remote-call-python 1.7.0__tar.gz → 1.7.1__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.
- {chalk_remote_call_python-1.7.0 → chalk_remote_call_python-1.7.1}/PKG-INFO +1 -1
- {chalk_remote_call_python-1.7.0 → chalk_remote_call_python-1.7.1}/chalk-remote-call-rs/chalk-remote-call-proto/src/gen/chalk.auth.v1.rs +9 -0
- {chalk_remote_call_python-1.7.0 → chalk_remote_call_python-1.7.1}/chalk-remote-call-rs/chalk-remote-call-proto/src/gen/chalk.runtime.v1.rs +58 -0
- {chalk_remote_call_python-1.7.0 → chalk_remote_call_python-1.7.1}/chalk-remote-call-rs/chalk-remote-call-proto/src/gen/chalk.runtime.v1.tonic.rs +173 -0
- {chalk_remote_call_python-1.7.0 → chalk_remote_call_python-1.7.1}/chalk-remote-call-rs/chalk-remote-call-proto/src/gen/descriptor.bin +0 -0
- chalk_remote_call_python-1.7.1/chalk-remote-call-rs/chalk-remote-call-server/src/async_service.rs +238 -0
- {chalk_remote_call_python-1.7.0 → chalk_remote_call_python-1.7.1}/chalk-remote-call-rs/chalk-remote-call-server/src/lib.rs +1 -0
- {chalk_remote_call_python-1.7.0 → chalk_remote_call_python-1.7.1}/chalk-remote-call-rs/chalk-remote-call-server/src/python_bridge.rs +81 -8
- {chalk_remote_call_python-1.7.0 → chalk_remote_call_python-1.7.1}/chalk-remote-call-rs/chalk-remote-call-server/src/server.rs +13 -0
- {chalk_remote_call_python-1.7.0 → chalk_remote_call_python-1.7.1}/chalk-remote-call-rs/chalk-remote-call-server/src/service.rs +1 -1
- {chalk_remote_call_python-1.7.0 → chalk_remote_call_python-1.7.1}/chalk_remote_call/_gen/chalk/auth/v1/permissions_pb2.py +9 -3
- chalk_remote_call_python-1.7.1/chalk_remote_call/_gen/chalk/runtime/v1/remote_python_call_pb2.py +80 -0
- {chalk_remote_call_python-1.7.0 → chalk_remote_call_python-1.7.1}/chalk_remote_call/_gen/chalk/runtime/v1/remote_python_call_pb2_grpc.py +68 -0
- chalk_remote_call_python-1.7.1/chalk_remote_call/_version.py +1 -0
- {chalk_remote_call_python-1.7.0 → chalk_remote_call_python-1.7.1}/chalk_remote_call_python.egg-info/PKG-INFO +1 -1
- {chalk_remote_call_python-1.7.0 → chalk_remote_call_python-1.7.1}/chalk_remote_call_python.egg-info/SOURCES.txt +1 -0
- chalk_remote_call_python-1.7.0/chalk_remote_call/_gen/chalk/runtime/v1/remote_python_call_pb2.py +0 -64
- chalk_remote_call_python-1.7.0/chalk_remote_call/_version.py +0 -1
- {chalk_remote_call_python-1.7.0 → chalk_remote_call_python-1.7.1}/MANIFEST.in +0 -0
- {chalk_remote_call_python-1.7.0 → chalk_remote_call_python-1.7.1}/README.md +0 -0
- {chalk_remote_call_python-1.7.0 → chalk_remote_call_python-1.7.1}/chalk-remote-call-rs/Cargo.lock +0 -0
- {chalk_remote_call_python-1.7.0 → chalk_remote_call_python-1.7.1}/chalk-remote-call-rs/Cargo.toml +0 -0
- {chalk_remote_call_python-1.7.0 → chalk_remote_call_python-1.7.1}/chalk-remote-call-rs/chalk-remote-call-proto/Cargo.toml +0 -0
- {chalk_remote_call_python-1.7.0 → chalk_remote_call_python-1.7.1}/chalk-remote-call-rs/chalk-remote-call-proto/src/gen/chalk.common.v1.rs +0 -0
- {chalk_remote_call_python-1.7.0 → chalk_remote_call_python-1.7.1}/chalk-remote-call-rs/chalk-remote-call-proto/src/gen/chalk.utils.v1.rs +0 -0
- {chalk_remote_call_python-1.7.0 → chalk_remote_call_python-1.7.1}/chalk-remote-call-rs/chalk-remote-call-proto/src/lib.rs +0 -0
- {chalk_remote_call_python-1.7.0 → chalk_remote_call_python-1.7.1}/chalk-remote-call-rs/chalk-remote-call-server/Cargo.toml +0 -0
- {chalk_remote_call_python-1.7.0 → chalk_remote_call_python-1.7.1}/chalk-remote-call-rs/chalk-remote-call-server/src/coalesce.rs +0 -0
- {chalk_remote_call_python-1.7.0 → chalk_remote_call_python-1.7.1}/chalk-remote-call-rs/rust-toolchain.toml +0 -0
- {chalk_remote_call_python-1.7.0 → chalk_remote_call_python-1.7.1}/chalk_remote_call/__init__.py +0 -0
- {chalk_remote_call_python-1.7.0 → chalk_remote_call_python-1.7.1}/chalk_remote_call/__main__.py +0 -0
- {chalk_remote_call_python-1.7.0 → chalk_remote_call_python-1.7.1}/chalk_remote_call/_gen/__init__.py +0 -0
- {chalk_remote_call_python-1.7.0 → chalk_remote_call_python-1.7.1}/chalk_remote_call/_gen/chalk/__init__.py +0 -0
- {chalk_remote_call_python-1.7.0 → chalk_remote_call_python-1.7.1}/chalk_remote_call/_gen/chalk/auth/__init__.py +0 -0
- {chalk_remote_call_python-1.7.0 → chalk_remote_call_python-1.7.1}/chalk_remote_call/_gen/chalk/auth/v1/__init__.py +0 -0
- {chalk_remote_call_python-1.7.0 → chalk_remote_call_python-1.7.1}/chalk_remote_call/_gen/chalk/auth/v1/permissions_pb2_grpc.py +0 -0
- {chalk_remote_call_python-1.7.0 → chalk_remote_call_python-1.7.1}/chalk_remote_call/_gen/chalk/common/__init__.py +0 -0
- {chalk_remote_call_python-1.7.0 → chalk_remote_call_python-1.7.1}/chalk_remote_call/_gen/chalk/common/v1/__init__.py +0 -0
- {chalk_remote_call_python-1.7.0 → chalk_remote_call_python-1.7.1}/chalk_remote_call/_gen/chalk/common/v1/chalk_error_pb2.py +0 -0
- {chalk_remote_call_python-1.7.0 → chalk_remote_call_python-1.7.1}/chalk_remote_call/_gen/chalk/common/v1/chalk_error_pb2_grpc.py +0 -0
- {chalk_remote_call_python-1.7.0 → chalk_remote_call_python-1.7.1}/chalk_remote_call/_gen/chalk/runtime/__init__.py +0 -0
- {chalk_remote_call_python-1.7.0 → chalk_remote_call_python-1.7.1}/chalk_remote_call/_gen/chalk/runtime/v1/__init__.py +0 -0
- {chalk_remote_call_python-1.7.0 → chalk_remote_call_python-1.7.1}/chalk_remote_call/_gen/chalk/utils/__init__.py +0 -0
- {chalk_remote_call_python-1.7.0 → chalk_remote_call_python-1.7.1}/chalk_remote_call/_gen/chalk/utils/v1/__init__.py +0 -0
- {chalk_remote_call_python-1.7.0 → chalk_remote_call_python-1.7.1}/chalk_remote_call/_gen/chalk/utils/v1/encoding_pb2.py +0 -0
- {chalk_remote_call_python-1.7.0 → chalk_remote_call_python-1.7.1}/chalk_remote_call/_gen/chalk/utils/v1/encoding_pb2_grpc.py +0 -0
- {chalk_remote_call_python-1.7.0 → chalk_remote_call_python-1.7.1}/chalk_remote_call/_gen/chalk/utils/v1/field_change_pb2.py +0 -0
- {chalk_remote_call_python-1.7.0 → chalk_remote_call_python-1.7.1}/chalk_remote_call/_gen/chalk/utils/v1/field_change_pb2_grpc.py +0 -0
- {chalk_remote_call_python-1.7.0 → chalk_remote_call_python-1.7.1}/chalk_remote_call/_gen/chalk/utils/v1/sensitive_pb2.py +0 -0
- {chalk_remote_call_python-1.7.0 → chalk_remote_call_python-1.7.1}/chalk_remote_call/_gen/chalk/utils/v1/sensitive_pb2_grpc.py +0 -0
- {chalk_remote_call_python-1.7.0 → chalk_remote_call_python-1.7.1}/chalk_remote_call/_native.pyi +0 -0
- {chalk_remote_call_python-1.7.0 → chalk_remote_call_python-1.7.1}/chalk_remote_call/arrow_utils.py +0 -0
- {chalk_remote_call_python-1.7.0 → chalk_remote_call_python-1.7.1}/chalk_remote_call/cli.py +0 -0
- {chalk_remote_call_python-1.7.0 → chalk_remote_call_python-1.7.1}/chalk_remote_call/handler_loader.py +0 -0
- {chalk_remote_call_python-1.7.0 → chalk_remote_call_python-1.7.1}/chalk_remote_call/input_transform.py +0 -0
- {chalk_remote_call_python-1.7.0 → chalk_remote_call_python-1.7.1}/chalk_remote_call/server.py +0 -0
- {chalk_remote_call_python-1.7.0 → chalk_remote_call_python-1.7.1}/chalk_remote_call/servicer.py +0 -0
- {chalk_remote_call_python-1.7.0 → chalk_remote_call_python-1.7.1}/chalk_remote_call/tracing.py +0 -0
- {chalk_remote_call_python-1.7.0 → chalk_remote_call_python-1.7.1}/chalk_remote_call_python.egg-info/dependency_links.txt +0 -0
- {chalk_remote_call_python-1.7.0 → chalk_remote_call_python-1.7.1}/chalk_remote_call_python.egg-info/entry_points.txt +0 -0
- {chalk_remote_call_python-1.7.0 → chalk_remote_call_python-1.7.1}/chalk_remote_call_python.egg-info/requires.txt +0 -0
- {chalk_remote_call_python-1.7.0 → chalk_remote_call_python-1.7.1}/chalk_remote_call_python.egg-info/top_level.txt +0 -0
- {chalk_remote_call_python-1.7.0 → chalk_remote_call_python-1.7.1}/pyproject.toml +0 -0
- {chalk_remote_call_python-1.7.0 → chalk_remote_call_python-1.7.1}/setup.cfg +0 -0
- {chalk_remote_call_python-1.7.0 → chalk_remote_call_python-1.7.1}/setup.py +0 -0
|
@@ -39,6 +39,9 @@ pub enum Permission {
|
|
|
39
39
|
InfrastructureWrite = 31,
|
|
40
40
|
EnvironmentCreate = 32,
|
|
41
41
|
InternalDataplaneStatusUpdate = 33,
|
|
42
|
+
InternalWorkingTokenExchange = 34,
|
|
43
|
+
BillingWrite = 35,
|
|
44
|
+
QueryOfflineRead = 36,
|
|
42
45
|
}
|
|
43
46
|
impl Permission {
|
|
44
47
|
/// String value of the enum field names used in the ProtoBuf definition.
|
|
@@ -81,6 +84,9 @@ impl Permission {
|
|
|
81
84
|
Permission::InfrastructureWrite => "PERMISSION_INFRASTRUCTURE_WRITE",
|
|
82
85
|
Permission::EnvironmentCreate => "PERMISSION_ENVIRONMENT_CREATE",
|
|
83
86
|
Permission::InternalDataplaneStatusUpdate => "PERMISSION_INTERNAL_DATAPLANE_STATUS_UPDATE",
|
|
87
|
+
Permission::InternalWorkingTokenExchange => "PERMISSION_INTERNAL_WORKING_TOKEN_EXCHANGE",
|
|
88
|
+
Permission::BillingWrite => "PERMISSION_BILLING_WRITE",
|
|
89
|
+
Permission::QueryOfflineRead => "PERMISSION_QUERY_OFFLINE_READ",
|
|
84
90
|
}
|
|
85
91
|
}
|
|
86
92
|
/// Creates an enum from field names used in the ProtoBuf definition.
|
|
@@ -120,6 +126,9 @@ impl Permission {
|
|
|
120
126
|
"PERMISSION_INFRASTRUCTURE_WRITE" => Some(Self::InfrastructureWrite),
|
|
121
127
|
"PERMISSION_ENVIRONMENT_CREATE" => Some(Self::EnvironmentCreate),
|
|
122
128
|
"PERMISSION_INTERNAL_DATAPLANE_STATUS_UPDATE" => Some(Self::InternalDataplaneStatusUpdate),
|
|
129
|
+
"PERMISSION_INTERNAL_WORKING_TOKEN_EXCHANGE" => Some(Self::InternalWorkingTokenExchange),
|
|
130
|
+
"PERMISSION_BILLING_WRITE" => Some(Self::BillingWrite),
|
|
131
|
+
"PERMISSION_QUERY_OFFLINE_READ" => Some(Self::QueryOfflineRead),
|
|
123
132
|
_ => None,
|
|
124
133
|
}
|
|
125
134
|
}
|
|
@@ -86,6 +86,38 @@ pub struct PollRemoteCallResponse {
|
|
|
86
86
|
#[prost(message, repeated, tag="4")]
|
|
87
87
|
pub errors: ::prost::alloc::vec::Vec<super::super::common::v1::ChalkError>,
|
|
88
88
|
}
|
|
89
|
+
/// Drop pending items from one or all per-function queues for the tenant.
|
|
90
|
+
/// Already-popped (in-flight) calls continue to completion; only items still
|
|
91
|
+
/// queued in Redis are removed.
|
|
92
|
+
#[allow(clippy::derive_partial_eq_without_eq)]
|
|
93
|
+
#[derive(Clone, PartialEq, ::prost::Message)]
|
|
94
|
+
pub struct PurgeQueueRequest {
|
|
95
|
+
#[prost(oneof="purge_queue_request::Request", tags="1, 2")]
|
|
96
|
+
pub request: ::core::option::Option<purge_queue_request::Request>,
|
|
97
|
+
}
|
|
98
|
+
/// Nested message and enum types in `PurgeQueueRequest`.
|
|
99
|
+
pub mod purge_queue_request {
|
|
100
|
+
#[allow(clippy::derive_partial_eq_without_eq)]
|
|
101
|
+
#[derive(Clone, PartialEq, ::prost::Oneof)]
|
|
102
|
+
pub enum Request {
|
|
103
|
+
/// Drop pending items from the named function's queue.
|
|
104
|
+
#[prost(string, tag="1")]
|
|
105
|
+
FunctionName(::prost::alloc::string::String),
|
|
106
|
+
/// If true, drop pending items from every per-function queue for the tenant.
|
|
107
|
+
#[prost(bool, tag="2")]
|
|
108
|
+
All(bool),
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
#[allow(clippy::derive_partial_eq_without_eq)]
|
|
112
|
+
#[derive(Clone, PartialEq, ::prost::Message)]
|
|
113
|
+
pub struct PurgeQueueResponse {
|
|
114
|
+
/// Number of pending items dropped per function. For a single-function
|
|
115
|
+
/// purge, contains exactly one entry (or none, if the queue was already
|
|
116
|
+
/// empty). For a tenant-wide purge, contains every queue that had at
|
|
117
|
+
/// least one pending item. The total dropped is `sum(values)`.
|
|
118
|
+
#[prost(map="string, uint64", tag="1")]
|
|
119
|
+
pub items_removed_by_function: ::std::collections::HashMap<::prost::alloc::string::String, u64>,
|
|
120
|
+
}
|
|
89
121
|
// ── Function Queue Meta Service ───────────────────────────────────
|
|
90
122
|
|
|
91
123
|
/// Information about a single function call.
|
|
@@ -130,6 +162,32 @@ pub struct GetRecentCallsResponse {
|
|
|
130
162
|
#[prost(message, repeated, tag="1")]
|
|
131
163
|
pub calls: ::prost::alloc::vec::Vec<FunctionCallInfo>,
|
|
132
164
|
}
|
|
165
|
+
#[allow(clippy::derive_partial_eq_without_eq)]
|
|
166
|
+
#[derive(Clone, PartialEq, ::prost::Message)]
|
|
167
|
+
pub struct GetCallResultsRequest {
|
|
168
|
+
/// Call IDs to fetch from the function queue.
|
|
169
|
+
#[prost(string, repeated, tag="1")]
|
|
170
|
+
pub call_ids: ::prost::alloc::vec::Vec<::prost::alloc::string::String>,
|
|
171
|
+
}
|
|
172
|
+
#[allow(clippy::derive_partial_eq_without_eq)]
|
|
173
|
+
#[derive(Clone, PartialEq, ::prost::Message)]
|
|
174
|
+
pub struct CallResult {
|
|
175
|
+
/// The requested call ID.
|
|
176
|
+
#[prost(string, tag="1")]
|
|
177
|
+
pub call_id: ::prost::alloc::string::String,
|
|
178
|
+
/// Present when the function queue returned a result for this call.
|
|
179
|
+
#[prost(message, optional, tag="2")]
|
|
180
|
+
pub response: ::core::option::Option<PollRemoteCallResponse>,
|
|
181
|
+
/// Populated when the queue lookup failed for this specific call.
|
|
182
|
+
#[prost(string, tag="3")]
|
|
183
|
+
pub error_message: ::prost::alloc::string::String,
|
|
184
|
+
}
|
|
185
|
+
#[allow(clippy::derive_partial_eq_without_eq)]
|
|
186
|
+
#[derive(Clone, PartialEq, ::prost::Message)]
|
|
187
|
+
pub struct GetCallResultsResponse {
|
|
188
|
+
#[prost(message, repeated, tag="1")]
|
|
189
|
+
pub results: ::prost::alloc::vec::Vec<CallResult>,
|
|
190
|
+
}
|
|
133
191
|
/// Request the number of calls submitted in the past hour.
|
|
134
192
|
#[allow(clippy::derive_partial_eq_without_eq)]
|
|
135
193
|
#[derive(Clone, PartialEq, ::prost::Message)]
|
|
@@ -443,6 +443,36 @@ pub mod async_remote_call_service_client {
|
|
|
443
443
|
);
|
|
444
444
|
self.inner.unary(req, path, codec).await
|
|
445
445
|
}
|
|
446
|
+
pub async fn purge_queue(
|
|
447
|
+
&mut self,
|
|
448
|
+
request: impl tonic::IntoRequest<super::PurgeQueueRequest>,
|
|
449
|
+
) -> std::result::Result<
|
|
450
|
+
tonic::Response<super::PurgeQueueResponse>,
|
|
451
|
+
tonic::Status,
|
|
452
|
+
> {
|
|
453
|
+
self.inner
|
|
454
|
+
.ready()
|
|
455
|
+
.await
|
|
456
|
+
.map_err(|e| {
|
|
457
|
+
tonic::Status::new(
|
|
458
|
+
tonic::Code::Unknown,
|
|
459
|
+
format!("Service was not ready: {}", e.into()),
|
|
460
|
+
)
|
|
461
|
+
})?;
|
|
462
|
+
let codec = tonic::codec::ProstCodec::default();
|
|
463
|
+
let path = http::uri::PathAndQuery::from_static(
|
|
464
|
+
"/chalk.runtime.v1.AsyncRemoteCallService/PurgeQueue",
|
|
465
|
+
);
|
|
466
|
+
let mut req = request.into_request();
|
|
467
|
+
req.extensions_mut()
|
|
468
|
+
.insert(
|
|
469
|
+
GrpcMethod::new(
|
|
470
|
+
"chalk.runtime.v1.AsyncRemoteCallService",
|
|
471
|
+
"PurgeQueue",
|
|
472
|
+
),
|
|
473
|
+
);
|
|
474
|
+
self.inner.unary(req, path, codec).await
|
|
475
|
+
}
|
|
446
476
|
}
|
|
447
477
|
}
|
|
448
478
|
/// Generated server implementations.
|
|
@@ -466,6 +496,13 @@ pub mod async_remote_call_service_server {
|
|
|
466
496
|
tonic::Response<super::PollRemoteCallResponse>,
|
|
467
497
|
tonic::Status,
|
|
468
498
|
>;
|
|
499
|
+
async fn purge_queue(
|
|
500
|
+
&self,
|
|
501
|
+
request: tonic::Request<super::PurgeQueueRequest>,
|
|
502
|
+
) -> std::result::Result<
|
|
503
|
+
tonic::Response<super::PurgeQueueResponse>,
|
|
504
|
+
tonic::Status,
|
|
505
|
+
>;
|
|
469
506
|
}
|
|
470
507
|
#[derive(Debug)]
|
|
471
508
|
pub struct AsyncRemoteCallServiceServer<T: AsyncRemoteCallService> {
|
|
@@ -642,6 +679,52 @@ pub mod async_remote_call_service_server {
|
|
|
642
679
|
};
|
|
643
680
|
Box::pin(fut)
|
|
644
681
|
}
|
|
682
|
+
"/chalk.runtime.v1.AsyncRemoteCallService/PurgeQueue" => {
|
|
683
|
+
#[allow(non_camel_case_types)]
|
|
684
|
+
struct PurgeQueueSvc<T: AsyncRemoteCallService>(pub Arc<T>);
|
|
685
|
+
impl<
|
|
686
|
+
T: AsyncRemoteCallService,
|
|
687
|
+
> tonic::server::UnaryService<super::PurgeQueueRequest>
|
|
688
|
+
for PurgeQueueSvc<T> {
|
|
689
|
+
type Response = super::PurgeQueueResponse;
|
|
690
|
+
type Future = BoxFuture<
|
|
691
|
+
tonic::Response<Self::Response>,
|
|
692
|
+
tonic::Status,
|
|
693
|
+
>;
|
|
694
|
+
fn call(
|
|
695
|
+
&mut self,
|
|
696
|
+
request: tonic::Request<super::PurgeQueueRequest>,
|
|
697
|
+
) -> Self::Future {
|
|
698
|
+
let inner = Arc::clone(&self.0);
|
|
699
|
+
let fut = async move {
|
|
700
|
+
<T as AsyncRemoteCallService>::purge_queue(&inner, request)
|
|
701
|
+
.await
|
|
702
|
+
};
|
|
703
|
+
Box::pin(fut)
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
let accept_compression_encodings = self.accept_compression_encodings;
|
|
707
|
+
let send_compression_encodings = self.send_compression_encodings;
|
|
708
|
+
let max_decoding_message_size = self.max_decoding_message_size;
|
|
709
|
+
let max_encoding_message_size = self.max_encoding_message_size;
|
|
710
|
+
let inner = self.inner.clone();
|
|
711
|
+
let fut = async move {
|
|
712
|
+
let method = PurgeQueueSvc(inner);
|
|
713
|
+
let codec = tonic::codec::ProstCodec::default();
|
|
714
|
+
let mut grpc = tonic::server::Grpc::new(codec)
|
|
715
|
+
.apply_compression_config(
|
|
716
|
+
accept_compression_encodings,
|
|
717
|
+
send_compression_encodings,
|
|
718
|
+
)
|
|
719
|
+
.apply_max_message_size_config(
|
|
720
|
+
max_decoding_message_size,
|
|
721
|
+
max_encoding_message_size,
|
|
722
|
+
);
|
|
723
|
+
let res = grpc.unary(method, req).await;
|
|
724
|
+
Ok(res)
|
|
725
|
+
};
|
|
726
|
+
Box::pin(fut)
|
|
727
|
+
}
|
|
645
728
|
_ => {
|
|
646
729
|
Box::pin(async move {
|
|
647
730
|
Ok(
|
|
@@ -797,6 +880,38 @@ pub mod function_queue_meta_service_client {
|
|
|
797
880
|
);
|
|
798
881
|
self.inner.unary(req, path, codec).await
|
|
799
882
|
}
|
|
883
|
+
/** Return current status and accumulated result chunks for specific calls.
|
|
884
|
+
*/
|
|
885
|
+
pub async fn get_call_results(
|
|
886
|
+
&mut self,
|
|
887
|
+
request: impl tonic::IntoRequest<super::GetCallResultsRequest>,
|
|
888
|
+
) -> std::result::Result<
|
|
889
|
+
tonic::Response<super::GetCallResultsResponse>,
|
|
890
|
+
tonic::Status,
|
|
891
|
+
> {
|
|
892
|
+
self.inner
|
|
893
|
+
.ready()
|
|
894
|
+
.await
|
|
895
|
+
.map_err(|e| {
|
|
896
|
+
tonic::Status::new(
|
|
897
|
+
tonic::Code::Unknown,
|
|
898
|
+
format!("Service was not ready: {}", e.into()),
|
|
899
|
+
)
|
|
900
|
+
})?;
|
|
901
|
+
let codec = tonic::codec::ProstCodec::default();
|
|
902
|
+
let path = http::uri::PathAndQuery::from_static(
|
|
903
|
+
"/chalk.runtime.v1.FunctionQueueMetaService/GetCallResults",
|
|
904
|
+
);
|
|
905
|
+
let mut req = request.into_request();
|
|
906
|
+
req.extensions_mut()
|
|
907
|
+
.insert(
|
|
908
|
+
GrpcMethod::new(
|
|
909
|
+
"chalk.runtime.v1.FunctionQueueMetaService",
|
|
910
|
+
"GetCallResults",
|
|
911
|
+
),
|
|
912
|
+
);
|
|
913
|
+
self.inner.unary(req, path, codec).await
|
|
914
|
+
}
|
|
800
915
|
/** Return the number of calls submitted to a function in the past hour.
|
|
801
916
|
*/
|
|
802
917
|
pub async fn get_call_count(
|
|
@@ -847,6 +962,15 @@ pub mod function_queue_meta_service_server {
|
|
|
847
962
|
tonic::Response<super::GetRecentCallsResponse>,
|
|
848
963
|
tonic::Status,
|
|
849
964
|
>;
|
|
965
|
+
/** Return current status and accumulated result chunks for specific calls.
|
|
966
|
+
*/
|
|
967
|
+
async fn get_call_results(
|
|
968
|
+
&self,
|
|
969
|
+
request: tonic::Request<super::GetCallResultsRequest>,
|
|
970
|
+
) -> std::result::Result<
|
|
971
|
+
tonic::Response<super::GetCallResultsResponse>,
|
|
972
|
+
tonic::Status,
|
|
973
|
+
>;
|
|
850
974
|
/** Return the number of calls submitted to a function in the past hour.
|
|
851
975
|
*/
|
|
852
976
|
async fn get_call_count(
|
|
@@ -984,6 +1108,55 @@ pub mod function_queue_meta_service_server {
|
|
|
984
1108
|
};
|
|
985
1109
|
Box::pin(fut)
|
|
986
1110
|
}
|
|
1111
|
+
"/chalk.runtime.v1.FunctionQueueMetaService/GetCallResults" => {
|
|
1112
|
+
#[allow(non_camel_case_types)]
|
|
1113
|
+
struct GetCallResultsSvc<T: FunctionQueueMetaService>(pub Arc<T>);
|
|
1114
|
+
impl<
|
|
1115
|
+
T: FunctionQueueMetaService,
|
|
1116
|
+
> tonic::server::UnaryService<super::GetCallResultsRequest>
|
|
1117
|
+
for GetCallResultsSvc<T> {
|
|
1118
|
+
type Response = super::GetCallResultsResponse;
|
|
1119
|
+
type Future = BoxFuture<
|
|
1120
|
+
tonic::Response<Self::Response>,
|
|
1121
|
+
tonic::Status,
|
|
1122
|
+
>;
|
|
1123
|
+
fn call(
|
|
1124
|
+
&mut self,
|
|
1125
|
+
request: tonic::Request<super::GetCallResultsRequest>,
|
|
1126
|
+
) -> Self::Future {
|
|
1127
|
+
let inner = Arc::clone(&self.0);
|
|
1128
|
+
let fut = async move {
|
|
1129
|
+
<T as FunctionQueueMetaService>::get_call_results(
|
|
1130
|
+
&inner,
|
|
1131
|
+
request,
|
|
1132
|
+
)
|
|
1133
|
+
.await
|
|
1134
|
+
};
|
|
1135
|
+
Box::pin(fut)
|
|
1136
|
+
}
|
|
1137
|
+
}
|
|
1138
|
+
let accept_compression_encodings = self.accept_compression_encodings;
|
|
1139
|
+
let send_compression_encodings = self.send_compression_encodings;
|
|
1140
|
+
let max_decoding_message_size = self.max_decoding_message_size;
|
|
1141
|
+
let max_encoding_message_size = self.max_encoding_message_size;
|
|
1142
|
+
let inner = self.inner.clone();
|
|
1143
|
+
let fut = async move {
|
|
1144
|
+
let method = GetCallResultsSvc(inner);
|
|
1145
|
+
let codec = tonic::codec::ProstCodec::default();
|
|
1146
|
+
let mut grpc = tonic::server::Grpc::new(codec)
|
|
1147
|
+
.apply_compression_config(
|
|
1148
|
+
accept_compression_encodings,
|
|
1149
|
+
send_compression_encodings,
|
|
1150
|
+
)
|
|
1151
|
+
.apply_max_message_size_config(
|
|
1152
|
+
max_decoding_message_size,
|
|
1153
|
+
max_encoding_message_size,
|
|
1154
|
+
);
|
|
1155
|
+
let res = grpc.unary(method, req).await;
|
|
1156
|
+
Ok(res)
|
|
1157
|
+
};
|
|
1158
|
+
Box::pin(fut)
|
|
1159
|
+
}
|
|
987
1160
|
"/chalk.runtime.v1.FunctionQueueMetaService/GetCallCount" => {
|
|
988
1161
|
#[allow(non_camel_case_types)]
|
|
989
1162
|
struct GetCallCountSvc<T: FunctionQueueMetaService>(pub Arc<T>);
|
|
Binary file
|
chalk_remote_call_python-1.7.1/chalk-remote-call-rs/chalk-remote-call-server/src/async_service.rs
ADDED
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
use std::collections::HashMap;
|
|
2
|
+
use std::sync::atomic::{AtomicU64, Ordering};
|
|
3
|
+
use std::sync::{Arc, Mutex};
|
|
4
|
+
|
|
5
|
+
use chalk_remote_call_proto::chalk::common::v1::ChalkError;
|
|
6
|
+
use chalk_remote_call_proto::chalk::runtime::v1::async_remote_call_service_server::AsyncRemoteCallService;
|
|
7
|
+
use chalk_remote_call_proto::chalk::runtime::v1::{
|
|
8
|
+
remote_call_args, EnqueueRemoteCallRequest, EnqueueRemoteCallResponse, PollRemoteCallRequest,
|
|
9
|
+
PollRemoteCallResponse, PurgeQueueRequest, PurgeQueueResponse, RemoteCallStatus,
|
|
10
|
+
};
|
|
11
|
+
use tonic::{Request, Response, Status};
|
|
12
|
+
use tracing::{debug, error, info, instrument};
|
|
13
|
+
|
|
14
|
+
use crate::python_bridge::{ChunkBuffer, PythonHandler};
|
|
15
|
+
use crate::service::extract_metadata;
|
|
16
|
+
|
|
17
|
+
/// In-memory execution record for one enqueued call.
|
|
18
|
+
///
|
|
19
|
+
/// Lives only on the sg pod that accepted the `EnqueueRemoteCall`, and is lost
|
|
20
|
+
/// on pod restart. That is the accepted limitation of the base async path:
|
|
21
|
+
/// arbitrary user handlers cannot be checkpointed, so an sg-pod death loses the
|
|
22
|
+
/// computation regardless. A reclaiming consumer will re-enqueue (and the
|
|
23
|
+
/// function re-runs). Durable reattach across *consumer* restarts is a later
|
|
24
|
+
/// phase and lives outside this struct.
|
|
25
|
+
struct CallState {
|
|
26
|
+
status: RemoteCallStatus,
|
|
27
|
+
/// Result chunks, written directly by the handler's `BufferEmitter` as it
|
|
28
|
+
/// runs and read by `PollRemoteCall` by cursor. Held behind its own lock
|
|
29
|
+
/// (not the registry map lock) so the hot emit path only contends per-call,
|
|
30
|
+
/// and `status`/`error` can be updated without blocking emits.
|
|
31
|
+
chunks: ChunkBuffer,
|
|
32
|
+
/// Populated only when `status == Failed`; surfaced as a `ChalkError`.
|
|
33
|
+
error: Option<String>,
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
impl CallState {
|
|
37
|
+
fn new() -> Self {
|
|
38
|
+
Self {
|
|
39
|
+
status: RemoteCallStatus::Pending,
|
|
40
|
+
chunks: Arc::new(Mutex::new(Vec::new())),
|
|
41
|
+
error: None,
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
type Registry = Arc<Mutex<HashMap<String, CallState>>>;
|
|
47
|
+
|
|
48
|
+
/// Async (enqueue + poll) executor for the scaling-group hop.
|
|
49
|
+
///
|
|
50
|
+
/// `EnqueueRemoteCall` runs the handler in a detached background task that
|
|
51
|
+
/// writes result chunks straight into the call's buffer, and returns
|
|
52
|
+
/// immediately; `PollRemoteCall` reads those chunks by cursor. This decouples
|
|
53
|
+
/// function execution from any single connection's lifetime, so the path is
|
|
54
|
+
/// immune to gateway request/stream timeouts — every RPC here is sub-second
|
|
55
|
+
/// regardless of how long the function runs.
|
|
56
|
+
pub struct AsyncRemoteCallServiceImpl {
|
|
57
|
+
python_handler: Arc<PythonHandler>,
|
|
58
|
+
registry: Registry,
|
|
59
|
+
next_id: AtomicU64,
|
|
60
|
+
/// True when the server was started with coalescing enabled. In that mode
|
|
61
|
+
/// `python_handler`'s bridge expects the batched calling convention, which
|
|
62
|
+
/// the per-call dispatch does not satisfy, so async enqueue is refused
|
|
63
|
+
/// rather than silently calling the handler with the wrong shape.
|
|
64
|
+
batching_enabled: bool,
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
impl AsyncRemoteCallServiceImpl {
|
|
68
|
+
pub fn new(python_handler: Arc<PythonHandler>, batching_enabled: bool) -> Self {
|
|
69
|
+
Self {
|
|
70
|
+
python_handler,
|
|
71
|
+
registry: Arc::new(Mutex::new(HashMap::new())),
|
|
72
|
+
next_id: AtomicU64::new(1),
|
|
73
|
+
batching_enabled,
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
#[tonic::async_trait]
|
|
79
|
+
impl AsyncRemoteCallService for AsyncRemoteCallServiceImpl {
|
|
80
|
+
#[instrument(skip_all)]
|
|
81
|
+
async fn enqueue_remote_call(
|
|
82
|
+
&self,
|
|
83
|
+
request: Request<EnqueueRemoteCallRequest>,
|
|
84
|
+
) -> Result<Response<EnqueueRemoteCallResponse>, Status> {
|
|
85
|
+
if self.batching_enabled {
|
|
86
|
+
return Err(Status::unimplemented(
|
|
87
|
+
"async enqueue/poll is not supported when request coalescing is enabled",
|
|
88
|
+
));
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
let metadata = extract_metadata(request.metadata());
|
|
92
|
+
let peer = request
|
|
93
|
+
.remote_addr()
|
|
94
|
+
.map(|a| a.to_string())
|
|
95
|
+
.unwrap_or_default();
|
|
96
|
+
let req = request.into_inner();
|
|
97
|
+
let function_name = req.name;
|
|
98
|
+
|
|
99
|
+
// Only inline feather bytes are supported today; the object-store
|
|
100
|
+
// variant is reserved for large payloads and not wired up here.
|
|
101
|
+
let ipc_bytes = match req.args.and_then(|a| a.args) {
|
|
102
|
+
Some(remote_call_args::Args::FeatherBytes(b)) => b.to_vec(),
|
|
103
|
+
Some(remote_call_args::Args::StorageObjectId(_)) => {
|
|
104
|
+
return Err(Status::unimplemented(
|
|
105
|
+
"storage_object_id args are not supported by the scaling-group executor",
|
|
106
|
+
));
|
|
107
|
+
}
|
|
108
|
+
None => Vec::new(),
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
// Pod-scoped id: the registry only knows about calls accepted by this
|
|
112
|
+
// pod, so a monotonic per-process counter is sufficient for uniqueness.
|
|
113
|
+
let call_id = format!("sg-{}", self.next_id.fetch_add(1, Ordering::Relaxed));
|
|
114
|
+
|
|
115
|
+
let state = CallState::new();
|
|
116
|
+
// The handler writes chunks into this buffer directly; the registry
|
|
117
|
+
// keeps the same Arc so polls can read them back.
|
|
118
|
+
let buffer = state.chunks.clone();
|
|
119
|
+
self.registry
|
|
120
|
+
.lock()
|
|
121
|
+
.expect("registry mutex poisoned")
|
|
122
|
+
.insert(call_id.clone(), state);
|
|
123
|
+
|
|
124
|
+
info!(call_id = %call_id, function_name = %function_name, "enqueued async call");
|
|
125
|
+
|
|
126
|
+
let handler = self.python_handler.clone();
|
|
127
|
+
let registry = self.registry.clone();
|
|
128
|
+
let id = call_id.clone();
|
|
129
|
+
tokio::spawn(async move {
|
|
130
|
+
set_status(®istry, &id, RemoteCallStatus::Running);
|
|
131
|
+
|
|
132
|
+
// The handler appends each chunk straight into `buffer`; completion
|
|
133
|
+
// is signalled purely by this returning, so there is no channel to
|
|
134
|
+
// drain and nothing that waits on Python object teardown.
|
|
135
|
+
let result = handler
|
|
136
|
+
.call_into_buffer(ipc_bytes, function_name, metadata, peer, buffer)
|
|
137
|
+
.await;
|
|
138
|
+
|
|
139
|
+
let mut reg = registry.lock().expect("registry mutex poisoned");
|
|
140
|
+
if let Some(s) = reg.get_mut(&id) {
|
|
141
|
+
match result {
|
|
142
|
+
Ok(()) => {
|
|
143
|
+
s.status = RemoteCallStatus::Completed;
|
|
144
|
+
let n = s.chunks.lock().map(|b| b.len()).unwrap_or(0);
|
|
145
|
+
info!(call_id = %id, chunks = n, "async call completed");
|
|
146
|
+
}
|
|
147
|
+
Err(e) => {
|
|
148
|
+
s.status = RemoteCallStatus::Failed;
|
|
149
|
+
s.error = Some(e.to_string());
|
|
150
|
+
error!(call_id = %id, error = %e, "async call failed");
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
Ok(Response::new(EnqueueRemoteCallResponse { call_id }))
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
#[instrument(skip_all)]
|
|
160
|
+
async fn poll_remote_call(
|
|
161
|
+
&self,
|
|
162
|
+
request: Request<PollRemoteCallRequest>,
|
|
163
|
+
) -> Result<Response<PollRemoteCallResponse>, Status> {
|
|
164
|
+
let req = request.into_inner();
|
|
165
|
+
let cursor: usize = if req.cursor.is_empty() {
|
|
166
|
+
0
|
|
167
|
+
} else {
|
|
168
|
+
req.cursor
|
|
169
|
+
.parse()
|
|
170
|
+
.map_err(|_| Status::invalid_argument(format!("invalid cursor: {}", req.cursor)))?
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
// Read status/error and grab the chunk-buffer handle under the map lock,
|
|
174
|
+
// then release it before locking the buffer. `status` is set to a
|
|
175
|
+
// terminal value only after the handler returns (all chunks already
|
|
176
|
+
// appended), so seeing `Completed` guarantees the buffer is complete.
|
|
177
|
+
let (status, error, chunks) = {
|
|
178
|
+
let reg = self.registry.lock().expect("registry mutex poisoned");
|
|
179
|
+
let state = reg
|
|
180
|
+
.get(&req.call_id)
|
|
181
|
+
.ok_or_else(|| Status::not_found(format!("unknown call_id: {}", req.call_id)))?;
|
|
182
|
+
(state.status, state.error.clone(), state.chunks.clone())
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
let buf = chunks.lock().expect("chunk buffer poisoned");
|
|
186
|
+
// Clamp so a stale/over-large cursor returns an empty suffix rather than
|
|
187
|
+
// panicking on the slice.
|
|
188
|
+
let total = buf.len();
|
|
189
|
+
let from = cursor.min(total);
|
|
190
|
+
let results = buf[from..].to_vec();
|
|
191
|
+
drop(buf);
|
|
192
|
+
|
|
193
|
+
let errors = if status == RemoteCallStatus::Failed {
|
|
194
|
+
vec![ChalkError {
|
|
195
|
+
message: error.unwrap_or_else(|| "remote call failed".to_string()),
|
|
196
|
+
..Default::default()
|
|
197
|
+
}]
|
|
198
|
+
} else {
|
|
199
|
+
Vec::new()
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
debug!(
|
|
203
|
+
call_id = %req.call_id,
|
|
204
|
+
status = ?status,
|
|
205
|
+
from,
|
|
206
|
+
returned = results.len(),
|
|
207
|
+
"poll"
|
|
208
|
+
);
|
|
209
|
+
|
|
210
|
+
Ok(Response::new(PollRemoteCallResponse {
|
|
211
|
+
status: status as i32,
|
|
212
|
+
results,
|
|
213
|
+
cursor: total.to_string(),
|
|
214
|
+
errors,
|
|
215
|
+
}))
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
async fn purge_queue(
|
|
219
|
+
&self,
|
|
220
|
+
_request: Request<PurgeQueueRequest>,
|
|
221
|
+
) -> Result<Response<PurgeQueueResponse>, Status> {
|
|
222
|
+
// PurgeQueue operates on the tenant's Redis-backed function queues,
|
|
223
|
+
// which live in the function-queue server — not on an individual
|
|
224
|
+
// scaling-group executor pod.
|
|
225
|
+
Err(Status::unimplemented(
|
|
226
|
+
"PurgeQueue is a function-queue-server operation; not supported on the scaling-group executor",
|
|
227
|
+
))
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/// Set the status of an in-flight call, if it still exists in the registry.
|
|
232
|
+
fn set_status(registry: &Registry, call_id: &str, status: RemoteCallStatus) {
|
|
233
|
+
if let Ok(mut reg) = registry.lock() {
|
|
234
|
+
if let Some(s) = reg.get_mut(call_id) {
|
|
235
|
+
s.status = status;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|