Skip to content
This repository has been archived by the owner on Apr 8, 2024. It is now read-only.

Commit

Permalink
0.20.3 (#70)
Browse files Browse the repository at this point in the history
0.20.3
  • Loading branch information
s3than authored Sep 10, 2019
2 parents bea0b2e + c1d372e commit 6630b69
Show file tree
Hide file tree
Showing 9 changed files with 143 additions and 32 deletions.
18 changes: 15 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,23 +93,35 @@ Retry is provided by [promise-retry](https://www.npmjs.com/package/promise-retry

Additionally, the gRPC Client will contiually reconnect when in a failed state.

### TLS

Enable a secure connection by setting `useTLS: true`:

```typescript
const zbc = new ZB.ZBClient(tlsProxiedGatewayAddress, {
useTLS: true,
})
```

### OAuth

In case you need to connect to a secured endpoint with OAuth (such as Camunda Cloud), you can pass in OAuth credentials. This will enable TLS, and handle the OAuth flow to get / renew a JWT:
In case you need to connect to a secured endpoint with OAuth (such as Camunda Cloud), you can pass in OAuth credentials. This will enable TLS (unless you explicitly disable it with `useTLS: false`), and handle the OAuth flow to get / renew a JWT:

```typescript
const zbc = new ZB.ZBClient("103ca930-6da6-4df7-aa97-941eb1f85040.zeebe.camunda.io:443", {
auth: {
oAuth: {
url: "https://login.cloud.camunda.io/oauth/token",
audience: "103ca930-6da6-4df7-aa97-941eb1f85040.zeebe.camunda.io",
clientId: "yStuGvJ6a1RQhy8DQpeXJ80yEpar3pXh",
clientSecret:
"WZahIGHjyj0-oQ7DZ_aH2wwNuZt5O8Sq0ZJTz0OaxfO7D6jaDBZxM_Q-BHRsiGO_",
cache: true
cacheOnDisk: true
}
}
```
The `cacheOnDisk` option will cache the token on disk, which can be useful in development if you are restarting the service frequently.
### Create a Task Worker
```javascript
Expand Down
1 change: 1 addition & 0 deletions interfaces/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from '../dist/lib/interfaces'
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "zeebe-node",
"version": "v0.20.2",
"version": "v0.20.3",
"description": "A Node.js client library for the Zeebe Microservices Orchestration Engine.",
"keywords": [
"zeebe",
Expand Down
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export { BpmnParser } from './lib/BpmnParser'
export * from './lib/interfaces'
export * from './zb/ZBClient'
export * from './zb/ZBWorker'
4 changes: 3 additions & 1 deletion src/lib/GRPCClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ export class GRPCClient extends EventEmitter {
packageName,
protoPath,
service,
useTLS,
}: {
host: string
loglevel: Loglevel
Expand All @@ -71,6 +72,7 @@ export class GRPCClient extends EventEmitter {
packageName: string
protoPath: string
service: string
useTLS: boolean
}) {
super()
this.oAuth = oAuth
Expand All @@ -95,7 +97,7 @@ export class GRPCClient extends EventEmitter {

const proto = loadPackageDefinition(this.packageDefinition)[packageName]
const listMethods = this.packageDefinition[`${packageName}.${service}`]
const channelCredentials = oAuth
const channelCredentials = useTLS
? credentials.createSsl()
: credentials.createInsecure()
this.client = new proto[service](host, channelCredentials, {
Expand Down
25 changes: 15 additions & 10 deletions src/lib/OAuthProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@ export interface OAuthProviderConfig {
clientId: string
clientSecret: string
/** Cache token in memory and on filesystem? */
cache: boolean
cacheOnDisk: boolean
}

export class OAuthProvider {
private static cachedTokenFile = (clientId: string) =>
`./.oauth-token-${clientId}.json`
Expand All @@ -27,7 +28,7 @@ export class OAuthProvider {
public clientId: string
public clientSecret: string
public useFileCache: boolean
public tokenCache = new Map()
public tokenCache = {}

constructor({
/** OAuth Endpoint URL */
Expand All @@ -37,24 +38,24 @@ export class OAuthProvider {
clientId,
clientSecret,
/** Cache token in memory and on filesystem? */
cache,
cacheOnDisk,
}: {
url: string
audience: string
clientId: string
clientSecret: string
cache: boolean
cacheOnDisk: boolean
}) {
this.url = url
this.audience = audience
this.clientId = clientId
this.clientSecret = clientSecret
this.useFileCache = cache
this.useFileCache = cacheOnDisk
}

public async getToken(): Promise<string> {
if (this.tokenCache.has(this.clientId)) {
return this.tokenCache.get(this.clientId).access_token
if (this.tokenCache[this.clientId]) {
return this.tokenCache[this.clientId].access_token
}
if (this.useFileCache) {
const cachedToken = this.fromFileCache(this.clientId)
Expand All @@ -79,6 +80,7 @@ export class OAuthProvider {
if (this.useFileCache) {
this.toFileCache(token)
}
this.tokenCache[this.clientId] = token
this.startExpiryTimer(token)

return token.access_token
Expand Down Expand Up @@ -112,13 +114,16 @@ export class OAuthProvider {

private toFileCache(token: Token) {
const d = new Date()
const file = OAuthProvider.cachedTokenFile(this.clientId)
fs.writeFile(
OAuthProvider.cachedTokenFile(this.clientId),
file,
JSON.stringify({
...token,
expiry: d.setSeconds(d.getSeconds() + token.expires_in),
}),
e => {
// tslint:disable-next-line
console.log('Error writing OAuth token to file' + file)
// tslint:disable-next-line
console.error(e)
}
Expand All @@ -135,9 +140,9 @@ export class OAuthProvider {
const current = d.setSeconds(d.getSeconds())
const validityPeriod = token.expiry - current * 1000
if (validityPeriod <= 0) {
this.tokenCache.delete(this.clientId)
delete this.tokenCache[this.clientId]
return
}
setTimeout(() => this.tokenCache.delete(this.clientId), validityPeriod)
setTimeout(() => delete this.tokenCache[this.clientId], validityPeriod)
}
}
104 changes: 91 additions & 13 deletions src/lib/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,16 @@ export type Loglevel = 'INFO' | 'DEBUG' | 'NONE' | 'ERROR'

export interface CompleteFn<WorkerOutputVariables> {
(updatedVariables?: Partial<WorkerOutputVariables>): boolean
/**
* Complete the job with a success, optionally passing in a state update to merge
* with the workflow variables on the broker.
*/
success: (updatedVariables?: Partial<WorkerOutputVariables>) => boolean
/**
* Fail the job with an informative message as to the cause. Optionally pass in a
* value remaining retries. If no value is passed for retries then the current retry
* count is decremented. Pass in `0`for retries to raise an incident in Operate.
*/
failure: (errorMessage: string, retries?: number) => void
}

Expand All @@ -25,14 +34,6 @@ export interface OperationOptionsNoRetry {
version?: number
}

export function hasRetry(options): options is OperationOptionsWithRetry {
return options.retry === true
}

export function noRetry(options): options is OperationOptionsNoRetry {
return options.retry === false
}

export type OperationOptions =
| OperationOptionsWithRetry
| OperationOptionsNoRetry
Expand Down Expand Up @@ -85,10 +86,28 @@ export interface ActivateJobsResponse {
* Request object to send the broker to request jobs for the worker.
*/
export interface ActivateJobsRequest {
/**
* The job type, as defined in the BPMN process (e.g. <zeebe:taskDefinition
* type="payment-service" />)
*/
type: string
/** The name of the worker activating the jobs, mostly used for logging purposes */
worker: string
/**
* The duration the broker allows for jobs activated by this call to complete
* before timing them out releasing them for retry on the broker.
* The broker checks time outs every 30 seconds, so the broker timeout is guaranteed in at-most timeout + 29s
* be guaranteed.
*/
timeout: number
/**
* The maximum jobs to activate by this request
*/
maxJobsToActivate: number
/**
* A list of variables to fetch as the job variables; if empty, all visible variables at
* the time of activation for the scope of the job will be returned
*/
fetchVariable?: string[]
/**
* The request will be completed when atleast one job is activated or after the requestTimeout.
Expand All @@ -100,44 +119,84 @@ export interface ActivateJobsRequest {
}

export interface ActivatedJob {
/** The key, a unique identifier for the job */
readonly key: string
/**
* The job type, as defined in the BPMN process (e.g. <zeebe:taskDefinition
* type="payment-service" />)
*/
readonly type: string
/** The job's workflow instance key */
readonly workflowInstanceKey: string
/** The bpmn process ID of the job workflow definition */
readonly bpmnProcessId: string
/** The version of the job workflow definition */
readonly workflowDefinitionVersion: number
/** The key of the job workflow definition */
readonly workflowKey: string
/** The associated task element ID */
readonly elementId: string
/**
* The unique key identifying the associated task, unique within the scope of the
* workflow instance
*/
readonly elementInstanceKey: string
/**
* JSON object as a string
* A set of custom headers defined during modelling
*/
readonly customHeaders: string
/** The name of the worker that activated this job */
readonly worker: string
/* The amount of retries left to this job (should always be positive) */
readonly retries: number
/**
* epoch milliseconds
* When the job will timeout on the broker if it is not completed by this worker.
* In epoch milliseconds
*/
readonly deadline: string
/**
* JSON object as a string
* All visible variables in the task scope, computed at activation time, constrained by any
* fetchVariables value in the ActivateJobRequest.
*/
readonly variables: string
}

export interface Job<Variables = KeyedObject, CustomHeaders = KeyedObject> {
/** The key, a unique identifier for the job */
readonly key: string
/**
* The job type, as defined in the BPMN process (e.g. <zeebe:taskDefinition
* type="payment-service" />)
*/
readonly type: string
/** The job's workflow instance key */
readonly workflowInstanceKey: string
/** The bpmn process ID of the job workflow definition */
readonly bpmnProcessId: string
/** The version of the job workflow defini` tion */
readonly workflowDefinitionVersion: number
/** The key of the job workflow definition */
readonly workflowKey: string
/** The associated task element ID */
readonly elementId: string
/**
* The unique key identifying the associated task, unique within the scope of the
* workflow instance
*/
readonly elementInstanceKey: string
/**
* A set of custom headers defined during modelling
*/
readonly customHeaders: CustomHeaders
/** The name of the worker that activated this job */
readonly worker: string
/* The amount of retries left to this job (should always be positive) */
readonly retries: number
// epoch milliseconds
readonly deadline: string
/**
* All visible variables in the task scope, computed at activation time.
*/
readonly variables: Variables
}

Expand All @@ -147,7 +206,8 @@ export interface ZBWorkerOptions {
*/
maxJobsToActivate?: number
/**
* Max ms to allow before time out of a task given to this worker. Default: 1000ms.
* Max ms to allow before time out of a task given to this worker. Default: 30000ms.
* The broker checks deadline timeouts every 30 seconds, so an
*/
timeout?: number
/**
Expand Down Expand Up @@ -179,9 +239,26 @@ export interface CreateWorkflowInstanceRequest<Variables = KeyedObject> {
}

export interface CreateWorkflowInstanceResponse {
/**
* The unique key identifying the workflow definition (e.g. returned from a workflow
* in the DeployWorkflowResponse message)
*/
readonly workflowKey: string
/**
* The BPMN process ID of the workflow definition
*/
readonly bpmnProcessId: string
/**
* The version of the process; set to -1 to use the latest version
*/
readonly version: number
/**
* Stringified JSON document that will instantiate the variables for the root variable scope of the
* workflow instance; it must be a JSON object, as variables will be mapped in a
* key-value fashion. e.g. { "a": 1, "b": 2 } will create two variables, named "a" and
* "b" respectively, with their associated values. [{ "a": 1, "b": 2 }] would not be a\
* valid argument, as the root of the JSON document is an array and not an object.
*/
readonly workflowInstanceKey: string
}

Expand Down Expand Up @@ -319,7 +396,8 @@ export interface ZBClientOptions {
retry?: boolean
maxRetries?: number
maxRetryTimeout?: number
auth?: OAuthProviderConfig
oAuth?: OAuthProviderConfig
useTLS?: boolean
longPoll?: number
}

Expand Down
Loading

0 comments on commit 6630b69

Please sign in to comment.