docs / Guides / Getting started
Surviving a restart
Demonstrating why to use genroc in the first place.
Create process from scratch
Let’s now create a process which will run for a longer time:
# definitions/ticker.genroc.yaml
nameUnique process identifier.: tickerUnique process identifier.
tasksOrdered list of execution tasks. Control advances linearly unless a switch case redirects.:
- idTask identifier, unique within the definition.: tickTask identifier, unique within the definition.
actionDescribes the action to perform. Omit for switch-only (routing) tasks.:
typeDelay action: parks the instance until a duration elapses (for) or an instant arrives (until).: delayDelay action: parks the instance until a duration elapses (for) or an instant arrives (until).
forA duration from when the task is reached: "2h30m", a number of milliseconds, or a $: expression.: 10sA duration from when the task is reached: "2h30m", a number of milliseconds, or a $: expression.
outputtasks.tick.output — object{count}:
countcount — integer: "$: (selfself → object{previous?}.previousself.previous → object{count}|null.countself.previous.count → integer|null ?? 0) + 1(self.previous.count ?? 0) + 1 → integer"
switchRequired. Routing: a shorthand ("next", "end", "$task-id") or an ordered list of cases.:
- caseself.output.count < 3 → boolean: "selfself → object{output, previous?}.outputself.output → object{count}.countself.output.count → integer < 3self.output.count < 3 → boolean"
goto"end" to terminate, "next" to advance, or "$task-id" to jump to a task.: $tick"end" to terminate, "next" to advance, or "$task-id" to jump to a task.
- goto"end" to terminate, "next" to advance, or "$task-id" to jump to a task.: end"end" to terminate, "next" to advance, or "$task-id" to jump to a task.
outputoutput — object{ticks}:
ticksticks — integer: "$: outputsoutputs → object{tick}.tickoutputs.tick → object{count}.countoutputs.tick.count → integer ?? 0outputs.tick.count ?? 0 → integer"
Copy this yaml and put it into definitions/ticker.genroc.yaml (we are still working with project produced by genctl init from previous sections).
Let’s apply
Let’s now apply the process:
> genctl apply
latest: hello v1 (current)
latest: ticker - -> v1 (new)
You should see the same output as above. The hello process is unchanged — (current) means
nothing moved — and ticker is created.
Run the process
This process doesn’t require any input, so it’s simple to run it.
genctl run ticker
Now let’s check the logs.
genctl logs @last
This process runs for about 30s, so you can run the logs command repeatedly until it ends.
Once it finishes, you should see something like this:
> genctl logs @last
TIME LEVEL ID EVENT TASK
--- 2026-09-08 +02:00 ---
14:39:51 INFO 4ptydpvz inst_created by=no-auth:anonymous
14:39:51 INFO 4ptydpvz delay_armed tick msg="10s -> 2026-09-08T12:40:01Z"
14:40:01 INFO 4ptydpvz task_completed tick msg="→ $tick"
14:40:01 INFO 4ptydpvz delay_armed tick msg="10s -> 2026-09-08T12:40:11Z"
14:40:12 INFO 4ptydpvz task_completed tick msg="→ $tick"
14:40:12 INFO 4ptydpvz delay_armed tick msg="10s -> 2026-09-08T12:40:22Z"
14:40:22 INFO 4ptydpvz inst_completed tick output={"ticks":3}
Let’s try to break it!
Let’s now start a new instance and immediately stop the docker containers.
genctl run ticker && docker compose stop
Leave the server down for some time and then start it again.
docker compose up -d
Now let’s check the logs:
> genctl logs @last
TIME LEVEL ID EVENT TASK
--- 2026-09-08 +02:00 ---
14:50:53 INFO 20he91zm inst_created by=no-auth:anonymous
14:50:53 INFO 20he91zm delay_armed tick msg="10s -> 2026-09-08T12:51:03Z"
14:52:23 INFO 20he91zm task_completed tick msg="→ $tick"
14:52:23 INFO 20he91zm delay_armed tick msg="10s -> 2026-09-08T12:52:33Z"
14:52:33 INFO 20he91zm task_completed tick msg="→ $tick"
14:52:33 INFO 20he91zm delay_armed tick msg="10s -> 2026-09-08T12:52:43Z"
14:52:44 INFO 20he91zm inst_completed tick output={"ticks":3}
You can see that process started at 14:50:53, but then there is nothing for 90 seconds. Then it recovers and continues.
The instance lives in the database not in the running server. So if the server restarts, nothing is lost.
How about hard crashes?
You might object that docker stops the server gracefully and so it never aborts the running process forcibly, but what if our computer crashes or there is an electricity outage?
Genroc is safe in these cases too - and here the nuance starts. None of the actions in ticker have side-effects, so genroc can simply re-execute the task and continue.