camunda/camunda-8-js-sdk

[Feature Request] Support multi-tenanted Zeebe workers

Closed this issue · 5 comments

SDK Component

Zeebe

Expected Behavior

When creating a Zeebe worker via zeebe.createWorker in a multi-tenanted environment, the worker options should accept a single tenantId or an array of tenantIds.

Current Behavior

When creating a Zeebe worker via zeebe.createWorker, the tenantId property is missing in the typings. Adding it anyway (ignoring Typescript), does work and allows the worker to be single-tenanted. However, the SDK only seems to support a single tenant.

Possible Solution

Expose/create a tenantIds property on the ZBWorkerBase class, and update the following implementation that forces a single tenant: https://github.com/camunda/camunda-8-js-sdk/blob/main/src/zeebe/lib/ZBWorkerBase.ts#L563

Steps to Reproduce

  1. Enable multi-tenancy
  2. Create a Zeebe worker and force the tenantId into the zeebe.createWorker options - the worker connects successfully
  3. Try to pass multiple tenants into the zeebe.createWorker options with the tenantIds property via an array, note it does not work

Context (Environment)

While it's possible to force a worker to be single-tenanted (despite the missing type), it's not possible to have a worker multi-tenanted. Meaning, if multiple tenants share the same job, a separate worker must be created per tenant per job.

At the moment, the worker inherits the process environment CAMUNDA_TENANT_ID value.

You can override this by supplying a specific tenantId to the createWorker call (and yes, it is undocumented at the moment).

You really want a multi-tenanted worker?

I had avoided supporting this scenario because it seems like you would want to enforce data segregation in the worker.

We could make the tenantId explicit, and accept an array of values; it would be optional, and if not supplied it would default to the CAMUNDA_TENANT_ID value from the client constructor or environment.

How does that sound?

We could make the tenantId explicit, and accept an array of values; it would be optional, and if not supplied it would default to the CAMUNDA_TENANT_ID value from the client constructor or environment.

How does that sound?

This sounds great! Thank you! 🙂

Our use case for multi-tenanted workers is that many of our products have relatively similar BPMNs/jobs, with the only input difference being the tenantId when executed. We enforce segregation at the application-level via RLS and some other methods, so the worker itself is less of a concern.

Thanks again!

@jwulf I think this was accidentally closed - the linked PR looks unrelated

Out in 8.6.1

Example use:

client.createWorker({
   taskHandler: (job) => {
      console.log(job.tenantId) // '<default>' | 'green'
      return job.complete()
   },
   taskType: 'multi-tenant-work',
   tenantIds: ['<default>', 'green'],
})

client.streamJobs({
   taskHandler: async (job) => {
      console.log(job.tenantId) // '<default>' | 'green'
      return job.complete()
   },
   type: 'multi-tenant-stream-work',
   tenantIds: ['<default>', 'green'],
   worker: 'stream-worker',
   timeout: 2000,
})