temporalio 0.0.2 → 0.1.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.
Files changed (202) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +25 -23
  3. data/bridge/Cargo.lock +168 -59
  4. data/bridge/Cargo.toml +4 -2
  5. data/bridge/sdk-core/README.md +19 -6
  6. data/bridge/sdk-core/client/src/lib.rs +215 -39
  7. data/bridge/sdk-core/client/src/metrics.rs +17 -8
  8. data/bridge/sdk-core/client/src/raw.rs +4 -4
  9. data/bridge/sdk-core/client/src/retry.rs +32 -20
  10. data/bridge/sdk-core/core/Cargo.toml +22 -9
  11. data/bridge/sdk-core/core/src/abstractions.rs +203 -14
  12. data/bridge/sdk-core/core/src/core_tests/activity_tasks.rs +76 -41
  13. data/bridge/sdk-core/core/src/core_tests/determinism.rs +165 -2
  14. data/bridge/sdk-core/core/src/core_tests/local_activities.rs +204 -83
  15. data/bridge/sdk-core/core/src/core_tests/queries.rs +3 -4
  16. data/bridge/sdk-core/core/src/core_tests/workers.rs +1 -3
  17. data/bridge/sdk-core/core/src/core_tests/workflow_tasks.rs +397 -54
  18. data/bridge/sdk-core/core/src/ephemeral_server/mod.rs +106 -12
  19. data/bridge/sdk-core/core/src/internal_flags.rs +136 -0
  20. data/bridge/sdk-core/core/src/lib.rs +16 -9
  21. data/bridge/sdk-core/core/src/telemetry/log_export.rs +1 -1
  22. data/bridge/sdk-core/core/src/telemetry/metrics.rs +69 -35
  23. data/bridge/sdk-core/core/src/telemetry/mod.rs +29 -13
  24. data/bridge/sdk-core/core/src/telemetry/prometheus_server.rs +17 -12
  25. data/bridge/sdk-core/core/src/test_help/mod.rs +62 -12
  26. data/bridge/sdk-core/core/src/worker/activities/activity_heartbeat_manager.rs +112 -156
  27. data/bridge/sdk-core/core/src/worker/activities/activity_task_poller_stream.rs +89 -0
  28. data/bridge/sdk-core/core/src/worker/activities/local_activities.rs +352 -122
  29. data/bridge/sdk-core/core/src/worker/activities.rs +233 -157
  30. data/bridge/sdk-core/core/src/worker/client/mocks.rs +22 -2
  31. data/bridge/sdk-core/core/src/worker/client.rs +18 -2
  32. data/bridge/sdk-core/core/src/worker/mod.rs +165 -58
  33. data/bridge/sdk-core/core/src/worker/workflow/bridge.rs +1 -3
  34. data/bridge/sdk-core/core/src/worker/workflow/driven_workflow.rs +3 -5
  35. data/bridge/sdk-core/core/src/worker/workflow/history_update.rs +856 -277
  36. data/bridge/sdk-core/core/src/worker/workflow/machines/activity_state_machine.rs +100 -43
  37. data/bridge/sdk-core/core/src/worker/workflow/machines/cancel_external_state_machine.rs +7 -7
  38. data/bridge/sdk-core/core/src/worker/workflow/machines/cancel_workflow_state_machine.rs +5 -4
  39. data/bridge/sdk-core/core/src/worker/workflow/machines/child_workflow_state_machine.rs +87 -27
  40. data/bridge/sdk-core/core/src/worker/workflow/machines/complete_workflow_state_machine.rs +5 -4
  41. data/bridge/sdk-core/core/src/worker/workflow/machines/continue_as_new_workflow_state_machine.rs +5 -4
  42. data/bridge/sdk-core/core/src/worker/workflow/machines/fail_workflow_state_machine.rs +5 -4
  43. data/bridge/sdk-core/core/src/worker/workflow/machines/local_activity_state_machine.rs +137 -62
  44. data/bridge/sdk-core/core/src/worker/workflow/machines/mod.rs +25 -17
  45. data/bridge/sdk-core/core/src/worker/workflow/machines/modify_workflow_properties_state_machine.rs +7 -6
  46. data/bridge/sdk-core/core/src/worker/workflow/machines/patch_state_machine.rs +103 -152
  47. data/bridge/sdk-core/core/src/worker/workflow/machines/signal_external_state_machine.rs +7 -7
  48. data/bridge/sdk-core/core/src/worker/workflow/machines/timer_state_machine.rs +9 -9
  49. data/bridge/sdk-core/core/src/worker/workflow/machines/transition_coverage.rs +2 -2
  50. data/bridge/sdk-core/core/src/worker/workflow/machines/upsert_search_attributes_state_machine.rs +14 -7
  51. data/bridge/sdk-core/core/src/worker/workflow/machines/workflow_machines/local_acts.rs +5 -16
  52. data/bridge/sdk-core/core/src/worker/workflow/machines/workflow_machines.rs +201 -121
  53. data/bridge/sdk-core/core/src/worker/workflow/machines/workflow_task_state_machine.rs +11 -14
  54. data/bridge/sdk-core/core/src/worker/workflow/managed_run/managed_wf_test.rs +30 -15
  55. data/bridge/sdk-core/core/src/worker/workflow/managed_run.rs +1026 -376
  56. data/bridge/sdk-core/core/src/worker/workflow/mod.rs +460 -384
  57. data/bridge/sdk-core/core/src/worker/workflow/run_cache.rs +40 -57
  58. data/bridge/sdk-core/core/src/worker/workflow/wft_extraction.rs +125 -0
  59. data/bridge/sdk-core/core/src/worker/workflow/wft_poller.rs +1 -4
  60. data/bridge/sdk-core/core/src/worker/workflow/workflow_stream/saved_wf_inputs.rs +117 -0
  61. data/bridge/sdk-core/core/src/worker/workflow/workflow_stream/tonic_status_serde.rs +24 -0
  62. data/bridge/sdk-core/core/src/worker/workflow/workflow_stream.rs +448 -718
  63. data/bridge/sdk-core/core-api/Cargo.toml +2 -1
  64. data/bridge/sdk-core/core-api/src/errors.rs +1 -34
  65. data/bridge/sdk-core/core-api/src/lib.rs +6 -2
  66. data/bridge/sdk-core/core-api/src/telemetry.rs +0 -6
  67. data/bridge/sdk-core/core-api/src/worker.rs +14 -1
  68. data/bridge/sdk-core/fsm/rustfsm_procmacro/src/lib.rs +18 -15
  69. data/bridge/sdk-core/fsm/rustfsm_trait/src/lib.rs +8 -3
  70. data/bridge/sdk-core/histories/evict_while_la_running_no_interference-16_history.bin +0 -0
  71. data/bridge/sdk-core/protos/api_upstream/temporal/api/command/v1/message.proto +5 -17
  72. data/bridge/sdk-core/protos/api_upstream/temporal/api/common/v1/message.proto +11 -0
  73. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/command_type.proto +1 -6
  74. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/event_type.proto +6 -6
  75. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/failed_cause.proto +5 -0
  76. data/bridge/sdk-core/protos/api_upstream/temporal/api/enums/v1/update.proto +22 -6
  77. data/bridge/sdk-core/protos/api_upstream/temporal/api/history/v1/message.proto +48 -19
  78. data/bridge/sdk-core/protos/api_upstream/temporal/api/namespace/v1/message.proto +2 -0
  79. data/bridge/sdk-core/protos/api_upstream/temporal/api/operatorservice/v1/request_response.proto +3 -0
  80. data/bridge/sdk-core/protos/api_upstream/temporal/api/{enums/v1/interaction_type.proto → protocol/v1/message.proto} +29 -11
  81. data/bridge/sdk-core/protos/api_upstream/temporal/api/sdk/v1/task_complete_metadata.proto +63 -0
  82. data/bridge/sdk-core/protos/api_upstream/temporal/api/update/v1/message.proto +111 -0
  83. data/bridge/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/request_response.proto +59 -28
  84. data/bridge/sdk-core/protos/api_upstream/temporal/api/workflowservice/v1/service.proto +2 -2
  85. data/bridge/sdk-core/protos/local/temporal/sdk/core/activity_result/activity_result.proto +1 -0
  86. data/bridge/sdk-core/protos/local/temporal/sdk/core/activity_task/activity_task.proto +1 -0
  87. data/bridge/sdk-core/protos/local/temporal/sdk/core/child_workflow/child_workflow.proto +1 -0
  88. data/bridge/sdk-core/protos/local/temporal/sdk/core/common/common.proto +1 -0
  89. data/bridge/sdk-core/protos/local/temporal/sdk/core/core_interface.proto +1 -0
  90. data/bridge/sdk-core/protos/local/temporal/sdk/core/external_data/external_data.proto +1 -0
  91. data/bridge/sdk-core/protos/local/temporal/sdk/core/workflow_activation/workflow_activation.proto +7 -0
  92. data/bridge/sdk-core/protos/local/temporal/sdk/core/workflow_commands/workflow_commands.proto +1 -0
  93. data/bridge/sdk-core/protos/local/temporal/sdk/core/workflow_completion/workflow_completion.proto +6 -0
  94. data/bridge/sdk-core/sdk/Cargo.toml +3 -2
  95. data/bridge/sdk-core/sdk/src/lib.rs +87 -20
  96. data/bridge/sdk-core/sdk/src/workflow_future.rs +9 -8
  97. data/bridge/sdk-core/sdk-core-protos/Cargo.toml +5 -2
  98. data/bridge/sdk-core/sdk-core-protos/build.rs +36 -1
  99. data/bridge/sdk-core/sdk-core-protos/src/history_builder.rs +100 -87
  100. data/bridge/sdk-core/sdk-core-protos/src/history_info.rs +5 -1
  101. data/bridge/sdk-core/sdk-core-protos/src/lib.rs +175 -57
  102. data/bridge/sdk-core/sdk-core-protos/src/task_token.rs +12 -2
  103. data/bridge/sdk-core/test-utils/Cargo.toml +3 -1
  104. data/bridge/sdk-core/test-utils/src/canned_histories.rs +106 -296
  105. data/bridge/sdk-core/test-utils/src/histfetch.rs +1 -1
  106. data/bridge/sdk-core/test-utils/src/lib.rs +82 -23
  107. data/bridge/sdk-core/test-utils/src/wf_input_saver.rs +50 -0
  108. data/bridge/sdk-core/test-utils/src/workflows.rs +29 -0
  109. data/bridge/sdk-core/tests/fuzzy_workflow.rs +130 -0
  110. data/bridge/sdk-core/tests/{load_tests.rs → heavy_tests.rs} +125 -51
  111. data/bridge/sdk-core/tests/integ_tests/ephemeral_server_tests.rs +25 -3
  112. data/bridge/sdk-core/tests/integ_tests/heartbeat_tests.rs +5 -3
  113. data/bridge/sdk-core/tests/integ_tests/metrics_tests.rs +218 -16
  114. data/bridge/sdk-core/tests/integ_tests/polling_tests.rs +4 -47
  115. data/bridge/sdk-core/tests/integ_tests/queries_tests.rs +5 -128
  116. data/bridge/sdk-core/tests/integ_tests/visibility_tests.rs +83 -25
  117. data/bridge/sdk-core/tests/integ_tests/workflow_tests/activities.rs +93 -69
  118. data/bridge/sdk-core/tests/integ_tests/workflow_tests/cancel_external.rs +1 -0
  119. data/bridge/sdk-core/tests/integ_tests/workflow_tests/cancel_wf.rs +6 -13
  120. data/bridge/sdk-core/tests/integ_tests/workflow_tests/child_workflows.rs +1 -0
  121. data/bridge/sdk-core/tests/integ_tests/workflow_tests/continue_as_new.rs +6 -2
  122. data/bridge/sdk-core/tests/integ_tests/workflow_tests/determinism.rs +3 -10
  123. data/bridge/sdk-core/tests/integ_tests/workflow_tests/local_activities.rs +72 -191
  124. data/bridge/sdk-core/tests/integ_tests/workflow_tests/modify_wf_properties.rs +1 -0
  125. data/bridge/sdk-core/tests/integ_tests/workflow_tests/patches.rs +7 -28
  126. data/bridge/sdk-core/tests/integ_tests/workflow_tests/replay.rs +12 -7
  127. data/bridge/sdk-core/tests/integ_tests/workflow_tests/resets.rs +1 -0
  128. data/bridge/sdk-core/tests/integ_tests/workflow_tests/signals.rs +18 -14
  129. data/bridge/sdk-core/tests/integ_tests/workflow_tests/stickyness.rs +6 -20
  130. data/bridge/sdk-core/tests/integ_tests/workflow_tests/timers.rs +10 -21
  131. data/bridge/sdk-core/tests/integ_tests/workflow_tests/upsert_search_attrs.rs +6 -4
  132. data/bridge/sdk-core/tests/integ_tests/workflow_tests.rs +10 -11
  133. data/bridge/sdk-core/tests/main.rs +3 -13
  134. data/bridge/sdk-core/tests/runner.rs +75 -36
  135. data/bridge/sdk-core/tests/wf_input_replay.rs +32 -0
  136. data/bridge/src/connection.rs +41 -25
  137. data/bridge/src/lib.rs +269 -14
  138. data/bridge/src/runtime.rs +1 -1
  139. data/bridge/src/test_server.rs +153 -0
  140. data/bridge/src/worker.rs +89 -16
  141. data/lib/gen/temporal/api/command/v1/message_pb.rb +4 -18
  142. data/lib/gen/temporal/api/common/v1/message_pb.rb +4 -0
  143. data/lib/gen/temporal/api/enums/v1/command_type_pb.rb +1 -3
  144. data/lib/gen/temporal/api/enums/v1/event_type_pb.rb +3 -3
  145. data/lib/gen/temporal/api/enums/v1/failed_cause_pb.rb +2 -0
  146. data/lib/gen/temporal/api/enums/v1/update_pb.rb +6 -4
  147. data/lib/gen/temporal/api/history/v1/message_pb.rb +27 -19
  148. data/lib/gen/temporal/api/namespace/v1/message_pb.rb +1 -0
  149. data/lib/gen/temporal/api/operatorservice/v1/request_response_pb.rb +3 -0
  150. data/lib/gen/temporal/api/protocol/v1/message_pb.rb +30 -0
  151. data/lib/gen/temporal/api/sdk/v1/task_complete_metadata_pb.rb +23 -0
  152. data/lib/gen/temporal/api/testservice/v1/request_response_pb.rb +49 -0
  153. data/lib/gen/temporal/api/testservice/v1/service_pb.rb +21 -0
  154. data/lib/gen/temporal/api/update/v1/message_pb.rb +72 -0
  155. data/lib/gen/temporal/api/workflowservice/v1/request_response_pb.rb +26 -16
  156. data/lib/gen/temporal/sdk/core/activity_result/activity_result_pb.rb +13 -9
  157. data/lib/gen/temporal/sdk/core/activity_task/activity_task_pb.rb +10 -6
  158. data/lib/gen/temporal/sdk/core/child_workflow/child_workflow_pb.rb +13 -9
  159. data/lib/gen/temporal/sdk/core/common/common_pb.rb +7 -3
  160. data/lib/gen/temporal/sdk/core/core_interface_pb.rb +9 -3
  161. data/lib/gen/temporal/sdk/core/external_data/external_data_pb.rb +7 -3
  162. data/lib/gen/temporal/sdk/core/workflow_activation/workflow_activation_pb.rb +27 -21
  163. data/lib/gen/temporal/sdk/core/workflow_commands/workflow_commands_pb.rb +28 -24
  164. data/lib/gen/temporal/sdk/core/workflow_completion/workflow_completion_pb.rb +12 -5
  165. data/lib/temporalio/activity/context.rb +13 -8
  166. data/lib/temporalio/activity/info.rb +1 -1
  167. data/lib/temporalio/bridge/connect_options.rb +15 -0
  168. data/lib/temporalio/bridge/retry_config.rb +24 -0
  169. data/lib/temporalio/bridge/tls_options.rb +19 -0
  170. data/lib/temporalio/client/implementation.rb +8 -8
  171. data/lib/temporalio/connection/retry_config.rb +44 -0
  172. data/lib/temporalio/connection/service.rb +20 -0
  173. data/lib/temporalio/connection/test_service.rb +92 -0
  174. data/lib/temporalio/connection/tls_options.rb +51 -0
  175. data/lib/temporalio/connection/workflow_service.rb +731 -0
  176. data/lib/temporalio/connection.rb +55 -720
  177. data/lib/temporalio/interceptor/activity_inbound.rb +22 -0
  178. data/lib/temporalio/interceptor/activity_outbound.rb +24 -0
  179. data/lib/temporalio/interceptor/chain.rb +5 -5
  180. data/lib/temporalio/interceptor/client.rb +8 -4
  181. data/lib/temporalio/interceptor.rb +22 -0
  182. data/lib/temporalio/retry_policy.rb +13 -3
  183. data/lib/temporalio/testing/time_skipping_handle.rb +32 -0
  184. data/lib/temporalio/testing/time_skipping_interceptor.rb +23 -0
  185. data/lib/temporalio/testing/workflow_environment.rb +112 -0
  186. data/lib/temporalio/testing.rb +175 -0
  187. data/lib/temporalio/version.rb +1 -1
  188. data/lib/temporalio/worker/activity_runner.rb +26 -4
  189. data/lib/temporalio/worker/activity_worker.rb +44 -18
  190. data/lib/temporalio/worker/sync_worker.rb +47 -11
  191. data/lib/temporalio/worker.rb +27 -21
  192. data/lib/temporalio/workflow/async.rb +46 -0
  193. data/lib/temporalio/workflow/future.rb +138 -0
  194. data/lib/temporalio/workflow/info.rb +76 -0
  195. data/temporalio.gemspec +4 -3
  196. metadata +67 -17
  197. data/bridge/sdk-core/Cargo.lock +0 -2606
  198. data/bridge/sdk-core/protos/api_upstream/temporal/api/interaction/v1/message.proto +0 -87
  199. data/lib/bridge.so +0 -0
  200. data/lib/gen/temporal/api/enums/v1/interaction_type_pb.rb +0 -25
  201. data/lib/gen/temporal/api/interaction/v1/message_pb.rb +0 -49
  202. data/lib/gen/temporal/sdk/core/bridge/bridge_pb.rb +0 -222
