@temporalio/core-bridge 1.5.2 → 1.7.0
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.
- package/Cargo.lock +304 -112
- package/lib/index.d.ts +8 -6
- package/lib/index.js.map +1 -1
- package/package.json +9 -4
- package/releases/aarch64-apple-darwin/index.node +0 -0
- package/releases/aarch64-unknown-linux-gnu/index.node +0 -0
- package/releases/x86_64-apple-darwin/index.node +0 -0
- package/releases/x86_64-pc-windows-msvc/index.node +0 -0
- package/releases/x86_64-unknown-linux-gnu/index.node +0 -0
- package/sdk-core/.buildkite/docker/Dockerfile +2 -2
- package/sdk-core/.buildkite/docker/docker-compose.yaml +1 -1
- package/sdk-core/.buildkite/pipeline.yml +2 -4
- package/sdk-core/.cargo/config.toml +5 -2
- package/sdk-core/.github/workflows/heavy.yml +29 -0
- package/sdk-core/Cargo.toml +1 -1
- package/sdk-core/README.md +20 -10
- package/sdk-core/client/src/lib.rs +215 -39
- package/sdk-core/client/src/metrics.rs +17 -8
- package/sdk-core/client/src/raw.rs +4 -4
- package/sdk-core/client/src/retry.rs +32 -20
- package/sdk-core/core/Cargo.toml +25 -12
- package/sdk-core/core/src/abstractions/take_cell.rs +28 -0
- package/sdk-core/core/src/abstractions.rs +204 -14
- package/sdk-core/core/src/core_tests/activity_tasks.rs +143 -50
- package/sdk-core/core/src/core_tests/child_workflows.rs +6 -5
- package/sdk-core/core/src/core_tests/determinism.rs +165 -2
- package/sdk-core/core/src/core_tests/local_activities.rs +431 -43
- package/sdk-core/core/src/core_tests/queries.rs +34 -16
- package/sdk-core/core/src/core_tests/workers.rs +8 -5
- package/sdk-core/core/src/core_tests/workflow_tasks.rs +588 -55
- package/sdk-core/core/src/ephemeral_server/mod.rs +113 -12
- package/sdk-core/core/src/internal_flags.rs +155 -0
- package/sdk-core/core/src/lib.rs +16 -9
- package/sdk-core/core/src/protosext/mod.rs +1 -1
- package/sdk-core/core/src/replay/mod.rs +16 -27
- package/sdk-core/core/src/telemetry/log_export.rs +1 -1
- package/sdk-core/core/src/telemetry/metrics.rs +69 -35
- package/sdk-core/core/src/telemetry/mod.rs +60 -21
- package/sdk-core/core/src/telemetry/prometheus_server.rs +19 -13
- package/sdk-core/core/src/test_help/mod.rs +73 -14
- package/sdk-core/core/src/worker/activities/activity_heartbeat_manager.rs +119 -160
- package/sdk-core/core/src/worker/activities/activity_task_poller_stream.rs +89 -0
- package/sdk-core/core/src/worker/activities/local_activities.rs +379 -129
- package/sdk-core/core/src/worker/activities.rs +350 -175
- package/sdk-core/core/src/worker/client/mocks.rs +22 -2
- package/sdk-core/core/src/worker/client.rs +18 -2
- package/sdk-core/core/src/worker/mod.rs +183 -64
- package/sdk-core/core/src/worker/workflow/bridge.rs +1 -3
- package/sdk-core/core/src/worker/workflow/driven_workflow.rs +3 -5
- package/sdk-core/core/src/worker/workflow/history_update.rs +916 -277
- package/sdk-core/core/src/worker/workflow/machines/activity_state_machine.rs +216 -183
- package/sdk-core/core/src/worker/workflow/machines/cancel_external_state_machine.rs +9 -12
- package/sdk-core/core/src/worker/workflow/machines/cancel_workflow_state_machine.rs +7 -9
- package/sdk-core/core/src/worker/workflow/machines/child_workflow_state_machine.rs +160 -87
- package/sdk-core/core/src/worker/workflow/machines/complete_workflow_state_machine.rs +13 -14
- package/sdk-core/core/src/worker/workflow/machines/continue_as_new_workflow_state_machine.rs +7 -9
- package/sdk-core/core/src/worker/workflow/machines/fail_workflow_state_machine.rs +14 -17
- package/sdk-core/core/src/worker/workflow/machines/local_activity_state_machine.rs +242 -110
- package/sdk-core/core/src/worker/workflow/machines/mod.rs +27 -19
- package/sdk-core/core/src/worker/workflow/machines/modify_workflow_properties_state_machine.rs +9 -11
- package/sdk-core/core/src/worker/workflow/machines/patch_state_machine.rs +321 -206
- package/sdk-core/core/src/worker/workflow/machines/signal_external_state_machine.rs +13 -18
- package/sdk-core/core/src/worker/workflow/machines/timer_state_machine.rs +20 -29
- package/sdk-core/core/src/worker/workflow/machines/transition_coverage.rs +2 -2
- package/sdk-core/core/src/worker/workflow/machines/upsert_search_attributes_state_machine.rs +257 -51
- package/sdk-core/core/src/worker/workflow/machines/workflow_machines/local_acts.rs +6 -17
- package/sdk-core/core/src/worker/workflow/machines/workflow_machines.rs +310 -150
- package/sdk-core/core/src/worker/workflow/machines/workflow_task_state_machine.rs +17 -20
- package/sdk-core/core/src/worker/workflow/managed_run/managed_wf_test.rs +31 -15
- package/sdk-core/core/src/worker/workflow/managed_run.rs +1052 -380
- package/sdk-core/core/src/worker/workflow/mod.rs +598 -390
- package/sdk-core/core/src/worker/workflow/run_cache.rs +40 -57
- package/sdk-core/core/src/worker/workflow/wft_extraction.rs +137 -0
- package/sdk-core/core/src/worker/workflow/wft_poller.rs +1 -4
- package/sdk-core/core/src/worker/workflow/workflow_stream/saved_wf_inputs.rs +117 -0
- package/sdk-core/core/src/worker/workflow/workflow_stream/tonic_status_serde.rs +24 -0
- package/sdk-core/core/src/worker/workflow/workflow_stream.rs +469 -718
- package/sdk-core/core-api/Cargo.toml +2 -1
- package/sdk-core/core-api/src/errors.rs +1 -34
- package/sdk-core/core-api/src/lib.rs +19 -9
- package/sdk-core/core-api/src/telemetry.rs +4 -6
- package/sdk-core/core-api/src/worker.rs +19 -1
- package/sdk-core/etc/deps.svg +115 -140
- package/sdk-core/etc/regen-depgraph.sh +5 -0
- package/sdk-core/fsm/rustfsm_procmacro/src/lib.rs +86 -61
- package/sdk-core/fsm/rustfsm_trait/src/lib.rs +29 -71
- package/sdk-core/histories/ends_empty_wft_complete.bin +0 -0
- package/sdk-core/histories/evict_while_la_running_no_interference-16_history.bin +0 -0
- package/sdk-core/histories/old_change_marker_format.bin +0 -0
- package/sdk-core/protos/api_upstream/.github/CODEOWNERS +2 -1
- package/sdk-core/protos/api_upstream/Makefile +6 -6
- package/sdk-core/protos/api_upstream/build/go.mod +7 -0
- package/sdk-core/protos/api_upstream/build/go.sum +5 -0
- package/sdk-core/protos/api_upstream/build/tools.go +29 -0
- package/sdk-core/protos/api_upstream/go.mod +6 -0
- package/sdk-core/protos/api_upstream/temporal/api/batch/v1/message.proto +9 -2
- package/sdk-core/protos/api_upstream/temporal/api/command/v1/message.proto +7 -26
- package/sdk-core/protos/api_upstream/temporal/api/common/v1/message.proto +13 -2
- package/sdk-core/protos/api_upstream/temporal/api/enums/v1/batch_operation.proto +3 -2
- package/sdk-core/protos/api_upstream/temporal/api/enums/v1/command_type.proto +3 -7
- package/sdk-core/protos/api_upstream/temporal/api/enums/v1/common.proto +3 -2
- package/sdk-core/protos/api_upstream/temporal/api/enums/v1/event_type.proto +8 -8
- package/sdk-core/protos/api_upstream/temporal/api/enums/v1/failed_cause.proto +25 -2
- package/sdk-core/protos/api_upstream/temporal/api/enums/v1/namespace.proto +2 -2
- package/sdk-core/protos/api_upstream/temporal/api/enums/v1/query.proto +2 -2
- package/sdk-core/protos/api_upstream/temporal/api/enums/v1/reset.proto +2 -2
- package/sdk-core/protos/api_upstream/temporal/api/enums/v1/schedule.proto +2 -2
- package/sdk-core/protos/api_upstream/temporal/api/enums/v1/task_queue.proto +2 -2
- package/sdk-core/protos/api_upstream/temporal/api/enums/v1/update.proto +24 -19
- package/sdk-core/protos/api_upstream/temporal/api/enums/v1/workflow.proto +2 -2
- package/sdk-core/protos/api_upstream/temporal/api/errordetails/v1/message.proto +2 -2
- package/sdk-core/protos/api_upstream/temporal/api/failure/v1/message.proto +2 -2
- package/sdk-core/protos/api_upstream/temporal/api/filter/v1/message.proto +2 -2
- package/sdk-core/protos/api_upstream/temporal/api/history/v1/message.proto +49 -26
- package/sdk-core/protos/api_upstream/temporal/api/namespace/v1/message.proto +4 -2
- package/sdk-core/protos/api_upstream/temporal/api/operatorservice/v1/request_response.proto +5 -2
- package/sdk-core/protos/api_upstream/temporal/api/operatorservice/v1/service.proto +2 -2
- package/sdk-core/protos/api_upstream/temporal/api/protocol/v1/message.proto +57 -0
- package/sdk-core/protos/api_upstream/temporal/api/query/v1/message.proto +2 -2
- package/sdk-core/protos/api_upstream/temporal/api/replication/v1/message.proto +2 -2
- package/sdk-core/protos/api_upstream/temporal/api/schedule/v1/message.proto +2 -2
- package/sdk-core/protos/api_upstream/temporal/api/sdk/v1/task_complete_metadata.proto +63 -0
- package/sdk-core/protos/api_upstream/temporal/api/taskqueue/v1/message.proto +2 -2
- package/sdk-core/protos/api_upstream/temporal/api/update/v1/message.proto +71 -6
- package/sdk-core/protos/api_upstream/temporal/api/version/v1/message.proto +2 -2
- package/sdk-core/protos/api_upstream/temporal/api/workflow/v1/message.proto +2 -2
- package/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +64 -28
- package/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +4 -4
- package/sdk-core/protos/local/temporal/sdk/core/activity_result/activity_result.proto +7 -8
- package/sdk-core/protos/local/temporal/sdk/core/activity_task/activity_task.proto +10 -7
- package/sdk-core/protos/local/temporal/sdk/core/child_workflow/child_workflow.proto +19 -30
- package/sdk-core/protos/local/temporal/sdk/core/common/common.proto +1 -0
- package/sdk-core/protos/local/temporal/sdk/core/core_interface.proto +1 -0
- package/sdk-core/protos/local/temporal/sdk/core/external_data/external_data.proto +8 -0
- package/sdk-core/protos/local/temporal/sdk/core/workflow_activation/workflow_activation.proto +67 -60
- package/sdk-core/protos/local/temporal/sdk/core/workflow_commands/workflow_commands.proto +85 -84
- package/sdk-core/protos/local/temporal/sdk/core/workflow_completion/workflow_completion.proto +9 -3
- package/sdk-core/protos/testsrv_upstream/temporal/api/testservice/v1/request_response.proto +2 -2
- package/sdk-core/protos/testsrv_upstream/temporal/api/testservice/v1/service.proto +2 -2
- package/sdk-core/sdk/Cargo.toml +5 -4
- package/sdk-core/sdk/src/lib.rs +108 -26
- package/sdk-core/sdk/src/workflow_context/options.rs +7 -1
- package/sdk-core/sdk/src/workflow_context.rs +24 -17
- package/sdk-core/sdk/src/workflow_future.rs +16 -15
- package/sdk-core/sdk-core-protos/Cargo.toml +5 -2
- package/sdk-core/sdk-core-protos/build.rs +36 -2
- package/sdk-core/sdk-core-protos/src/history_builder.rs +138 -106
- package/sdk-core/sdk-core-protos/src/history_info.rs +10 -1
- package/sdk-core/sdk-core-protos/src/lib.rs +272 -87
- package/sdk-core/sdk-core-protos/src/task_token.rs +12 -2
- package/sdk-core/test-utils/Cargo.toml +3 -1
- package/sdk-core/test-utils/src/canned_histories.rs +106 -296
- package/sdk-core/test-utils/src/histfetch.rs +1 -1
- package/sdk-core/test-utils/src/lib.rs +82 -23
- package/sdk-core/test-utils/src/wf_input_saver.rs +50 -0
- package/sdk-core/test-utils/src/workflows.rs +29 -0
- package/sdk-core/tests/fuzzy_workflow.rs +130 -0
- package/sdk-core/tests/{load_tests.rs → heavy_tests.rs} +125 -51
- package/sdk-core/tests/integ_tests/ephemeral_server_tests.rs +25 -3
- package/sdk-core/tests/integ_tests/heartbeat_tests.rs +10 -5
- package/sdk-core/tests/integ_tests/metrics_tests.rs +218 -16
- package/sdk-core/tests/integ_tests/polling_tests.rs +4 -47
- package/sdk-core/tests/integ_tests/queries_tests.rs +5 -128
- package/sdk-core/tests/integ_tests/visibility_tests.rs +83 -25
- package/sdk-core/tests/integ_tests/workflow_tests/activities.rs +161 -72
- package/sdk-core/tests/integ_tests/workflow_tests/cancel_external.rs +1 -0
- package/sdk-core/tests/integ_tests/workflow_tests/cancel_wf.rs +6 -13
- package/sdk-core/tests/integ_tests/workflow_tests/child_workflows.rs +80 -3
- package/sdk-core/tests/integ_tests/workflow_tests/continue_as_new.rs +6 -2
- package/sdk-core/tests/integ_tests/workflow_tests/determinism.rs +3 -10
- package/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +94 -200
- package/sdk-core/tests/integ_tests/workflow_tests/modify_wf_properties.rs +2 -4
- package/sdk-core/tests/integ_tests/workflow_tests/patches.rs +34 -28
- package/sdk-core/tests/integ_tests/workflow_tests/replay.rs +76 -7
- package/sdk-core/tests/integ_tests/workflow_tests/resets.rs +1 -0
- package/sdk-core/tests/integ_tests/workflow_tests/signals.rs +18 -14
- package/sdk-core/tests/integ_tests/workflow_tests/stickyness.rs +6 -20
- package/sdk-core/tests/integ_tests/workflow_tests/timers.rs +10 -21
- package/sdk-core/tests/integ_tests/workflow_tests/upsert_search_attrs.rs +7 -8
- package/sdk-core/tests/integ_tests/workflow_tests.rs +13 -14
- package/sdk-core/tests/main.rs +3 -13
- package/sdk-core/tests/runner.rs +75 -36
- package/sdk-core/tests/wf_input_replay.rs +32 -0
- package/src/conversions.rs +14 -8
- package/src/runtime.rs +9 -8
- package/ts/index.ts +8 -6
- package/sdk-core/bridge-ffi/Cargo.toml +0 -24
- package/sdk-core/bridge-ffi/LICENSE.txt +0 -23
- package/sdk-core/bridge-ffi/build.rs +0 -25
- package/sdk-core/bridge-ffi/include/sdk-core-bridge.h +0 -224
- package/sdk-core/bridge-ffi/src/lib.rs +0 -746
- package/sdk-core/bridge-ffi/src/wrappers.rs +0 -221
- package/sdk-core/protos/local/temporal/sdk/core/bridge/bridge.proto +0 -210
- package/sdk-core/sdk/src/conversions.rs +0 -8
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
use crate::{AttachMetricLabels, LONG_POLL_METHOD_NAMES};
|
|
2
2
|
use futures::{future::BoxFuture, FutureExt};
|
|
3
3
|
use opentelemetry::{
|
|
4
|
-
metrics::{Counter, Histogram
|
|
4
|
+
metrics::{Counter, Histogram},
|
|
5
5
|
KeyValue,
|
|
6
6
|
};
|
|
7
7
|
use std::{
|
|
@@ -30,18 +30,27 @@ pub struct MetricsContext {
|
|
|
30
30
|
long_svc_request_latency: Histogram<u64>,
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
+
/// Things that can provide metrics for the client implement this. Trait exists to avoid having
|
|
34
|
+
/// to make a whole new lower-level crate just for a tiny shared wrapper around OTel meters.
|
|
35
|
+
pub trait ClientMetricProvider: Send + Sync {
|
|
36
|
+
/// Construct a counter metric
|
|
37
|
+
fn counter(&self, name: &'static str) -> Counter<u64>;
|
|
38
|
+
/// Construct a histogram metric
|
|
39
|
+
fn histogram(&self, name: &'static str) -> Histogram<u64>;
|
|
40
|
+
}
|
|
41
|
+
|
|
33
42
|
impl MetricsContext {
|
|
34
|
-
pub(crate) fn new(kvs: Vec<KeyValue>,
|
|
43
|
+
pub(crate) fn new(kvs: Vec<KeyValue>, metric_provider: &dyn ClientMetricProvider) -> Self {
|
|
35
44
|
Self {
|
|
36
45
|
ctx: opentelemetry::Context::current(),
|
|
37
46
|
kvs: Arc::new(kvs),
|
|
38
47
|
poll_is_long: false,
|
|
39
|
-
svc_request:
|
|
40
|
-
svc_request_failed:
|
|
41
|
-
long_svc_request:
|
|
42
|
-
long_svc_request_failed:
|
|
43
|
-
svc_request_latency:
|
|
44
|
-
long_svc_request_latency:
|
|
48
|
+
svc_request: metric_provider.counter("request"),
|
|
49
|
+
svc_request_failed: metric_provider.counter("request_failure"),
|
|
50
|
+
long_svc_request: metric_provider.counter("long_request"),
|
|
51
|
+
long_svc_request_failed: metric_provider.counter("long_request_failure"),
|
|
52
|
+
svc_request_latency: metric_provider.histogram("request_latency"),
|
|
53
|
+
long_svc_request_latency: metric_provider.histogram("long_request_latency"),
|
|
45
54
|
}
|
|
46
55
|
}
|
|
47
56
|
|
|
@@ -760,9 +760,9 @@ proxier! {
|
|
|
760
760
|
}
|
|
761
761
|
);
|
|
762
762
|
(
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
763
|
+
update_workflow_execution,
|
|
764
|
+
UpdateWorkflowExecutionRequest,
|
|
765
|
+
UpdateWorkflowExecutionResponse,
|
|
766
766
|
|r| {
|
|
767
767
|
let labels = AttachMetricLabels::namespace(r.get_ref().namespace.clone());
|
|
768
768
|
r.extensions_mut().insert(labels);
|
|
@@ -898,7 +898,7 @@ mod tests {
|
|
|
898
898
|
let no_underscores: HashSet<_> = impl_list.iter().map(|x| x.replace('_', "")).collect();
|
|
899
899
|
for method in methods {
|
|
900
900
|
if !no_underscores.contains(&method.to_lowercase()) {
|
|
901
|
-
panic!("RPC method {} is not implemented by raw client"
|
|
901
|
+
panic!("RPC method {method} is not implemented by raw client")
|
|
902
902
|
}
|
|
903
903
|
}
|
|
904
904
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
use crate::{
|
|
2
|
-
ClientOptions, ListClosedFilters, ListOpenFilters, Namespace,
|
|
3
|
-
StartTimeFilter, WorkflowClientTrait, WorkflowOptions,
|
|
2
|
+
ClientOptions, ListClosedFilters, ListOpenFilters, Namespace, RegisterNamespaceOptions, Result,
|
|
3
|
+
RetryConfig, SignalWithStartOptions, StartTimeFilter, WorkflowClientTrait, WorkflowOptions,
|
|
4
4
|
};
|
|
5
5
|
use backoff::{backoff::Backoff, exponential::ExponentialBackoff, Clock, SystemClock};
|
|
6
6
|
use futures_retry::{ErrorHandler, FutureRetry, RetryPolicy};
|
|
@@ -8,7 +8,7 @@ use std::{fmt::Debug, future::Future, sync::Arc, time::Duration};
|
|
|
8
8
|
use temporal_sdk_core_protos::{
|
|
9
9
|
coresdk::workflow_commands::QueryResult,
|
|
10
10
|
temporal::api::{
|
|
11
|
-
common::v1::{
|
|
11
|
+
common::v1::{Payload, Payloads},
|
|
12
12
|
enums::v1::WorkflowTaskFailedCause,
|
|
13
13
|
failure::v1::Failure,
|
|
14
14
|
query::v1::WorkflowQuery,
|
|
@@ -362,28 +362,14 @@ where
|
|
|
362
362
|
|
|
363
363
|
async fn signal_with_start_workflow_execution(
|
|
364
364
|
&self,
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
workflow_id: String,
|
|
368
|
-
workflow_type: String,
|
|
369
|
-
request_id: Option<String>,
|
|
370
|
-
options: WorkflowOptions,
|
|
371
|
-
signal_name: String,
|
|
372
|
-
signal_input: Option<Payloads>,
|
|
373
|
-
signal_header: Option<Header>,
|
|
365
|
+
options: SignalWithStartOptions,
|
|
366
|
+
workflow_options: WorkflowOptions,
|
|
374
367
|
) -> Result<SignalWithStartWorkflowExecutionResponse> {
|
|
375
368
|
retry_call!(
|
|
376
369
|
self,
|
|
377
370
|
signal_with_start_workflow_execution,
|
|
378
|
-
input.clone(),
|
|
379
|
-
task_queue.clone(),
|
|
380
|
-
workflow_id.clone(),
|
|
381
|
-
workflow_type.clone(),
|
|
382
|
-
request_id.clone(),
|
|
383
371
|
options.clone(),
|
|
384
|
-
|
|
385
|
-
signal_input.clone(),
|
|
386
|
-
signal_header.clone()
|
|
372
|
+
workflow_options.clone()
|
|
387
373
|
)
|
|
388
374
|
}
|
|
389
375
|
|
|
@@ -473,6 +459,13 @@ where
|
|
|
473
459
|
)
|
|
474
460
|
}
|
|
475
461
|
|
|
462
|
+
async fn register_namespace(
|
|
463
|
+
&self,
|
|
464
|
+
options: RegisterNamespaceOptions,
|
|
465
|
+
) -> Result<RegisterNamespaceResponse> {
|
|
466
|
+
retry_call!(self, register_namespace, options.clone())
|
|
467
|
+
}
|
|
468
|
+
|
|
476
469
|
async fn list_namespaces(&self) -> Result<ListNamespacesResponse> {
|
|
477
470
|
retry_call!(self, list_namespaces,)
|
|
478
471
|
}
|
|
@@ -530,6 +523,25 @@ where
|
|
|
530
523
|
)
|
|
531
524
|
}
|
|
532
525
|
|
|
526
|
+
async fn list_archived_workflow_executions(
|
|
527
|
+
&self,
|
|
528
|
+
page_size: i32,
|
|
529
|
+
next_page_token: Vec<u8>,
|
|
530
|
+
query: String,
|
|
531
|
+
) -> Result<ListArchivedWorkflowExecutionsResponse> {
|
|
532
|
+
retry_call!(
|
|
533
|
+
self,
|
|
534
|
+
list_archived_workflow_executions,
|
|
535
|
+
page_size,
|
|
536
|
+
next_page_token.clone(),
|
|
537
|
+
query.clone()
|
|
538
|
+
)
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
async fn get_search_attributes(&self) -> Result<GetSearchAttributesResponse> {
|
|
542
|
+
retry_call!(self, get_search_attributes)
|
|
543
|
+
}
|
|
544
|
+
|
|
533
545
|
fn get_options(&self) -> &ClientOptions {
|
|
534
546
|
self.client.get_options()
|
|
535
547
|
}
|
package/sdk-core/core/Cargo.toml
CHANGED
|
@@ -12,12 +12,17 @@ categories = ["development-tools"]
|
|
|
12
12
|
|
|
13
13
|
[lib]
|
|
14
14
|
|
|
15
|
+
[features]
|
|
16
|
+
# Do not enable this feature when building production SDKs. If we ever want a user in the field to
|
|
17
|
+
# record WF input data, we can build them a custom SDK or they can build - it adds significant extra
|
|
18
|
+
# code size in the form of [de]serializers.
|
|
19
|
+
save_wf_inputs = ["rmp-serde", "temporal-sdk-core-protos/serde_serialize"]
|
|
20
|
+
|
|
15
21
|
[dependencies]
|
|
16
22
|
anyhow = "1.0"
|
|
17
23
|
arc-swap = "1.3"
|
|
18
|
-
async-channel = "1.6"
|
|
19
24
|
async-trait = "0.1"
|
|
20
|
-
base64 = "0.
|
|
25
|
+
base64 = "0.21"
|
|
21
26
|
crossbeam = "0.8"
|
|
22
27
|
dashmap = "5.0"
|
|
23
28
|
derive_builder = "0.12"
|
|
@@ -31,8 +36,7 @@ http = "0.2"
|
|
|
31
36
|
hyper = "0.14"
|
|
32
37
|
itertools = "0.10"
|
|
33
38
|
lazy_static = "1.4"
|
|
34
|
-
|
|
35
|
-
lru = "0.8"
|
|
39
|
+
lru = "0.10"
|
|
36
40
|
mockall = "0.11"
|
|
37
41
|
nix = "0.26"
|
|
38
42
|
once_cell = "1.5"
|
|
@@ -40,29 +44,31 @@ opentelemetry = { version = "0.18", features = ["rt-tokio"] }
|
|
|
40
44
|
opentelemetry-otlp = { version = "0.11", features = ["tokio", "metrics"] }
|
|
41
45
|
opentelemetry-prometheus = "0.11"
|
|
42
46
|
parking_lot = { version = "0.12", features = ["send_guard"] }
|
|
47
|
+
pin-project = "1.0"
|
|
43
48
|
prometheus = "0.13"
|
|
44
49
|
prost = "0.11"
|
|
45
|
-
prost-types = "0.
|
|
50
|
+
prost-types = { version = "0.4", package = "prost-wkt-types" }
|
|
46
51
|
rand = "0.8.3"
|
|
47
52
|
reqwest = { version = "0.11", features = ["json", "stream", "rustls-tls", "tokio-rustls"], default-features = false }
|
|
48
53
|
ringbuf = "0.3"
|
|
54
|
+
rmp-serde = { version = "1.1", optional = true }
|
|
49
55
|
serde = "1.0"
|
|
50
56
|
serde_json = "1.0"
|
|
51
57
|
siphasher = "0.3"
|
|
52
58
|
slotmap = "1.0"
|
|
53
59
|
tar = "0.4"
|
|
54
60
|
thiserror = "1.0"
|
|
55
|
-
tokio = { version = "1.
|
|
61
|
+
tokio = { version = "1.26", features = ["rt", "rt-multi-thread", "parking_lot", "time", "fs", "process"] }
|
|
56
62
|
tokio-util = { version = "0.7", features = ["io", "io-util"] }
|
|
57
63
|
tokio-stream = "0.1"
|
|
58
64
|
tonic = { version = "0.8", features = ["tls", "tls-roots"] }
|
|
59
|
-
tracing =
|
|
65
|
+
tracing = "0.1"
|
|
60
66
|
tracing-futures = "0.2"
|
|
61
67
|
tracing-opentelemetry = "0.18"
|
|
62
68
|
tracing-subscriber = { version = "0.3", features = ["parking_lot", "env-filter", "registry"] }
|
|
63
69
|
url = "2.2"
|
|
64
70
|
uuid = { version = "1.1", features = ["v4"] }
|
|
65
|
-
zip = "0.6"
|
|
71
|
+
zip = "0.6.3"
|
|
66
72
|
|
|
67
73
|
# 1st party local deps
|
|
68
74
|
[dependencies.temporal-sdk-core-api]
|
|
@@ -85,8 +91,9 @@ version = "0.1"
|
|
|
85
91
|
[dev-dependencies]
|
|
86
92
|
assert_matches = "1.4"
|
|
87
93
|
bimap = "0.6.1"
|
|
94
|
+
clap = { version = "4.0", features = ["derive"] }
|
|
88
95
|
criterion = "0.4"
|
|
89
|
-
rstest = "0.
|
|
96
|
+
rstest = "0.17"
|
|
90
97
|
temporal-sdk-core-test-utils = { path = "../test-utils" }
|
|
91
98
|
temporal-sdk = { path = "../sdk" }
|
|
92
99
|
|
|
@@ -101,9 +108,10 @@ path = "../tests/main.rs"
|
|
|
101
108
|
test = false
|
|
102
109
|
|
|
103
110
|
[[test]]
|
|
104
|
-
name = "
|
|
105
|
-
path = "../tests/
|
|
111
|
+
name = "heavy_tests"
|
|
112
|
+
path = "../tests/heavy_tests.rs"
|
|
106
113
|
test = false
|
|
114
|
+
required-features = ["save_wf_inputs"]
|
|
107
115
|
|
|
108
116
|
[[bench]]
|
|
109
117
|
name = "workflow_replay"
|
|
@@ -113,4 +121,9 @@ harness = false
|
|
|
113
121
|
# the dev-dependencies, which we want.
|
|
114
122
|
[[example]]
|
|
115
123
|
name = "integ_runner"
|
|
116
|
-
path = "../tests/runner.rs"
|
|
124
|
+
path = "../tests/runner.rs"
|
|
125
|
+
|
|
126
|
+
[[example]]
|
|
127
|
+
name = "wf_input_replay"
|
|
128
|
+
path = "../tests/wf_input_replay.rs"
|
|
129
|
+
required-features = ["save_wf_inputs"]
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
use parking_lot::Mutex;
|
|
2
|
+
use std::sync::atomic::{AtomicBool, Ordering};
|
|
3
|
+
|
|
4
|
+
/// Implements something a bit like a `OnceCell`, but starts already initialized and allows you
|
|
5
|
+
/// to take everything out of it only once in a thread-safe way. This isn't optimized for super
|
|
6
|
+
/// fast-path usage.
|
|
7
|
+
pub struct TakeCell<T> {
|
|
8
|
+
taken: AtomicBool,
|
|
9
|
+
data: Mutex<Option<T>>,
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
impl<T> TakeCell<T> {
|
|
13
|
+
pub fn new(val: T) -> Self {
|
|
14
|
+
Self {
|
|
15
|
+
taken: AtomicBool::new(false),
|
|
16
|
+
data: Mutex::new(Some(val)),
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/// If the cell has not already been taken from, takes the value and returns it
|
|
21
|
+
pub fn take_once(&self) -> Option<T> {
|
|
22
|
+
if self.taken.load(Ordering::Acquire) {
|
|
23
|
+
return None;
|
|
24
|
+
}
|
|
25
|
+
self.taken.store(true, Ordering::Release);
|
|
26
|
+
self.data.lock().take()
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -1,18 +1,30 @@
|
|
|
1
1
|
//! This module contains very generic helpers that can be used codebase-wide
|
|
2
2
|
|
|
3
|
+
pub mod take_cell;
|
|
4
|
+
|
|
3
5
|
use crate::MetricsContext;
|
|
6
|
+
use derive_more::DebugCustom;
|
|
4
7
|
use futures::{stream, Stream, StreamExt};
|
|
5
8
|
use std::{
|
|
6
9
|
fmt::{Debug, Formatter},
|
|
7
|
-
sync::
|
|
10
|
+
sync::{
|
|
11
|
+
atomic::{AtomicBool, AtomicUsize, Ordering},
|
|
12
|
+
Arc,
|
|
13
|
+
},
|
|
8
14
|
};
|
|
9
15
|
use tokio::sync::{AcquireError, OwnedSemaphorePermit, Semaphore, TryAcquireError};
|
|
16
|
+
use tokio_util::sync::CancellationToken;
|
|
10
17
|
|
|
11
18
|
/// Wraps a [Semaphore] with a function call that is fed the available permits any time a permit is
|
|
12
19
|
/// acquired or restored through the provided methods
|
|
13
20
|
#[derive(Clone)]
|
|
14
21
|
pub(crate) struct MeteredSemaphore {
|
|
15
22
|
sem: Arc<Semaphore>,
|
|
23
|
+
/// The number of permit owners who have acquired a permit from the semaphore, but are not yet
|
|
24
|
+
/// meaningfully using that permit. This is useful for giving a more semantically accurate count
|
|
25
|
+
/// of used task slots, since we typically wait for a permit first before polling, but that slot
|
|
26
|
+
/// isn't used in the sense the user expects until we actually also get the corresponding task.
|
|
27
|
+
unused_claimants: Arc<AtomicUsize>,
|
|
16
28
|
metrics_ctx: MetricsContext,
|
|
17
29
|
record_fn: fn(&MetricsContext, usize),
|
|
18
30
|
}
|
|
@@ -25,6 +37,7 @@ impl MeteredSemaphore {
|
|
|
25
37
|
) -> Self {
|
|
26
38
|
Self {
|
|
27
39
|
sem: Arc::new(Semaphore::new(inital_permits)),
|
|
40
|
+
unused_claimants: Arc::new(AtomicUsize::new(0)),
|
|
28
41
|
metrics_ctx,
|
|
29
42
|
record_fn,
|
|
30
43
|
}
|
|
@@ -36,42 +49,154 @@ impl MeteredSemaphore {
|
|
|
36
49
|
|
|
37
50
|
pub async fn acquire_owned(&self) -> Result<OwnedMeteredSemPermit, AcquireError> {
|
|
38
51
|
let res = self.sem.clone().acquire_owned().await?;
|
|
39
|
-
self.
|
|
40
|
-
Ok(OwnedMeteredSemPermit {
|
|
41
|
-
inner: res,
|
|
42
|
-
record_fn: self.record_drop_owned(),
|
|
43
|
-
})
|
|
52
|
+
Ok(self.build_owned(res))
|
|
44
53
|
}
|
|
45
54
|
|
|
46
55
|
pub fn try_acquire_owned(&self) -> Result<OwnedMeteredSemPermit, TryAcquireError> {
|
|
47
56
|
let res = self.sem.clone().try_acquire_owned()?;
|
|
57
|
+
Ok(self.build_owned(res))
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
fn build_owned(&self, res: OwnedSemaphorePermit) -> OwnedMeteredSemPermit {
|
|
61
|
+
self.unused_claimants.fetch_add(1, Ordering::Release);
|
|
48
62
|
self.record();
|
|
49
|
-
|
|
63
|
+
OwnedMeteredSemPermit {
|
|
50
64
|
inner: res,
|
|
51
|
-
|
|
52
|
-
|
|
65
|
+
unused_claimants: Some(self.unused_claimants.clone()),
|
|
66
|
+
record_fn: self.record_owned(),
|
|
67
|
+
}
|
|
53
68
|
}
|
|
54
69
|
|
|
55
70
|
fn record(&self) {
|
|
56
|
-
(self.record_fn)(
|
|
71
|
+
(self.record_fn)(
|
|
72
|
+
&self.metrics_ctx,
|
|
73
|
+
self.sem.available_permits() + self.unused_claimants.load(Ordering::Acquire),
|
|
74
|
+
);
|
|
57
75
|
}
|
|
58
76
|
|
|
59
|
-
fn
|
|
77
|
+
fn record_owned(&self) -> Box<dyn Fn(bool) + Send + Sync> {
|
|
60
78
|
let rcf = self.record_fn;
|
|
61
79
|
let mets = self.metrics_ctx.clone();
|
|
62
80
|
let sem = self.sem.clone();
|
|
63
|
-
|
|
81
|
+
let uc = self.unused_claimants.clone();
|
|
82
|
+
// When being called from the drop impl, the semaphore permit isn't actually dropped yet,
|
|
83
|
+
// so account for that.
|
|
84
|
+
Box::new(move |add_one: bool| {
|
|
85
|
+
let extra = usize::from(add_one);
|
|
86
|
+
rcf(
|
|
87
|
+
&mets,
|
|
88
|
+
sem.available_permits() + uc.load(Ordering::Acquire) + extra,
|
|
89
|
+
)
|
|
90
|
+
})
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/// A version of [MeteredSemaphore] that can be closed and supports waiting for close to complete.
|
|
95
|
+
/// Once closed, no permits will be handed out.
|
|
96
|
+
/// Close completes when all permits have been returned.
|
|
97
|
+
pub(crate) struct ClosableMeteredSemaphore {
|
|
98
|
+
inner: Arc<MeteredSemaphore>,
|
|
99
|
+
outstanding_permits: AtomicUsize,
|
|
100
|
+
close_requested: AtomicBool,
|
|
101
|
+
close_complete_token: CancellationToken,
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
impl ClosableMeteredSemaphore {
|
|
105
|
+
pub fn new_arc(sem: Arc<MeteredSemaphore>) -> Arc<Self> {
|
|
106
|
+
Arc::new(Self {
|
|
107
|
+
inner: sem,
|
|
108
|
+
outstanding_permits: Default::default(),
|
|
109
|
+
close_requested: AtomicBool::new(false),
|
|
110
|
+
close_complete_token: CancellationToken::new(),
|
|
111
|
+
})
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
impl ClosableMeteredSemaphore {
|
|
116
|
+
#[cfg(test)]
|
|
117
|
+
pub fn available_permits(&self) -> usize {
|
|
118
|
+
self.inner.available_permits()
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/// Request to close the semaphore and prevent new permits from being acquired.
|
|
122
|
+
pub fn close(&self) {
|
|
123
|
+
self.close_requested.store(true, Ordering::Release);
|
|
124
|
+
if self.outstanding_permits.load(Ordering::Acquire) == 0 {
|
|
125
|
+
self.close_complete_token.cancel();
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/// Returns after close has been requested and all outstanding permits have been returned.
|
|
130
|
+
pub async fn close_complete(&self) {
|
|
131
|
+
self.close_complete_token.cancelled().await;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/// Acquire a permit if one is available and close was not requested.
|
|
135
|
+
pub fn try_acquire_owned(
|
|
136
|
+
self: &Arc<Self>,
|
|
137
|
+
) -> Result<TrackedOwnedMeteredSemPermit, TryAcquireError> {
|
|
138
|
+
if self.close_requested.load(Ordering::Acquire) {
|
|
139
|
+
return Err(TryAcquireError::Closed);
|
|
140
|
+
}
|
|
141
|
+
self.outstanding_permits.fetch_add(1, Ordering::Release);
|
|
142
|
+
let res = self.inner.try_acquire_owned();
|
|
143
|
+
if res.is_err() {
|
|
144
|
+
self.outstanding_permits.fetch_sub(1, Ordering::Release);
|
|
145
|
+
}
|
|
146
|
+
res.map(|permit| TrackedOwnedMeteredSemPermit {
|
|
147
|
+
inner: Some(permit),
|
|
148
|
+
on_drop: self.on_permit_dropped(),
|
|
149
|
+
})
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
fn on_permit_dropped(self: &Arc<Self>) -> Box<dyn Fn() + Send + Sync> {
|
|
153
|
+
let sem = self.clone();
|
|
154
|
+
Box::new(move || {
|
|
155
|
+
sem.outstanding_permits.fetch_sub(1, Ordering::Release);
|
|
156
|
+
if sem.close_requested.load(Ordering::Acquire)
|
|
157
|
+
&& sem.outstanding_permits.load(Ordering::Acquire) == 0
|
|
158
|
+
{
|
|
159
|
+
sem.close_complete_token.cancel();
|
|
160
|
+
}
|
|
161
|
+
})
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/// Tracks an OwnedMeteredSemPermit and calls on_drop when dropped.
|
|
166
|
+
#[derive(DebugCustom)]
|
|
167
|
+
#[debug(fmt = "Tracked({inner:?})")]
|
|
168
|
+
pub(crate) struct TrackedOwnedMeteredSemPermit {
|
|
169
|
+
inner: Option<OwnedMeteredSemPermit>,
|
|
170
|
+
on_drop: Box<dyn Fn() + Send + Sync>,
|
|
171
|
+
}
|
|
172
|
+
impl From<TrackedOwnedMeteredSemPermit> for OwnedMeteredSemPermit {
|
|
173
|
+
fn from(mut value: TrackedOwnedMeteredSemPermit) -> Self {
|
|
174
|
+
value
|
|
175
|
+
.inner
|
|
176
|
+
.take()
|
|
177
|
+
.expect("Inner permit should be available")
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
impl Drop for TrackedOwnedMeteredSemPermit {
|
|
181
|
+
fn drop(&mut self) {
|
|
182
|
+
(self.on_drop)();
|
|
64
183
|
}
|
|
65
184
|
}
|
|
66
185
|
|
|
67
186
|
/// Wraps an [OwnedSemaphorePermit] to update metrics when it's dropped
|
|
68
187
|
pub(crate) struct OwnedMeteredSemPermit {
|
|
69
188
|
inner: OwnedSemaphorePermit,
|
|
70
|
-
|
|
189
|
+
/// See [MeteredSemaphore::unused_claimants]. If present when dropping, used to decrement the
|
|
190
|
+
/// count.
|
|
191
|
+
unused_claimants: Option<Arc<AtomicUsize>>,
|
|
192
|
+
record_fn: Box<dyn Fn(bool) + Send + Sync>,
|
|
71
193
|
}
|
|
72
194
|
impl Drop for OwnedMeteredSemPermit {
|
|
73
195
|
fn drop(&mut self) {
|
|
74
|
-
(self.
|
|
196
|
+
if let Some(uc) = self.unused_claimants.take() {
|
|
197
|
+
uc.fetch_sub(1, Ordering::Release);
|
|
198
|
+
}
|
|
199
|
+
(self.record_fn)(true)
|
|
75
200
|
}
|
|
76
201
|
}
|
|
77
202
|
impl Debug for OwnedMeteredSemPermit {
|
|
@@ -79,6 +204,32 @@ impl Debug for OwnedMeteredSemPermit {
|
|
|
79
204
|
self.inner.fmt(f)
|
|
80
205
|
}
|
|
81
206
|
}
|
|
207
|
+
impl OwnedMeteredSemPermit {
|
|
208
|
+
/// Should be called once this permit is actually being "used" for the work it was meant to
|
|
209
|
+
/// permit.
|
|
210
|
+
pub(crate) fn into_used(mut self) -> UsedMeteredSemPermit {
|
|
211
|
+
if let Some(uc) = self.unused_claimants.take() {
|
|
212
|
+
uc.fetch_sub(1, Ordering::Release);
|
|
213
|
+
(self.record_fn)(false)
|
|
214
|
+
}
|
|
215
|
+
UsedMeteredSemPermit(self)
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
#[derive(Debug)]
|
|
220
|
+
pub(crate) struct UsedMeteredSemPermit(OwnedMeteredSemPermit);
|
|
221
|
+
impl UsedMeteredSemPermit {
|
|
222
|
+
#[cfg(feature = "save_wf_inputs")]
|
|
223
|
+
pub(crate) fn fake_deserialized() -> Self {
|
|
224
|
+
let sem = Arc::new(Semaphore::new(1));
|
|
225
|
+
let inner = sem.try_acquire_owned().unwrap();
|
|
226
|
+
Self(OwnedMeteredSemPermit {
|
|
227
|
+
inner,
|
|
228
|
+
unused_claimants: None,
|
|
229
|
+
record_fn: Box::new(|_| {}),
|
|
230
|
+
})
|
|
231
|
+
}
|
|
232
|
+
}
|
|
82
233
|
|
|
83
234
|
/// From the input stream, create a new stream which only pulls from the input stream when allowed.
|
|
84
235
|
/// When allowed is determined by the passed in `proceeder` emitting an item. The input stream is
|
|
@@ -163,4 +314,43 @@ mod tests {
|
|
|
163
314
|
allow_tx.send(()).unwrap();
|
|
164
315
|
assert_eq!(when_allowed.poll_next_unpin(&mut cx), Poll::Ready(None));
|
|
165
316
|
}
|
|
317
|
+
|
|
318
|
+
#[tokio::test]
|
|
319
|
+
async fn closable_semaphore_permit_drop_returns_permit() {
|
|
320
|
+
let inner = MeteredSemaphore::new(2, MetricsContext::no_op(), |_, _| {});
|
|
321
|
+
let sem = ClosableMeteredSemaphore::new_arc(Arc::new(inner));
|
|
322
|
+
let perm = sem.try_acquire_owned().unwrap();
|
|
323
|
+
let permits = sem.outstanding_permits.load(Ordering::Acquire);
|
|
324
|
+
assert_eq!(permits, 1);
|
|
325
|
+
drop(perm);
|
|
326
|
+
let permits = sem.outstanding_permits.load(Ordering::Acquire);
|
|
327
|
+
assert_eq!(permits, 0);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
#[tokio::test]
|
|
331
|
+
async fn closable_semaphore_permit_drop_after_close_resolves_close_complete() {
|
|
332
|
+
let inner = MeteredSemaphore::new(2, MetricsContext::no_op(), |_, _| {});
|
|
333
|
+
let sem = ClosableMeteredSemaphore::new_arc(Arc::new(inner));
|
|
334
|
+
let perm = sem.try_acquire_owned().unwrap();
|
|
335
|
+
sem.close();
|
|
336
|
+
drop(perm);
|
|
337
|
+
sem.close_complete().await;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
#[tokio::test]
|
|
341
|
+
async fn closable_semaphore_close_complete_ready_if_unused() {
|
|
342
|
+
let inner = MeteredSemaphore::new(2, MetricsContext::no_op(), |_, _| {});
|
|
343
|
+
let sem = ClosableMeteredSemaphore::new_arc(Arc::new(inner));
|
|
344
|
+
sem.close();
|
|
345
|
+
sem.close_complete().await;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
#[tokio::test]
|
|
349
|
+
async fn closable_semaphore_does_not_hand_out_permits_after_closed() {
|
|
350
|
+
let inner = MeteredSemaphore::new(2, MetricsContext::no_op(), |_, _| {});
|
|
351
|
+
let sem = ClosableMeteredSemaphore::new_arc(Arc::new(inner));
|
|
352
|
+
sem.close();
|
|
353
|
+
let perm = sem.try_acquire_owned().unwrap_err();
|
|
354
|
+
assert_matches!(perm, TryAcquireError::Closed);
|
|
355
|
+
}
|
|
166
356
|
}
|