Rust SDK Starter

Is it possible to use the Rust SDK to add a starter to my application? I have a Go application and a Rust application but I would like to start the workflow on the go app from the rust end.

How would I go about doing this. Are there any examples on how to do this with the temporal-rust sdk?

You don’t need Temporal SDK to create a starter. Temporal service exposes gRPC interface. So you can generate your own gRPC client and use it to start workflows.

Is there an example call somewhere directly via grpc to start a workflow?

The request/response proto gets quite complicated with the amount of options it has.

Thanks

Hi I was wondering if you could still elaborate.

I have tried getting the proto files from this project GitHub - temporalio/api: Temporal gRPC API and proto files. I have got a rust builder set up

build.rs

 tonic_build::configure()
    .build_server(false)
    .file_descriptor_set_path(out_dir.join("service_descriptor.bin"))
    .compile(
        &["proto/temporal/api/workflowservice/v1/service.proto"],
        &["proto/"],
    )
    .unwrap();

and a way to call it
temporal.rs

tonic::include_proto!("temporal.api.workflowservice.v1"); // The string specified here must match the proto package name

pub(crate) const FILE_DESCRIPTOR_SET: &'static [u8] =
        tonic::include_file_descriptor_set!("service_descriptor");

However it cannot be built and there are over 150 errors of different kinds e.g

415 | #[derive(Clone, PartialEq, ::prost::Message)]
    |                            ^^^^^^^^^^^^^^^^ cannot infer type
    |
    = note: cannot satisfy `_: Default`
    = note: required by `std::default::Default::default`
    = note: this error originates in the derive macro `::prost::Message` (in Nightly builds, run with -Z macro-backtrace for more info)

While it can be called by a grpc call it isn’t as simple due to static typing as required by rust. Hence why I was asking if there was a way to interface with the sdk to call to start workflow

Hi @tmacx,

Your particular question is really just about using prost_build it looks like. I think you just may not be depending on prost_types which is why you are missing a Default implementation for something. Your error paste isn’t quite long enough for me to see what, though.

That said there is a fairly easy solution to your problem. The Rust Core has a crate specifically for just the protobuf generated stuff, located here: sdk-core/sdk-core-protos at 30f288e18f26443abc9ecf2da253f22eaf28b056 · temporalio/sdk-core · GitHub – I’m not regularly publishing it to crates.io right now and it’s not explicitly ready for public consumption but it should work just fine if all you need is a client. You can depend on it in your crate via a git path. Give that a shot and let me know how it goes.

It depends on proto files that are above it in the directory structure which might cause issues with depending on it via git path in cargo. If that’s the case, you might want to just pull down the entire sdk-core repo and depend on just the protos crate via path.

Thank you very much for this Spencer,

I got it working. It raises 2 new questions since I am now interacting with the sdk in a very bare way (over grpc):

I have the code below to start a workflow

let request = tonic::Request::new(StartWorkflowExecutionRequest {
  input: Some(Payloads{
    payloads :  vec![Payload {
      data: info.to_string().into_bytes(),
      metadata: hashmap!["name".to_string() => "name".to_string().into_bytes(), "encoding".to_string() => "json/plain" .to_string().into_bytes()],
      ..Payload::default()
    }]
  }),
  workflow_id: wf_id.clone(),
  workflow_type: Some(WorkflowType { name: "Workflow".to_string() }),
  task_queue: Some(TaskQueue { name: "hello-world".to_string(), kind: 0 }),
  request_id,
  // workflow_task_timeout: task_timeout.map(Into::into),
  namespace: "default".to_string(),
  ..Default::default()
});

let response = client.start_workflow_execution(request).await.unwrap();

I was wondering:

  • How do I make it execute and return immediately (vs waiting for temporal to finish the workflow)
  • How do I get the result of the workflow? The above response only contains a run id, and also if I’m not waiting for the grpc call to return how would I check?

This is what i’ve tried but I don’t seem to get anything useful:

let request = QueryWorkflowRequest {
      namespace: "default".to_string(),
      execution : Some(WorkflowExecution {
        workflow_id: wf_id,
        run_id: run_id.to_string(),
      }),
      query: Some(WorkflowQuery {
        query_type: "__open_sessions".to_string(),
        ..Default::default()
      }),
      query_reject_condition: 0,
    };

    let response = client.query_workflow(tonic::Request::new(request)).await?;

The above uses the helloworld example in the go-samples sdk, which has the Workflow return a result as a string

@Spencer_Judge I also was wondering how to use signals with the rusk-sdk

Tarang

  • How do I make it execute and return immediately (vs waiting for temporal to finish the workflow)

This is what start_workflow_execution does, so that should already be the case with what you’ve written.

How do I get the result of the workflow? The above response only contains a run id, and also if I’m not waiting for the grpc call to return how would I check?

You will want to use get_workflow_execution_history https://github.com/temporalio/api/blob/master/temporal/api/workflowservice/v1/service.proto#L83 – this is a bit challenging with the raw gRPC client as you need to wait for and interpret the final history event. I will be merging some updates to the proto files with better comments soon here https://github.com/temporalio/api/pull/121 which explain how to wait for the final event (specifically here: More and better comments by Sushisource · Pull Request #121 · temporalio/api · GitHub)

I am using start_workflow_execution but I feel it never returns immediately it waits for the execution to finish. Is that not supposed to be the case?