data/bridge/src/lib.rs CHANGED
@@ -4,16 +4,20 @@ extern crate lazy_static;
4
4
 
5
5
  mod connection;
6
6
  mod runtime;
7
+ mod test_server;
7
8
  mod worker;
8
9
 
9
10
  use connection::{Connection, RpcParams};
10
11
  use runtime::Runtime;
11
12
  use rutie::{
12
- Module, Object, Symbol, RString, Encoding, AnyObject, AnyException, Exception, VM, Thread,
13
- NilClass, Hash, Integer,
13
+ AnyException, AnyObject, Array, Boolean, Encoding, Exception, Hash, Integer, Module, NilClass,
14
+ Object, RString, Symbol, Thread, VM, Float,
14
15
  };
15
- use std::collections::HashMap;
16
+ use temporal_client::{ClientOptionsBuilder, TlsConfig, ClientTlsConfig, RetryConfig};
17
+ use temporal_sdk_core::Url;
18
+ use std::{collections::HashMap, time::Duration};
16
19
  use temporal_sdk_core_api::telemetry::{Logger, TelemetryOptionsBuilder};
20
+ use test_server::{TemporaliteConfig, TestServer, TestServerConfig};
17
21
  use tokio_util::sync::CancellationToken;
18
22
  use worker::{Worker, WorkerError, WorkerResult};
