Skip to content

Commit

Permalink
Added allowFailure flag to actions
Browse files Browse the repository at this point in the history
closes #35
  • Loading branch information
elboletaire committed Feb 6, 2019
1 parent 8a5f50c commit a3604bc
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 6 deletions.
22 changes: 17 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,19 +126,18 @@ Here's an example of an operator:

~~~yaml
# Execute every time a purchase is update
name: someUniqueName
name: some-unique-name-for-this-operator
eventName: events.purchase
route: updated
# true by default, but here you can see you're able to disable them just adding this key.
enabled: true
output: "interleaved|group|prefixed"
actions:
# Print event purchase logs
- name: print-log
type: log # Type log will use log plugin

# Check if event purchase is paid
- name: shouldSendEmail
- name: should-send-email
# Type conditional will stop operator execution if some condition is not meet.
type: conditional
options:
Expand All @@ -149,7 +148,7 @@ actions:
operation: defined

# Convert event to email
- name: eventToEmailMapper
- name: map-event-to-email
# Type mapper gets the previous action result and converts its fields to a new object with the specified structure.
type: mapper
options:
Expand All @@ -163,12 +162,21 @@ actions:
'*': vars

# Send membership to emails queue applying
- name: sendEventPurchaseToEmailQueue
- name: send-event-purchase-to-email-queue
# Type prev2task gets the previous action message and sends it to a task queue.
type: prev2task
options:
target: emails
targetRoute: email.send

# Send a telegram message to a specific group chat
- name: send-telegram-message
type: telegram
# In case the Telegram API fails, ignore the error
allowFailure: true
options:
chatId: '-12345'
template: 'Member with e-mail {{ to }} has registered for event {{ vars.event.name }}'
~~~

### Available actions to be defined in operators
Expand Down Expand Up @@ -212,8 +220,11 @@ It checks for defined conditions in the received object and aborts execution if
- field: someReceivingObjField
operation: ===
checkValue: valueToCheckAgainst

~~~

> **Note:** enabling `allowFailure` here would make the plugin to not work as expected.
##### Conditional operations

- `true` | `isTrue`: Value is set as boolean `true`.
Expand All @@ -225,6 +236,7 @@ It checks for defined conditions in the received object and aborts execution if
- `===`: Variable equals `checkValue`.
- `!==`: Variable does not equal `checkValue`.


#### `mapper`

It converts the message from the last action executed, to a new object following the specified mapping.
Expand Down
14 changes: 13 additions & 1 deletion src/model/Action.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,26 @@
type ConstructorParams = {
name: string,
type: string,
options: any,
event: string,
allowFailure?: boolean,
}

export default class Action {
name: string
type: string
options: any
event: string
allowFailure?: boolean

constructor({name, type, options, event}: {name: string, type: string, options: any, event: string}) {
constructor({name, type, options, event, allowFailure}: ConstructorParams) {
this.name = name
this.type = type
this.options = options
this.event = event
if (typeof allowFailure !== 'undefined') {
this.allowFailure = allowFailure
}
}

toString() {
Expand Down
54 changes: 54 additions & 0 deletions src/worker/ActionExecuter.spec.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
import axios from 'axios'
import axiosMockAdapter from 'axios-mock-adapter'
import rabbit from 'rabbot'
import ActionExecuter from './ActionExecuter'
import Action from '../model/Action'
import Event from '../model/Event'

const axiosMock = new axiosMockAdapter(axios)

describe('ActionExecuter', () => {
it('should handle comming events', () => {
const action = new Action({
Expand Down Expand Up @@ -58,4 +62,54 @@ describe('ActionExecuter', () => {

return expect(actionExecuter.execute(msg)).resolves.toBeTruthy()
})

it('should fail on error', () => {
const action = new Action({
name: 'sendMembershipsToEmail',
type: 'invented',
options: {},
event: '',
})

const actionExecuter = new ActionExecuter(action, rabbit, new Event({
name: 'test',
eventName: 'test',
route: 'test',
actions: []
}))

return expect(actionExecuter.execute({})).rejects.toBeTruthy()
})

it('should not fail on error if allowFailure is set to true', () => {
axiosMock.onPost(/api\.telegram\.org/).reply(404)

const action = new Action({
name: 'sendMembershipsToEmail',
type: 'telegram',
allowFailure: true,
options: {
chatId: '',
template: '',
},
event: 'event-name',
})

const actionExecuter = new ActionExecuter(action, rabbit, new Event({
name: 'test',
eventName: 'test',
route: 'test',
actions: [],
}))

const msg = {
body: {
test: 'Test',
test2: 'Test2',
toString: () => '{test1: "Test", test2: "Test2"}'
}
}

return expect(actionExecuter.execute(msg)).resolves.toEqual(msg)
})
})
6 changes: 6 additions & 0 deletions src/worker/ActionExecuter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,12 @@ export default class ActionExecuter {
return result
})
.catch((err) => {
if (this.action.allowFailure) {
logger.info(this.preLog, 'Action execution failed, but allowFailure is set, so ignoring...')

return Promise.resolve(message)
}

debug('Action executed failed with %j', err)

throw err
Expand Down

0 comments on commit a3604bc

Please sign in to comment.