{"id":13590076,"url":"https://github.com/nikku/camunda-worker-node","last_synced_at":"2025-04-15T14:57:04.654Z","repository":{"id":57139698,"uuid":"41437655","full_name":"nikku/camunda-worker-node","owner":"nikku","description":"Implement your external task workers for Camunda in NodeJS.","archived":false,"fork":false,"pushed_at":"2021-09-15T12:30:50.000Z","size":306,"stargazers_count":51,"open_issues_count":0,"forks_count":27,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-04-15T14:56:57.094Z","etag":null,"topics":["camunda","external-task","workers"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/camunda-worker-node","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nikku.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-08-26T16:47:18.000Z","updated_at":"2024-07-11T20:48:10.000Z","dependencies_parsed_at":"2022-09-03T01:20:20.360Z","dependency_job_id":null,"html_url":"https://github.com/nikku/camunda-worker-node","commit_stats":null,"previous_names":[],"tags_count":25,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nikku%2Fcamunda-worker-node","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nikku%2Fcamunda-worker-node/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nikku%2Fcamunda-worker-node/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nikku%2Fcamunda-worker-node/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nikku","download_url":"https://codeload.github.com/nikku/camunda-worker-node/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249094937,"owners_count":21211836,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["camunda","external-task","workers"],"created_at":"2024-08-01T16:00:38.754Z","updated_at":"2025-04-15T14:57:04.629Z","avatar_url":"https://github.com/nikku.png","language":"JavaScript","funding_links":[],"categories":["Community Supported"],"sub_categories":[],"readme":"# camunda-worker-node\n\n[![CI](https://github.com/nikku/camunda-worker-node/actions/workflows/CI.yml/badge.svg)](https://github.com/nikku/camunda-worker-node/actions/workflows/CI.yml)\n\nImplement your [external task workers](https://docs.camunda.org/manual/latest/user-guide/process-engine/external-tasks/) for [Camunda](http://camunda.org) in [NodeJS](https://nodejs.org/).\n\n\u003e Compatible with Camunda `\u003e= 7.8`. Requires NodeJS `\u003e= 8.6`.\n\n\n## Usage\n\nThis library exposes a simple API to implement external task workers for [Camunda](http://camunda.org).\n\n```javascript\nvar Worker = require('camunda-worker-node');\nvar Backoff = require('camunda-worker-node/lib/backoff');\n\nvar engineEndpoint = 'http://localhost:8080/engine-rest';\n\nvar worker = Worker(engineEndpoint, {\n  workerId: 'some-worker-id',\n  use: [\n    Backoff\n  ]\n});\n\n// a work subscription may access and modify process variables\nworker.subscribe('work:A', [ 'numberVar' ], async function(context) {\n\n  var newNumber = context.variables.numberVar + 1;\n\n  // fail with an error if things go awry\n  if (ooops) {\n    throw new Error('no work done');\n  }\n\n  // complete with update variables\n  return {\n    variables: {\n      numberVar: newNumber\n    }\n  };\n});\n\n// stop the worker instance with the application\nworker.stop();\n```\n\nMake sure you properly configured the [external tasks](https://docs.camunda.org/manual/latest/user-guide/process-engine/external-tasks/) in your BPMN 2.0 diagram:\n\n```xml\n\u003cbpmn:serviceTask\n  id=\"Task_A\"\n  camunda:type=\"external\"\n  camunda:topicName=\"work:A\" /\u003e\n```\n\n\n## Features\n\n* Subscribe to work [node-style](#work-node-style) or via [`async` functions](#work-with-async-function)\n* Complete tasks with updated variables or fail with errors\n* Trigger [BPMN errors](#trigger-bpmn-errors)\n* [Configure and extend task locks](#task-locks)\n* Configure [logging](#logging) and [authentication](#authentication)\n* [Configure task fetching](#task-fetching)\n* [Control the worker life-cycle](#worker-life-cycle)\n* [Extend via plug-ins](#extend-via-plug-ins)\n* [Customize Variable Serialization](#variable-serialization)\n\n\n## Resources\n\n* [Example](./example)\n* [Issues](https://github.com/nikku/camunda-worker-node/issues)\n* [Changelog](./CHANGELOG.md)\n\n\n## Implementing Worker\n\nImplement your workers via `async`, promise returning functions or pass results via node-style callbacks.\n\n\n### Work, Node Style\n\nUse the provided callback to pass task execution errors and data, node-style:\n\n```javascript\n// report work results via a node-style callback\nworkes.subscribe('work:B', function(context, callback) {\n\n  var newNumber = context.variables.numberVar + 1;\n\n  // indicate an error\n  callback(\n    new Error('no work done');\n  );\n\n  // or return actual result\n  callback(null, {\n    variables: {\n      numberVar: newNumber\n    }\n  });\n});\n```\n\n### Work with async Function\n\nES6 style async/await to implement work is fully supported:\n\n```javascript\n// implement work via a Promise returning async function\nworker.subscribe('work:B', async function(context) {\n\n  // await async increment\n  var newNumber = await increment(context.variables.numberVar);\n\n  // indicate an error\n  throw new Error('no work done');\n\n  // or return actual result\n  return {\n    variables: {\n      numberVar: newNumber\n    }\n  };\n});\n```\n\n\n## Trigger BPMN Errors\n\nYou may indicate BPMN errors to trigger business defined exception handling:\n\n```javascript\nworker.subscribe('work:B', async function(context) {\n\n  // trigger business aka BPMN errors\n  return {\n    errorCode: 'some-bpmn-error'\n  };\n});\n```\n\n\n## Task Locks\n\nYou may configure the initial lock time (defaults to 10 seconds) on worker registration.\n\nAt the same time you may use the method `extendLock`, provided via the task context,\nto increase the lock time while the worker is busy.\n\n```javascript\n// configure three seconds as initial lock time\nworker.subscribe('work:B', {\n  lockDuration: 3000,\n  variables: [ 'a' ]\n}, async function(context) {\n\n  var extendLock = context.extendLock;\n\n  // extend the lock for another five seconds\n  await extendLock(5000);\n\n  // complete task\n  return {};\n});\n```\n\nRead more about external task locking in the [Camunda Documentation](https://docs.camunda.org/manual/latest/user-guide/process-engine/external-tasks/).\n\n\n## Authentication\n\nWe provide middlewares for basic auth as well as token based authentication.\n\n### Basic Auth\n\nProvide your client credentials via the [`BasicAuth`](./lib/basic-auth.js) middleware:\n\n```javascript\nvar worker = Worker(engineEndpoint, {\n  use: [\n    BasicAuth('walt', 'SECRET_PASSWORD')\n  ]\n};\n```\n\n\n### Token Authentication\n\nProvide your tokens via the [`Auth`](./lib/auth.js) middleware:\n\n```javascript\nvar worker = Worker(engineEndpoint, {\n  use: [\n    Auth('Bearer', 'BEARER_TOKEN')\n  ]\n};\n```\n\n\n### Custom Made\n\nTo support custom authentication options add additional request headers to authenticate your task worker via the `requestOptions` configuration:\n\n```javascript\nvar worker = Worker(engineEndpoint, {\n  requestOptions: {\n    headers: {\n      Hello: 'Authenticated?'\n    }\n  }\n})\n```\n\n\n## Logging\n\nWe employ [debug](https://www.npmjs.com/package/debug) for logging.\n\nUse the [`Logger` extension](./lib/logger.js) in combination with `DEBUG=*` to capture a full trace of what's going on under the hood:\n\n```bash\nDEBUG=* node start-workers.js\n```\n\n\n## Task Fetching\n\nTask fetching is controlled by two configuration properties:\n\n* `maxTasks` - maximum number of tasks to be fetched and locked with a single poll\n* `pollingInterval` - interval in milliseconds between polls\n\nYou may configure both properties on worker creation and at run-time:\n\n```javascript\nvar worker = Worker(engineEndpoint, {\n  maxTasks: 2,\n  pollingInterval: 1500\n});\n\n// dynamically increase max tasks\nworker.configure({\n  maxTasks: 5\n});\n```\n\nThis way you can configure the task fetching behavior both statically and dynamically.\n\nRoll your own middleware to dynamically configure the worker instance or let\nthe [`Backoff` middleware](./lib/backoff.js) take care of it.\n\nAs an alternative to configuring these values you may [stop and re-start](#worker-life-cycle)\nthe Worker instance as needed, too.\n\n\n## Worker Life-Cycle\n\nPer default the worker instance will start to poll for work immediately.\nConfigure this behavior via the `autoPoll` option and start, stop and re-start\nthe instance programatically if you need to:\n\n```javascript\nvar worker = Worker(engineEndpoint, {\n  autoPoll: false\n});\n\n// manually start polling\nworker.start();\n\n// stop later on\nawait worker.stop();\n\n// re-start at some point in time\nworker.start();\n```\n\n\n## Extend via Plug-ins\n\nA worker may be extended via the `use` config parameter.\n\n```javascript\nWorker(engineEndpoint, {\n  use: [\n    Logger,\n    Backoff,\n    Metrics,\n    BasicAuth('Walt', 'SECRET_PASSWORD')\n  ]\n});\n```\n\n#### Existing Extensions\n\n* [`Logger`](./lib/logger.js) - adds verbose logging of what is going on\n* [`Backoff`](./lib/backoff.js) - dynamically adjust poll times based on Camunda REST api availability, fetched tasks and poll processing times\n* [`Metrics`](./lib/metrics.js) - collect and periodically log utilization metrics\n* [`BasicAuth`](./lib/basic-auth.js) - authorize against REST api with username + password\n* [`Auth`](./lib/auth.js) - authorize against REST api with arbitrary tokens\n\n\n## Variable Serialization\n\nVariables, when being read, modified and passed back on taks completion will preserve\ntheir serialized form (indicated via `valueInfo` as documented in the [Camunda REST API documentation](https://docs.camunda.org/manual/latest/reference/rest/external-task/post-complete/)). Newly added variables will be serialized without `valueInfo` using the types `String`, `Date`, `Boolean`, `Json` or `Double` as appropriate.\n\nYou may wrap variables with `SerializedVariable` if you would like to take full control over variable serialization:\n\n```javascript\nvar Serialized = require('camunda-worker-node/lib/serialized-variable');\n\nworker.subscribe('shop:create-customer', async function(context) {\n\n  return {\n    variables: {\n      // wrap user to indicate it is already serialized\n      customer: Serialized({\n        type: 'Object',\n        value: JSON.stringify({\n          name: 'Hugo'\n        }),\n        valueInfo: {\n          serializationDataFormat: 'application/json',\n          objectTypeName: 'my.example.Customer'\n        }\n      })\n    }\n  };\n});\n```\n\n\n## Dynamically Unregister a Work Subscription\n\nIt is possible to dynamically unregister a work subscription any time.\n\n```javascript\nvar subscription = worker.subscribe('someTopic', async function(context) {\n  // do work\n  console.log('doing work!');\n});\n\n// later\nsubscription.remove();\n```\n\n\n## Installation\n\n```bash\nnpm i --save camunda-worker-node\n```\n\n\n## Develop\n\nInstall dependencies:\n\n```bash\nnpm install\n```\n\nLint and run all tests:\n\n```bash\nDEBUG=worker* npm run all\n```\n\n__Note:__ You need a Camunda BPM REST API exposed on `localhost:8080/engine-rest` for the tests to pass. An easy way to get it up running is [via Docker](https://github.com/camunda/docker-camunda-bpm-platform#get-started).\n\n\n## Related\n\n* [External task documentation](https://docs.camunda.org/manual/latest/user-guide/process-engine/external-tasks/)\n* [Official external task client](https://github.com/camunda/camunda-external-task-client-js)\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnikku%2Fcamunda-worker-node","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnikku%2Fcamunda-worker-node","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnikku%2Fcamunda-worker-node/lists"}