19
23
 
@@ -29,7 +33,7 @@ fn wrap_worker_error(e: &WorkerError) -> AnyException {
29
33
  _ => "Temporalio::Bridge::Error"
30
34
  };
31
35
 
32
- AnyException::new(name, Some(&format!("[{:?}] {}", e, e)))
36
+ AnyException::new(name, Some(&format!("[{e:?}] {e}")))
33
37
  }
34
38
 
35
39
  fn wrap_bytes(bytes: Vec<u8>) -> RString {
@@ -56,6 +60,16 @@ fn to_hash_map(hash: Hash) -> HashMap<String, String> {
56
60
  result
57
61
  }
58
62
 
63
+ fn to_vec(array: Array) -> Vec<String> {
64
+ let mut result: Vec<String> = vec![];
65
+ for item in array.into_iter() {
66
+ let string = item.try_convert_to::<RString>().map_err(VM::raise_ex).unwrap().to_string();
67
+ result.push(string);
68
+ }
69
+
70
+ result
71
+ }
72
+
59
73
  fn worker_result_to_proc_args(result: WorkerResult) -> [AnyObject; 2] {
60
74
  let ruby_nil = NilClass::new().to_any_object();
61
75
  match result {
@@ -64,9 +78,24 @@ fn worker_result_to_proc_args(result: WorkerResult) -> [AnyObject; 2] {
64
78
  }
65
79
  }
66
80
 
81
+ fn unwrap_as_optional<T: rutie::VerifiedObject>(object: Result<AnyObject, AnyException>) -> Option<T> {
82
+ let object = object.map_err(VM::raise_ex).unwrap();
83
+ if object.is_nil() {
84
+ None
85
+ } else {
86
+ Some(
87
+ object
88
+ .try_convert_to::<T>()
89
+ .map_err(VM::raise_ex)
90
+ .unwrap()
91
+ )
92
+ }
93
+ }
94
+
67
95
  wrappable_struct!(Connection, ConnectionWrapper, CONNECTION_WRAPPER);
68
96
  wrappable_struct!(Runtime, RuntimeWrapper, RUNTIME_WRAPPER);
69
97
  wrappable_struct!(Worker, WorkerWrapper, WORKER_WRAPPER);
98
+ wrappable_struct!(TestServer, TestServerWrapper, TEST_SERVER_WRAPPER);
70
99
 
71
100
  class!(TemporalBridge);
72
101
 
@@ -74,13 +103,71 @@ methods!(
74
103
  TemporalBridge,
75
104
  _rtself, // somehow compiler is sure this is unused and insists on the "_"
76
105
 
77
- fn create_connection(runtime: AnyObject, host: RString) -> AnyObject {
78
- let host = host.map_err(VM::raise_ex).unwrap().to_string();
106
+ fn create_connection(runtime: AnyObject, options: AnyObject) -> AnyObject {
79
107
  let runtime = runtime.unwrap();
80
108
  let runtime = runtime.get_data(&*RUNTIME_WRAPPER);
81
109
 
110
+ let options = options.map_err(VM::raise_ex).unwrap();
111
+
112
+ let url = options.instance_variable_get("@url").try_convert_to::<RString>().map_err(VM::raise_ex).unwrap().to_string();
113
+ let url = Url::try_from(&*url).map_err(|e| raise_bridge_exception(&e.to_string())).unwrap();
114
+
115
+ let tls = unwrap_as_optional::<AnyObject>(Ok(options.instance_variable_get("@tls"))).map(|x| x.to_any_object());
116
+ let tls = tls.map(|tls| {
117
+ let server_root_ca_cert = unwrap_as_optional::<RString>(Ok(tls.instance_variable_get("@server_root_ca_cert"))).map(unwrap_bytes);
118
+ let client_cert = unwrap_as_optional::<RString>(Ok(tls.instance_variable_get("@client_cert"))).map(unwrap_bytes);
119
+ let client_private_key = unwrap_as_optional::<RString>(Ok(tls.instance_variable_get("@client_private_key"))).map(unwrap_bytes);
120
+ let server_name_override = unwrap_as_optional::<RString>(Ok(tls.instance_variable_get("@server_name_override"))).map(|x| x.to_string());
121
+
122
+ TlsConfig {
123
+ server_root_ca_cert,
124
+ client_tls_config:
125
+ if let (Some(client_cert), Some(client_private_key)) = (client_cert, client_private_key) {
126
+ Some(ClientTlsConfig {
127
+ client_cert,
128
+ client_private_key,
129
+ })
130
+ } else {
131
+ None
132
+ },
133
+ domain: server_name_override,
134
+ }
135
+ });
136
+
137
+ let client_version = options.instance_variable_get("@client_version").try_convert_to::<RString>().map_err(VM::raise_ex).unwrap().to_string();
138
+ let headers = unwrap_as_optional::<Hash>(Ok(options.instance_variable_get("@metadata"))).map(to_hash_map);
139
+
140
+ let retry_config = unwrap_as_optional::<AnyObject>(Ok(options.instance_variable_get("@retry_config"))).map(|x| x.to_any_object());
141
+ let retry_config = retry_config.map(|config| {
142
+ let initial_interval = Duration::from_millis(config.instance_variable_get("@initial_interval_millis").try_convert_to::<Integer>().map_err(VM::raise_ex).unwrap().to_u64());
143
+ let randomization_factor = config.instance_variable_get("@randomization_factor").try_convert_to::<Float>().map_err(VM::raise_ex).unwrap().to_f64();
144
+ let multiplier = config.instance_variable_get("@multiplier").try_convert_to::<Float>().map_err(VM::raise_ex).unwrap().to_f64();
145
+ let max_interval = Duration::from_millis(config.instance_variable_get("@max_interval_millis").try_convert_to::<Integer>().map_err(VM::raise_ex).unwrap().to_u64());
146
+ let max_elapsed_time = unwrap_as_optional::<Integer>(Ok(options.instance_variable_get("@max_elapsed_time_millis"))).map(|x| Duration::from_millis(x.to_u64()));
147
+ let max_retries = config.instance_variable_get("@max_retries").try_convert_to::<Integer>().map_err(VM::raise_ex).unwrap().to_u64();
148
+
149
+ RetryConfig {
150
+ initial_interval,
151
+ randomization_factor,
152
+ multiplier,
153
+ max_interval,
154
+ max_elapsed_time,
155
+ max_retries: max_retries as usize,
156
+ }
157
+ });
158
+
159
+ let mut options = ClientOptionsBuilder::default();
160
+ options.target_url(url)
161
+ .client_name("temporal-ruby".to_string())
162
+ .client_version(client_version)
163
+ .retry_config(retry_config.unwrap_or(RetryConfig::default()));
164
+ if let Some(tls_cfg) = tls {
165
+ options.tls_cfg(tls_cfg);
166
+ }
167
+
168
+ let options = options.build().map_err(|e| raise_bridge_exception(&e.to_string())).unwrap();
82
169
  let result = Thread::call_without_gvl(move || {
83
- Connection::connect(runtime.tokio_runtime.clone(), host.clone())
170
+ Connection::connect(runtime.tokio_runtime.clone(), options.clone(), headers.clone())
84
171
  }, Some(|| {}));
85
172
 
86
173
  let connection = result.map_err(|e| raise_bridge_exception(&e.to_string())).unwrap();
@@ -91,8 +178,9 @@ methods!(
91
178
  .wrap_data(connection, &*CONNECTION_WRAPPER)
92
179
  }
93
180
 
94
- fn call_rpc(rpc: Symbol, request: RString, metadata: Hash, timeout: Integer) -> RString {
181
+ fn call_rpc(rpc: Symbol, service: Symbol, request: RString, metadata: Hash, timeout: Integer) -> RString {
95
182
  let rpc = rpc.map_err(VM::raise_ex).unwrap().to_string();
183
+ let service = service.map_err(VM::raise_ex).unwrap().to_string();
96
184
  let request = unwrap_bytes(request.map_err(VM::raise_ex).unwrap());
97
185
  let metadata = to_hash_map(metadata.map_err(VM::raise_ex).unwrap());
98
186
  let timeout = timeout.map_or(None, |v| Some(v.to_u64()));
@@ -102,6 +190,7 @@ methods!(
102
190
  let connection = _rtself.get_data_mut(&*CONNECTION_WRAPPER);
103
191
  let params = RpcParams {
104
192
  rpc: rpc.clone(),
193
+ service: service.clone(),
105
194
  request: request.clone(),
106
195
  metadata: metadata.clone(),
107
196
  timeout_millis: timeout
@@ -136,14 +225,16 @@ methods!(
136
225
  NilClass::new()
137
226
  }
138
227
 
139
- fn create_worker(runtime: AnyObject, connection: AnyObject, namespace: RString, task_queue: RString) -> AnyObject {
228
+ fn create_worker(runtime: AnyObject, connection: AnyObject, namespace: RString, task_queue: RString, max_cached_workflows: Integer, no_remote_activity: Boolean) -> AnyObject {
140
229
  let namespace = namespace.map_err(VM::raise_ex).unwrap().to_string();
141
230
  let task_queue = task_queue.map_err(VM::raise_ex).unwrap().to_string();
231
+ let max_cached_workflows = max_cached_workflows.map_err(VM::raise_ex).unwrap().to_u32();
232
+ let no_remote_activity = no_remote_activity.map_err(VM::raise_ex).unwrap().to_bool();
142
233
  let runtime = runtime.unwrap();
143
234
  let runtime = runtime.get_data(&*RUNTIME_WRAPPER);
144
235
  let connection = connection.unwrap();
145
236
  let connection = connection.get_data(&*CONNECTION_WRAPPER);
146
- let worker = Worker::new(runtime, &connection.client, &namespace, &task_queue);
237
+ let worker = Worker::new(runtime, &connection.client, &namespace, &task_queue, max_cached_workflows, no_remote_activity);
147
238
 
148
239
  Module::from_existing("Temporalio")
149
240
  .get_nested_module("Bridge")
@@ -199,16 +290,170 @@ methods!(
199
290
  NilClass::new()
200
291
  }
201
292
 
293
+ fn worker_poll_workflow_activation() -> NilClass {
294
+ if !VM::is_block_given() {
295
+ panic!("Called #poll_workflow_activation without a block");
296
+ }
297
+
298
+ let ruby_callback = VM::block_proc();
299
+ let callback = move |result: WorkerResult| {
300
+ ruby_callback.call(&worker_result_to_proc_args(result));
301
+ };
302
+
303
+ let worker = _rtself.get_data_mut(&*WORKER_WRAPPER);
304
+ let result = worker.poll_workflow_activation(callback);
305
+
306
+ result.map_err(|e| raise_bridge_exception(&e.to_string())).unwrap();
307
+
308
+ NilClass::new()
309
+ }
310
+
311
+ fn worker_complete_workflow_activation(proto: RString) -> NilClass {
312
+ if !VM::is_block_given() {
313
+ panic!("Called #worker_complete_workflow_activation without a block");
314
+ }
315
+
316
+ let bytes = unwrap_bytes(proto.map_err(VM::raise_ex).unwrap());
317
+ let ruby_callback = VM::block_proc();
318
+ let callback = move |result: WorkerResult| {
319
+ ruby_callback.call(&worker_result_to_proc_args(result));
320
+ };
321
+
322
+ let worker = _rtself.get_data_mut(&*WORKER_WRAPPER);
323
+ let result = worker.complete_workflow_activation(bytes, callback);
324
+
325
+ result.map_err(|e| raise_bridge_exception(&e.to_string())).unwrap();
326
+
327
+ NilClass::new()
328
+ }
329
+
202
330
  fn worker_initiate_shutdown() -> NilClass {
203
331
  let worker = _rtself.get_data_mut(&*WORKER_WRAPPER);
204
- worker.initiate_shutdown();
332
+ worker.initiate_shutdown().map_err(|e| raise_bridge_exception(&e.to_string())).unwrap();
205
333
 
206
334
  NilClass::new()
207
335
  }
208
336
 
209
- fn worker_shutdown() -> NilClass {
337
+ fn worker_finalize_shutdown() -> NilClass {
210
338
  let worker = _rtself.get_data_mut(&*WORKER_WRAPPER);
211
- worker.shutdown();
339
+ worker.finalize_shutdown().map_err(|e| raise_bridge_exception(&e.to_string())).unwrap();
340
+
341
+ NilClass::new()
342
+ }
343
+
344
+ fn start_test_server(
345
+ runtime: AnyObject,
346
+ existing_path: AnyObject,
347
+ sdk_name: RString,
348
+ sdk_version: RString,
349
+ download_version: RString,
350
+ download_dir: AnyObject,
351
+ port: AnyObject,
352
+ extra_args: Array
353
+ ) -> AnyObject {
354
+ let runtime = runtime.unwrap();
355
+ let runtime = runtime.get_data(&*RUNTIME_WRAPPER);
356
+
357
+ let existing_path = unwrap_as_optional::<RString>(existing_path).map(|v| v.to_string());
358
+ let sdk_name = sdk_name.map_err(VM::raise_ex).unwrap().to_string();
359
+ let sdk_version = sdk_version.map_err(VM::raise_ex).unwrap().to_string();
360
+ let download_version = download_version.map_err(VM::raise_ex).unwrap().to_string();
361
+ let download_dir = unwrap_as_optional::<RString>(download_dir).map(|v| v.to_string());
362
+ let port = unwrap_as_optional::<Integer>(port).map(|v| u16::try_from(v.to_u32()).unwrap());
363
+ let extra_args = to_vec(extra_args.map_err(VM::raise_ex).unwrap());
364
+
365
+ let test_server = TestServer::start(
366
+ runtime,
367
+ TestServerConfig {
368
+ existing_path,
369
+ sdk_name,
370
+ sdk_version,
371
+ download_version,
372
+ download_dir,
373
+ port,
374
+ extra_args,
375
+ }
376
+ ).map_err(|e| raise_bridge_exception(&e.to_string())).unwrap();
377
+
378
+ Module::from_existing("Temporalio")
379
+ .get_nested_module("Bridge")
380
+ .get_nested_class("TestServer")
381
+ .wrap_data(test_server, &*TEST_SERVER_WRAPPER)
382
+ }
383
+
384
+ fn start_temporalite_server(
385
+ runtime: AnyObject,
386
+ existing_path: AnyObject,
387
+ sdk_name: RString,
388
+ sdk_version: RString,
389
+ download_version: RString,
390
+ download_dir: AnyObject,
391
+ namespace: RString,
392
+ ip: RString,
393
+ port: AnyObject,
394
+ database_filename: AnyObject,
395
+ ui: Boolean,
396
+ log_format: RString,
397
+ log_level: RString,
398
+ extra_args: Array
399
+ ) -> AnyObject {
400
+ let runtime = runtime.unwrap();
401
+ let runtime = runtime.get_data(&*RUNTIME_WRAPPER);
402
+
403
+ let existing_path = unwrap_as_optional::<RString>(existing_path).map(|v| v.to_string());
404
+ let sdk_name = sdk_name.map_err(VM::raise_ex).unwrap().to_string();
405
+ let sdk_version = sdk_version.map_err(VM::raise_ex).unwrap().to_string();
406
+ let download_version = download_version.map_err(VM::raise_ex).unwrap().to_string();
407
+ let download_dir = unwrap_as_optional::<RString>(download_dir).map(|v| v.to_string());
408
+ let namespace = namespace.map_err(VM::raise_ex).unwrap().to_string();
409
+ let ip = ip.map_err(VM::raise_ex).unwrap().to_string();
410
+ let port = unwrap_as_optional::<Integer>(port).map(|v| u16::try_from(v.to_u32()).unwrap());
411
+ let database_filename = unwrap_as_optional::<RString>(database_filename).map(|v| v.to_string());
412
+ let ui = ui.map_err(VM::raise_ex).unwrap().to_bool();
413
+ let log_format = log_format.map_err(VM::raise_ex).unwrap().to_string();
414
+ let log_level = log_level.map_err(VM::raise_ex).unwrap().to_string();
415
+ let extra_args = to_vec(extra_args.map_err(VM::raise_ex).unwrap());
416
+
417
+ let test_server = TestServer::start_temporalite(
418
+ runtime,
419
+ TemporaliteConfig {
420
+ existing_path,
421
+ sdk_name,
422
+ sdk_version,
423
+ download_version,
424
+ download_dir,
425
+ namespace,
426
+ ip,
427
+ port,
428
+ database_filename,
429
+ ui,
430
+ log_format,
431
+ log_level,
432
+ extra_args,
433
+ }
434
+ ).map_err(|e| raise_bridge_exception(&e.to_string())).unwrap();
435
+
436
+ Module::from_existing("Temporalio")
437
+ .get_nested_module("Bridge")
438
+ .get_nested_class("TestServer")
439
+ .wrap_data(test_server, &*TEST_SERVER_WRAPPER)
440
+ }
441
+
442
+ fn test_server_has_test_service() -> Boolean {
443
+ let test_server = _rtself.get_data_mut(&*TEST_SERVER_WRAPPER);
444
+
445
+ Boolean::new(test_server.has_test_service())
446
+ }
447
+
448
+ fn test_server_target() -> RString {
449
+ let test_server = _rtself.get_data_mut(&*TEST_SERVER_WRAPPER);
450
+
451
+ RString::new_utf8(&test_server.target())
452
+ }
453
+
454
+ fn test_server_shutdown() -> NilClass {
455
+ let test_server = _rtself.get_data_mut(&*TEST_SERVER_WRAPPER);
456
+ test_server.shutdown().map_err(|e| raise_bridge_exception(&e.to_string())).unwrap();
212
457
 
213
458
  NilClass::new()
214
459
  }
@@ -232,8 +477,18 @@ pub extern "C" fn init_bridge() {
232
477
  klass.def("poll_activity_task", worker_poll_activity_task);
233
478
  klass.def("complete_activity_task", worker_complete_activity_task);
234
479
  klass.def("record_activity_heartbeat", worker_record_activity_heartbeat);
480
+ klass.def("poll_workflow_activation", worker_poll_workflow_activation);
481
+ klass.def("complete_workflow_activation", worker_complete_workflow_activation);
235
482
  klass.def("initiate_shutdown", worker_initiate_shutdown);
236
- klass.def("shutdown", worker_shutdown);
483
+ klass.def("finalize_shutdown", worker_finalize_shutdown);
484
+ });
485
+
486
+ module.define_nested_class("TestServer", None).define(|klass| {
487
+ klass.def_self("start", start_test_server);
488
+ klass.def_self("start_temporalite", start_temporalite_server);
489
+ klass.def("has_test_service?", test_server_has_test_service);
490
+ klass.def("target", test_server_target);
491
+ klass.def("shutdown", test_server_shutdown);
237
492
  });
238
493
  });
239
494
  }
@@ -1,6 +1,6 @@
1
1
  use rutie::Thread;
2
+ use std::sync::mpsc::{channel, Receiver, Sender};
2
3
  use std::sync::Arc;
3
- use std::sync::mpsc::{channel, Sender, Receiver};
4
4
  use temporal_sdk_core::CoreRuntime;
5
5
  use temporal_sdk_core_api::telemetry::TelemetryOptions;
6
6
  use tokio::runtime::{Builder, Runtime as TokioRuntime};
@@ -0,0 +1,153 @@
1
+ use crate::runtime::Runtime;
2
+ use std::sync::Arc;
3
+ use temporal_sdk_core::ephemeral_server;
4
+ use thiserror::Error;
5
+ use tokio::runtime::Runtime as TokioRuntime;
6
+
7
+ #[derive(Error, Debug)]
8
+ pub enum TestServerError {
9
+ #[error(transparent)]
10
+ ConfigError(#[from] ephemeral_server::TestServerConfigBuilderError),
11
+
12
+ #[error(transparent)]
13
+ TemporaliteConfigError(#[from] ephemeral_server::TemporaliteConfigBuilderError),
14
+
15
+ #[error(transparent)]
16
+ Unknown(#[from] anyhow::Error),
17
+ }
18
+
19
+ pub struct TestServer {
20
+ core_server: ephemeral_server::EphemeralServer,
21
+ tokio_runtime: Arc<TokioRuntime>,
22
+ }
23
+
24
+ pub struct TestServerConfig {
25
+ pub existing_path: Option<String>,
26
+ pub sdk_name: String,
27
+ pub sdk_version: String,
28
+ pub download_version: String,
29
+ pub download_dir: Option<String>,
30
+ pub port: Option<u16>,
31
+ pub extra_args: Vec<String>,
32
+ }
33
+
34
+ pub struct TemporaliteConfig {
35
+ pub existing_path: Option<String>,
36
+ pub sdk_name: String,
37
+ pub sdk_version: String,
38
+ pub download_version: String,
39
+ pub download_dir: Option<String>,
40
+ pub namespace: String,
41
+ pub ip: String,
42
+ pub port: Option<u16>,
43
+ pub database_filename: Option<String>,
44
+ pub ui: bool,
45
+ pub log_format: String,
46
+ pub log_level: String,
47
+ pub extra_args: Vec<String>,
48
+ }
49
+
50
+ impl TestServer {
51
+ pub fn start(runtime: &Runtime, config: TestServerConfig) -> Result<TestServer, TestServerError> {
52
+ let config: ephemeral_server::TestServerConfig = config.try_into()?;
53
+ let core_server = runtime.tokio_runtime.block_on(config.start_server())?;
54
+
55
+ Ok(TestServer {
56
+ core_server,
57
+ tokio_runtime: runtime.tokio_runtime.clone(),
58
+ })
59
+ }
60
+
61
+ pub fn start_temporalite(runtime: &Runtime, config: TemporaliteConfig) -> Result<TestServer, TestServerError> {
62
+ let config: ephemeral_server::TemporaliteConfig = config.try_into()?;
63
+ let core_server = runtime.tokio_runtime.block_on(config.start_server())?;
64
+
65
+ // TODO: This needs further investigation, but for some reason without a short pause here
66
+ // the shutdown called immediately after will end up waiting for 10 seconds before the
67
+ // process dies. This might be related to Core's EphemeralServer not waiting long
68
+ // enough for the Temporalite to start before returning back the control to the SDK.
69
+ // Reported here — https://github.com/temporalio/cli/issues/79.
70
+ std::thread::sleep(std::time::Duration::from_millis(150));
71
+
72
+ Ok(TestServer {
73
+ core_server,
74
+ tokio_runtime: runtime.tokio_runtime.clone(),
75
+ })
76
+ }
77
+
78
+ pub fn has_test_service(&self) -> bool {
79
+ self.core_server.has_test_service
80
+ }
81
+
82
+ pub fn target(&self) -> String {
83
+ self.core_server.target.clone()
84
+ }
85
+
86
+ pub fn shutdown(&mut self) -> Result<(), TestServerError> {
87
+ self.tokio_runtime.block_on(self.core_server.shutdown())?;
88
+
89
+ Ok(())
90
+ }
91
+ }
92
+
93
+ fn ephemeral_exe(
94
+ existing_path: Option<String>,
95
+ sdk_name: String,
96
+ sdk_version: String,
97
+ download_version: String,
98
+ download_dir: Option<String>
99
+ ) -> ephemeral_server::EphemeralExe {
100
+ if let Some(path) = existing_path {
101
+ ephemeral_server::EphemeralExe::ExistingPath(path)
102
+ } else {
103
+ let version =
104
+ if download_version == "default" {
105
+ ephemeral_server::EphemeralExeVersion::SDKDefault { sdk_name, sdk_version }
106
+ } else {
107
+ ephemeral_server::EphemeralExeVersion::Fixed(download_version)
108
+ };
109
+
110
+ ephemeral_server::EphemeralExe::CachedDownload { version, dest_dir: download_dir }
111
+ }
112
+ }
113
+
114
+ impl TryFrom<TestServerConfig> for ephemeral_server::TestServerConfig {
115
+ type Error = ephemeral_server::TestServerConfigBuilderError;
116
+
117
+ fn try_from(config: TestServerConfig) -> Result<Self, Self::Error> {
118
+ ephemeral_server::TestServerConfigBuilder::default()
119
+ .exe(ephemeral_exe(
120
+ config.existing_path,
121
+ config.sdk_name,
122
+ config.sdk_version,
123
+ config.download_version,
124
+ config.download_dir
125
+ ))
126
+ .port(config.port)
127
+ .extra_args(config.extra_args)
128
+ .build()
129
+ }
130
+ }
131
+
132
+ impl TryFrom<TemporaliteConfig> for ephemeral_server::TemporaliteConfig {
133
+ type Error = ephemeral_server::TemporaliteConfigBuilderError;
134
+
135
+ fn try_from(config: TemporaliteConfig) -> Result<Self, Self::Error> {
136
+ ephemeral_server::TemporaliteConfigBuilder::default()
137
+ .exe(ephemeral_exe(
138
+ config.existing_path,
139
+ config.sdk_name,
140
+ config.sdk_version,
141
+ config.download_version,
142
+ config.download_dir
143
+ ))
144
+ .namespace(config.namespace)
145
+ .ip(config.ip)
146
+ .port(config.port)
147
+ .db_filename(config.database_filename)
148
+ .ui(config.ui)
149
+ .log((config.log_format, config.log_level))
150
+ .extra_args(config.extra_args)
151
+ .build()
152
+ }
153
+ }