How to execute only one job at a time?

Pyla Srenu: Hello Community,
I am new to zeebe, created one sample workflow and able to deploy that into operate. Able to execute service task using java zeebe client. Started 4 instances.
all the 4 instances are executing at the same time If I use zeebeworker (type).

But my question here, i want to execute only one instance using zeebeworker with some specific parameters . is that possible ?

korthout: Hi @Pyla Srenu You can configure your job worker to ask for only 1 job at a time by setting the maxJobsToActivate See https://github.com/camunda-cloud/zeebe/blob/main/clients/java/src/main/java/io/camunda/zeebe/client/api/worker/JobWorkerBuilderStep1.java#L104-L128

Note that even if multiple jobs are activated at the same time, they are handled sequentially by default. This is because the numJobWorkerExecutionThreads is set to 1 by default. See https://github.com/camunda-cloud/zeebe/blob/main/clients/java/src/main/java/io/camunda/zeebe/client/ZeebeClientBuilder.java#L47-L51

I’d like to add a counter question, why do you only want to have 1 job executed at a time? One of Camunda Cloud’s advantages is its high throughput, which can be achieved by having many process instances and jobs being worked on simultaneously.

Pyla Srenu: Hi @korthout - Thanks for the reply with description.

I am looking for, Will expose my own rest APIs to the UI to complete some user related stuff and along with this complete tasks in my logic itself using zeebeclient without using zeebeworker.

in this case I am getting complex here to get where is the process by inctanceProcessKey.

So I can easily complete that task using processinstancekey or any random uuid (I sent this UUID to the start the process instance to identify the process).

I am able to achieve my use case using camunda. but zeebe i am confusing how to do this.

Note: This post was generated by Slack Archivist from a conversation in the Zeebe Slack, a source of valuable discussions on Zeebe (get an invite). Someone in the Slack thought this was worth sharing!

If this post answered a question for you, hit the Like button - we use that to assess which posts to put into docs.

korthout: Okay. So if I understand correctly then you’re looking to interact with a specific process instance from outside of Zeebe without a job worker. Perhaps you can have a look at https://docs.camunda.io/docs/components/concepts/messages/|messages and <Message events | Camunda Cloud Docs catch events>. You can publish a message from your application using the Zeebe client. Then that message can be caught by a catch event in a process instance. If you’re worried you might publish the message before the process instance has arrived at the catch event, then you can set a TTL on the message to buffer it for some time.

Pyla Srenu: Hi @korthout - I gone through the community code for the simple-monitor and simple-task list. I got one thing from that code to use exporters (hazzlecast) to read job keys directly using process instance key.

After that i can provide that key to the zeebeclient to complete that job with specific paraments instead of complete all the jobs .

is my understanding correct here?

korthout: That is possible, but harder because you circumvent the standard orchestration offered by zeebe’s job workers model.

I have a feeling that the idea you’re proposing is not the best solution for your situation. Can you perhaps provide me an example process model so I have an idea of the interaction flow you have in mind

Taking from https://github.com/camunda-community-hub/camunda-8-examples/tree/main/synchronous-response-springboot, we used dynamic task types:

When we start a process, we pass as a variable a unique identifier generated by our system. This variable is called in our case applicationNumber. Then every task in the work flow has type named using the FEEL expression

="Task-xxx-" + applicationNumber

Then, we “manually” setup and track a Zeebe workers for each process, by the applicationNumber.
These workers live to process just the process step that corresponds to the applicationNumber, and then they are disposed of.

Using a spring boot @Service annotation (which in effect creates a Singleton) you can easily create and close (destroy) such workers.
Here is the code piece that starts a worker specific for a process:

//CamundaJobWroker is a class thaty holds reference to Zeebe worker and a boolean to show if is completed

// class level variable
private Map<String,CamundaJobWroker> activeWorkers = new HashMap<>();

// common method to start workers
JobWorker jw = zeebeClient
	.newWorker()
	.jobType(stepType + "-" + applicationNumber)
	.handler(
		(JobClient jobClient, ActivatedJob job) -> {
					try {
						
						zeebeClient.newCompleteCommand(job.getKey())
								.variables(variablesMap)
								.send().whenComplete((result, ex) -> {
									if (ex != null) {
										... handle exceptions here
									} else {
										// IMPORTANT: mark it as completed
										this.activeWorkers.get(workerName).complete();
									}
									
								});
					} catch (Exception ex) {
						... handle error here
					}
	 )
	.name(workerName)
	.maxJobsActive(1)
	.pollInterval(Duration.ofMillis(1000*1L))
	.open();

this.activeWorkers.put(workerName, new CamundaJobWroker(jw));


// Method to cleanup workers, executed every 5 minutes (300,000 milliseconds):
	@Scheduled(fixedRate = 300000)
	public void cleanupCompletedWorkers() {
		log.info("Cleaning up finished workers");
		activeWorkers.forEach((jobWorkerName, jobWorker) -> {

			if(jobWorker.isCompleted()){
				if(jobWorker.getJobWorker().isOpen()){
					log.info("Closing worker {}" , jobWorkerName );
					jobWorker.getJobWorker().close();
				}
			}
		});
	}

In our opinion this would be greatly simplified if ZeebeCliebt supported “moving the workflow forward” given a Process Key but such method does not exist.