Run workflow once in future time

Hello guys, I hope everyone is fine and safe.

I have been studying temporal, and I am thinking to use in my current company.

I have a question which I couldn’t find an “easy” solution, reading the docs and examples.

I need to schedule a job to run once, in a future time (like after 2 weeks, 1 month… etc).
It must run only once. I know I can start a workflow and keep it running (blocked using sleep and so on) until the future time I need.
I can also use cron job, and after the first time it runs, in some way kill the cron, avoiding to run another time.

I am wondering if there is a “simpler” way to do that.

Thanks in advance.

The simplest supported way is to start the workflow which sleeps for the desired time before executing the job through an activity.

Also be careful when using a timer/sleep if you want to schedule a workflow to be executed at a specific date.
If your workers are not running, your timers will not be started

I don’t know if it’s intended to have to do this, but this is what I do

I have a starting_date, let’s say it’s 10 days from now (“now” being the date when my workflow gets scheduled)
Instead of making it sleep for 10 days, I will substract my starting_date from workflow.Now (workflow.Now being the time when the workflow is picked up by a worker)
So now my workflow will correctly sleep until the starting_date

func MyScheduledWorkflow(ctx workflow.Context, starting_date int64) error {
	sleepDuration := starting_date - workflow.Now(ctx).Unix()
	workflow.Sleep(ctx, time.Second*time.Duration(sleepDuration))
}

I would have thought temporal takes the difference between WorkflowTaskScheduled's and WorkflowTaskStarted's creation dates
then deducts from the time used in timers and sleeps.

Or maybe it’s already doing it and I am doing things wrong?

@evlad you have a good point. You can use workflow.Info.WorkflowStartTime to retrieve the time when workflow was started:

func MyScheduledWorkflow(ctx workflow.Context, delay int64) error {
	timeSinceStarted :=workflow.Now(ctx).Sub(workflow.GetInfo(ctx).WorkflowStartTime)
	sleepDuration := time.Second * time.Duration(delay) - timeSinceStarted
	workflow.Sleep(ctx, sleepDuration)
}