Skip to content

Commit

Permalink
feat(hitl-next): create webhook for hitlnext events (#11976)
Browse files Browse the repository at this point in the history
* create_base

* add all events and pr comments
  • Loading branch information
davidvitora committed Jul 18, 2022
1 parent e4c0fdd commit 9ac31fb
Show file tree
Hide file tree
Showing 6 changed files with 88 additions and 7 deletions.
1 change: 1 addition & 0 deletions modules/hitlnext/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"axios": "^0.21.1",
"bluebird": "^3.5",
"classnames": "^2.2.6",
"exponential-backoff": "^3.1.0",
"flat": "^5.0.2",
"haikunator": "^2.1.2",
"immer": "^9.0.12",
Expand Down
8 changes: 4 additions & 4 deletions modules/hitlnext/src/backend/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ export default async (bp: typeof sdk, state: StateType, repository: Repository)

const payload: Pick<IAgent, 'online'> = { online }

realtime.sendPayload(req.params.botId, {
service.sendPayload(req.params.botId, {
resource: 'agent',
type: 'update',
id: agentId,
Expand Down Expand Up @@ -179,7 +179,7 @@ export default async (bp: typeof sdk, state: StateType, repository: Repository)
const handoff = await repository.updateHandoff(botId, id, payload)
state.cacheHandoff(botId, handoff.userThreadId, handoff)

realtime.sendPayload(botId, {
service.sendPayload(botId, {
resource: 'handoff',
type: 'update',
id: handoff.id,
Expand Down Expand Up @@ -276,7 +276,7 @@ export default async (bp: typeof sdk, state: StateType, repository: Repository)
} as sdk.IO.EventCtorArgs)
)

realtime.sendPayload(req.params.botId, {
service.sendPayload(req.params.botId, {
resource: 'handoff',
type: 'update',
id: handoff.id,
Expand Down Expand Up @@ -337,7 +337,7 @@ export default async (bp: typeof sdk, state: StateType, repository: Repository)
const comment = await repository.createComment(payload)
handoff.comments = [...handoff.comments, comment]

realtime.sendPayload(req.params.botId, {
service.sendPayload(req.params.botId, {
resource: 'handoff',
type: 'update',
id: handoff.id,
Expand Down
15 changes: 12 additions & 3 deletions modules/hitlnext/src/backend/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { MODULE_NAME } from '../constants'
import { ExitTypes, IHandoff, ISocketMessage } from '../types'
import { StateType } from '.'
import Repository from './repository'
import WebHookService from './webhook'

export const toEventDestination = (
botId: string,
Expand All @@ -19,12 +20,15 @@ interface Realtime {
}

class Service {
webhook: WebHookService
constructor(
private bp: typeof sdk,
private state: StateType,
private repository: Repository,
private realtime: Realtime
) {}
) {
this.webhook = new WebHookService(bp)
}

async createHandoff(
botId: string,
Expand All @@ -45,7 +49,7 @@ class Service {
await this.sendMessageToUser(config.transferMessage, eventDestination, language)
}

this.realtime.sendPayload(botId, { resource: 'handoff', type: 'create', id: handoff.id, payload: handoff })
this.sendPayload(botId, { resource: 'handoff', type: 'create', id: handoff.id, payload: handoff })

if (timeoutDelay !== undefined && timeoutDelay > 0) {
setTimeout(async () => {
Expand Down Expand Up @@ -93,7 +97,7 @@ class Service {
}

updateRealtimeHandoff(botId: string, handoff: Partial<IHandoff>) {
return this.realtime.sendPayload(botId, { resource: 'handoff', type: 'update', id: handoff.id, payload: handoff })
return this.sendPayload(botId, { resource: 'handoff', type: 'update', id: handoff.id, payload: handoff })
}

async transferToBot(event: sdk.IO.EventDestination, exitType: ExitTypes, agentName?: string) {
Expand All @@ -107,6 +111,11 @@ class Service {

await this.bp.events.sendEvent(stateUpdate)
}

sendPayload(botId: string, data: { resource: string; type: string; id: string; payload: any }) {
this.realtime.sendPayload(botId, data)
void this.webhook.send({ botId, ...data })
}
}

export default Service
59 changes: 59 additions & 0 deletions modules/hitlnext/src/backend/webhook.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import axios, { AxiosError, AxiosRequestConfig } from 'axios'
import * as sdk from 'botpress/sdk'
import { backOff } from 'exponential-backoff'
import { Webhook } from '../config'
import { MODULE_NAME } from '../constants'

const MAX_ATTEMPTS = 10

class WebHookService {
private config: Webhook
private disabled = true
constructor(private bp: typeof sdk) {
void this.setup()
}

private async setup() {
this.config = (await this.bp.config.getModuleConfig(MODULE_NAME)).eventsWebHook
this.disabled = !this.config
}

public async send(data: { botId: string; type: string; resource: string; id: string; payload: any }) {
if (this.disabled) {
return
}

const { url, headers } = this.config
const config: AxiosRequestConfig = {}

if (headers) {
config.headers = headers
}

try {
await backOff(async () => axios.post(url, data, config), {
jitter: 'none',
numOfAttempts: MAX_ATTEMPTS,
retry: (e: AxiosError, attemptNumber: number) => {
if (attemptNumber === 1 && e.response?.status !== 503) {
this.logWebhookError(e, url, 'Failed to send webhook event on first attempt. Retrying 9 more times')
}
return true
}
})
} catch (e) {
this.logWebhookError(e as AxiosError, url, `Unable to send webhook event after ${MAX_ATTEMPTS} attempts`)
}
}

private logWebhookError(e: AxiosError, url: string, message: string) {
this.bp.logger.warn(message, {
url,
message: e.message,
response: e.response?.data,
status: e.response?.status
})
}
}

export default WebHookService
7 changes: 7 additions & 0 deletions modules/hitlnext/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ export interface Config {
assignMessage: {
[Key: string]: string
}

eventsWebHook: Webhook
}

export interface IShortcut {
Expand All @@ -82,3 +84,8 @@ export interface IAutoComplete {
*/
shortcuts: IShortcut[]
}

export interface Webhook {
url: string
headers: { [name: string]: string }
}
5 changes: 5 additions & 0 deletions modules/hitlnext/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,11 @@ es-to-primitive@^1.2.1:
is-date-object "^1.0.1"
is-symbol "^1.0.2"

exponential-backoff@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/exponential-backoff/-/exponential-backoff-3.1.0.tgz#9409c7e579131f8bd4b32d7d8094a911040f2e68"
integrity sha512-oBuz5SYz5zzyuHINoe9ooePwSu0xApKWgeNzok4hZ5YKXFh9zrQBEM15CXqoZkJJPuI2ArvqjPQd8UKJA753XA==

flat@^5.0.2:
version "5.0.2"
resolved "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241"
Expand Down

0 comments on commit 9ac31fb

Please sign in to comment.