Skip to content

Conversation

ecwyne
Copy link

@ecwyne ecwyne commented Aug 22, 2025

There is currently no way to get the return value of a workflow except for getting it in an onComplete handler. This PR adds the returnValue to the WorkflowStatus when the status is "completed".


By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

@ecwyne
Copy link
Author

ecwyne commented Aug 27, 2025

Thanks for all you've built @ianmacartney! Your contributions to Convex make a huge difference.

Let me know if you have any feedback on this or if there's anything else I could do to help get it merged if you're interested.

Copy link

pkg-pr-new bot commented Sep 2, 2025

Open in StackBlitz

npm i https://pkg.pr.new/get-convex/workflow/@convex-dev/workflow@93

commit: d0b9ca8

@ianmacartney
Copy link
Contributor

Whoops sorry for the delay here @ecwyne - my only hesitation right now is I'd like to stop persisting the return value by default and encourage folks to save it somewhere as part of the onComplete.
However, if they're fine with the knowledge that when they clean it up it won't be available anymore, this seems reasonable. It already looks like we would be returning "pending" incorrectly if it finishes & is cleaned up, by my read.

What's your use-case where you don't want to use the onComplete to capture it?

@ecwyne
Copy link
Author

ecwyne commented Sep 3, 2025

Thanks @ianmacartney! No worries about the delay.

My current use case is running server-side and I'm waiting for the workflow to complete before responding to the request.

My workflow has the following logic to create a new customer:

  1. Call a 3rd party api in an action
  2. Write customer to db using the result of the action
  3. Return the newly created customer

When I'm starting the workflow all I have to identify the created customer is the workflowId, so I'll need to add that to the created customer (and have an index on workflowId just so that I can read it back out after the workflow completes. (I don't have a customer id to read yet)

I don't have to do any of that if I can get the result of the workflow when I check the status, as it's right in the returnValue

@ianmacartney
Copy link
Contributor

Gotcha - thanks that makes sense.
This would be a great usecase for custom / client-side ID generation, which we've started designing but don't have an ETA on shipping.

A couple questions to tease out the usecase:

  1. What's your timeline on deleting the data afterwards? Do you do periodic cleanup, immediately, or keep them around by default?
  2. If the request fails, how does the client know how to resume / if the call succeeded/ failed? If the workflow doesn't finish in time, will the customer become an orphaned entity of sorts?

One option, which I know is not as satisfying, would be to run a mutation which creates the empty user, starts a workflow passing the ID in, then returns the ID to the http action to use. It requires making a non-finalized user though. Or making your own progress type table, where you pass that ID to the workflow and return it to the client to subscribe on - which would allow using a mutation instead of an action / endpoint, which has nice behavior around idempotency, retries, etc.

@ecwyne
Copy link
Author

ecwyne commented Sep 3, 2025

I agree, client-side id generation would absolutely work in this case.

  1. What's your timeline on deleting the data afterwards? Do you do periodic cleanup, immediately, or keep them around by default?

At this point I am not doing any cleanup, but in theory I could do so immediately.

  1. If the request fails, how does the client know how to resume / if the call succeeded/ failed? If the workflow doesn't finish in time, will the customer become an orphaned entity of sorts?

Customer creation is the last step of the workflow, so it wouldn't be orphaned. If the workflow fails then I reply with a server error.

One option, which I know is not as satisfying, would be to run a mutation which creates the empty user, starts a workflow passing the ID in, then returns the ID to the http action to use. It requires making a non-finalized user though. Or making your own progress type table, where you pass that ID to the workflow and return it to the client to subscribe on - which would allow using a mutation instead of an action / endpoint, which has nice behavior around idempotency, retries, etc.

I'd like to avoid making a "non-finalized" customer. As of now my schema requires the data I get from the first call to the 3rd-party api before creating a customer and I'd like to avoid the possibility of having orphaned/incomplete customers at all.

@ianmacartney
Copy link
Contributor

ianmacartney commented Sep 15, 2025 via email

@ecwyne
Copy link
Author

ecwyne commented Sep 18, 2025

Thank you @ianmacartney, I'm curious if there's anywhere I can track the implementation of client-generated ids as that would also solve my use-case?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants