Skip to content

Commit

Permalink
fix(realtime): allow to use websocket without sticky sessions (#5688)
Browse files Browse the repository at this point in the history
* chore: bump socket.io to latest version

* fetch visitor id remotely if needed

* removed unused code

* fix code for fetch visitor id remotely + removed todo

* fix use jwt cookies with realtime service

* chore(admin): update recommendations for sticky sessions (#5693)

* bump studio bin version

* fix ie & build steps

* removed admin socket in ui-lite and removed guest socket in admin

Co-authored-by: Francois-Xavier P. Darveau <955524+EFF@users.noreply.github.com>
Co-authored-by: allardy <yann.allard1@gmail.com>
  • Loading branch information
3 people committed Nov 29, 2021
1 parent 472cd2d commit 5181340
Show file tree
Hide file tree
Showing 16 changed files with 587 additions and 417 deletions.
10 changes: 1 addition & 9 deletions build/gulp.ui.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const verbose = process.argv.includes('--verbose')
const build = () => {
gulp.task('build:shared', gulp.series([cleanShared, sharedBuild]))
gulp.task('build:admin', gulp.series([buildAdmin, cleanAdmin, copyAdmin]))
gulp.task('build:lite', gulp.series([buildLite, cleanLite, copyLite]))
gulp.task('build:lite', buildLite)

if (yn(process.env.GULP_PARALLEL)) {
return gulp.series(['build:shared', gulp.parallel(['build:admin', 'build:lite'])])
Expand Down Expand Up @@ -49,14 +49,6 @@ const buildLite = cb => {
admin.stderr.pipe(process.stderr)
}

const cleanLite = () => {
return gulp.src('./packages/bp/dist/ui-lite/public', { allowEmpty: true }).pipe(rimraf())
}

const copyLite = () => {
return gulp.src('./packages/ui-lite/public/**/*').pipe(gulp.dest('./packages/bp/dist/ui-lite/public'))
}

const cleanAdmin = () => {
return gulp.src('./packages/bp/dist/admin/ui/public', { allowEmpty: true }).pipe(rimraf())
}
Expand Down
2 changes: 1 addition & 1 deletion modules/hitlnext/src/views/full/AgentStatus.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ const AgentStatus: FC<Props> = ({ bp }) => {

useEffect(() => {
bp.events.on(`${WEBSOCKET_TOPIC}:${window.BOT_ID}`, handleMessage)
return () => bp.events.off(`hitlnext:${window.BOT_ID}`, handleMessage)
return () => bp.events.off(`${WEBSOCKET_TOPIC}:${window.BOT_ID}`, handleMessage)
}, [])

return <AgentIcon online={state.currentAgent?.online} />
Expand Down
4 changes: 1 addition & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"version": "0.1.9"
},
"studio": {
"version": "0.0.42"
"version": "0.0.43"
},
"messaging": {
"version": "0.1.17"
Expand Down Expand Up @@ -95,8 +95,6 @@
"@types/redlock": "^4.0.0",
"@types/seedrandom": "^2.4.28",
"@types/semver": "^7.3.8",
"@types/socket.io": "^2.1.2",
"@types/socket.io-client": "^1.4.36",
"@types/tar": "^4.0.4",
"@types/tmp": "^0.0.33",
"@types/universal-analytics": "^0.4.2",
Expand Down
6 changes: 3 additions & 3 deletions packages/bp/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"@babel/parser": "^7.11.2",
"@babel/traverse": "^7.11.0",
"@microsoft/recognizers-text-suite": "^1.3.0",
"@socket.io/redis-adapter": "^7.0.1",
"axios": "^0.21.1",
"bluebird-global": "^1.0.1",
"bluebird-retry": "^0.11.0",
Expand Down Expand Up @@ -95,9 +96,8 @@
"replace-in-file": "^4.1.1",
"seedrandom": "^3.0.5",
"semver": "^5.6.0",
"socket.io": "^2.2.0",
"socket.io-redis": "^5.2.0",
"socketio-jwt": "^4.5.0",
"socket.io": "^4.3.2",
"socket.io-client": "^4.3.2",
"tar": "^4.4.19",
"tmp": "^0.0.33",
"universal-analytics": "^0.4.20",
Expand Down
1 change: 1 addition & 0 deletions packages/bp/src/admin/ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
"redux": "^4.0.5",
"redux-thunk": "^2.3.0",
"snarkdown": "^1.2.2",
"socket.io-client": "^4.3.2",
"ui-shared": "link:../../../ui-shared"
},
"devDependencies": {
Expand Down
29 changes: 5 additions & 24 deletions packages/bp/src/admin/ui/src/app/EventBus.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import { auth } from 'botpress/shared'
import { EventEmitter2 } from 'eventemitter2'
import io from 'socket.io-client'
import { Socket, io } from 'socket.io-client'

// Copied mostly as-is from ui-studio
class EventBus extends EventEmitter2 {
private adminSocket!: SocketIOClient.Socket
private guestSocket!: SocketIOClient.Socket
private adminSocket!: Socket
static default: EventBus

constructor() {
Expand All @@ -24,49 +23,31 @@ class EventBus extends EventEmitter2 {
return
}

const socket = name.startsWith('guest.') ? this.guestSocket : this.adminSocket
const socket = this.adminSocket
socket && socket.emit('event', { name, data })
}

private updateVisitorSocketId() {
window.__BP_VISITOR_SOCKET_ID = this.guestSocket.id
}

setup = (customVisitorId?: string) => {
const query = {
visitorId: customVisitorId || auth.getUniqueVisitorId('admin')
}

const token = auth.getToken()
if (token) {
Object.assign(query, { token })
}

if (this.adminSocket) {
this.adminSocket.off('event', this.dispatchSocketEvent)
this.adminSocket.disconnect()
}

if (this.guestSocket) {
this.guestSocket.off('event', this.dispatchSocketEvent)
this.guestSocket.off('connect', this.updateVisitorSocketId)
this.guestSocket.disconnect()
}

const socketUrl = window['BP_SOCKET_URL'] || window.location.origin
const transports = window.SOCKET_TRANSPORTS
const token = auth.getToken()

this.adminSocket = io(`${socketUrl}/admin`, {
auth: { token },
query,
transports,
path: `${window['ROOT_PATH']}/socket.io`
})
this.adminSocket.on('event', this.dispatchSocketEvent)

this.guestSocket = io(`${socketUrl}/guest`, { query, transports, path: `${window['ROOT_PATH']}/socket.io` })

this.guestSocket.on('connect', this.updateVisitorSocketId.bind(this))
this.guestSocket.on('event', this.dispatchSocketEvent)
}
}

Expand Down
30 changes: 9 additions & 21 deletions packages/bp/src/admin/ui/src/management/checklist/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import { fetchServerConfig } from './reducer'
import style from './style.scss'

const NOT_SET = 'Not set'
const NB_PING_FOR_STICKY_SESSIONS = 3

const getDisplayValue = (val: any) => {
if (val === undefined || val === null) {
Expand Down Expand Up @@ -55,7 +54,6 @@ const Container = props => {
export const Checklist: FC<Props> = props => {
const [langSource, setLangSource] = useState<any>()
const [hasAuditTrail, setAuditTrail] = useState(false)
const [stickyEnabled, setStickyEnabled] = useState(false)

useEffect(() => {
if (!props.serverConfigLoaded) {
Expand All @@ -70,7 +68,6 @@ export const Checklist: FC<Props> = props => {
setLangSource(sources.languageSources)

await checkAuditTrail()
await checkStickySessions()
}

const checkAuditTrail = async () => {
Expand All @@ -82,17 +79,6 @@ export const Checklist: FC<Props> = props => {
setAuditTrail(_.some(audit, Boolean))
}

const checkStickySessions = async () => {
const results: string[] = await Promise.all(
_.times(NB_PING_FOR_STICKY_SESSIONS, async () => {
const { data } = await api.getSecured().get('/admin/ping')
return data.payload.serverId
})
)

setStickyEnabled(_.every(results, res => res === results[0]))
}

if (!props.serverConfig) {
return (
<Container>
Expand Down Expand Up @@ -259,19 +245,21 @@ export const Checklist: FC<Props> = props => {

<Item
title="Enable Sticky Sessions"
docs="https://botpress.com/docs/next/tutorials/cluster-digital-ocean#instructions"
status={stickyEnabled ? 'success' : 'warning'}
docs="https://botpress.com/docs/tutorials/cluster-digital-ocean#instructions"
status="none"
source={[
{ type: 'config', key: 'httpServer.socketTransports', value: getConfig('httpServer.socketTransports') }
]}
>
When running Botpress in Cluster mode with multiple servers, it is recommended to enable sticky sessions so
users are being served from the same server. When using "Websocket" as a primary socket transport, it is
mandatory to enable it, otherwise the handshake will never complete. A green check indicates that either
sticky is enabled, or you only have one server.
When using "Polling" as a primary or secondary socket transport, it is mandatory to enable sticky sessions,
otherwise the handshake may never complete. If you decide to use "Websocket" as the only transport, which is a
valid option nowadays, you don't need to enable sticky sessions.
<br />
<br />
<strong>This setting must be enabled on your load balancer.</strong>
See this documentation for more details:{' '}
<a href="https://socket.io/docs/v4/using-multiple-nodes/#why-is-sticky-session-required" target="_blank">
https://socket.io/docs/v4/using-multiple-nodes/#why-is-sticky-session-required
</a>
<br />
<br />
Here is your current socket transports configuration:
Expand Down
94 changes: 94 additions & 0 deletions packages/bp/src/admin/ui/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1932,6 +1932,11 @@
dependencies:
"@sinonjs/commons" "^1.7.0"

"@socket.io/component-emitter@~3.0.0":
version "3.0.0"
resolved "https://registry.yarnpkg.com/@socket.io/component-emitter/-/component-emitter-3.0.0.tgz#8863915676f837d9dad7b76f50cb500c1e9422e9"
integrity sha512-2pTGuibAXJswAPJjaKisthqS/NOK5ypG4LYT6tEAV0S/mxW0zOIvYvGK0V8w8+SHxAm6vRMSjqSalFXeBAqs+Q==

"@surma/rollup-plugin-off-main-thread@^1.1.1":
version "1.4.2"
resolved "https://registry.npmjs.org/@surma/rollup-plugin-off-main-thread/-/rollup-plugin-off-main-thread-1.4.2.tgz#e6786b6af5799f82f7ab3a82e53f6182d2b91a58"
Expand Down Expand Up @@ -3356,6 +3361,11 @@ babylon@^6.18.0:
resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3"
integrity sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==

backo2@~1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/backo2/-/backo2-1.0.2.tgz#31ab1ac8b129363463e35b3ebb69f4dfcfba7947"
integrity sha1-MasayLEpNjRj41s+u2n038+6eUc=

balanced-match@^0.4.2:
version "0.4.2"
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-0.4.2.tgz#cb3f3e3c732dc0f01ee70b403f302e61d7709838"
Expand All @@ -3366,6 +3376,11 @@ balanced-match@^1.0.0:
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c=

base64-arraybuffer@~1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/base64-arraybuffer/-/base64-arraybuffer-1.0.1.tgz#87bd13525626db4a9838e00a508c2b73efcf348c"
integrity sha512-vFIUq7FdLtjZMhATwDul5RZWv2jpXQ09Pd6jcVEOvIsqCWTRFD/ONHNfyOS8dA/Ippi5dsIgpyKWKZaAKZltbA==

base64-js@^1.0.2:
version "1.3.0"
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.0.tgz#cab1e6118f051095e58b5281aea8c1cd22bfc0e3"
Expand Down Expand Up @@ -4859,6 +4874,13 @@ debug@^4.1.1:
dependencies:
ms "2.1.2"

debug@~4.3.1, debug@~4.3.2:
version "4.3.2"
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.2.tgz#f0a49c18ac8779e31d4a0c6029dfb76873c7428b"
integrity sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==
dependencies:
ms "2.1.2"

decamelize@^1.1.1, decamelize@^1.1.2, decamelize@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
Expand Down Expand Up @@ -5285,6 +5307,28 @@ end-of-stream@^1.0.0, end-of-stream@^1.1.0:
dependencies:
once "^1.4.0"

engine.io-client@~6.0.1:
version "6.0.2"
resolved "https://registry.yarnpkg.com/engine.io-client/-/engine.io-client-6.0.2.tgz#ccfc059051e65ca63845e65929184757754cc34e"
integrity sha512-cAep9lhZV6Q8jMXx3TNSU5cydMzMed8/O7Tz5uzyqZvpNPtQ3WQXrLYGADxlsuaFmOLN7wZLmT7ImiFhUOku8g==
dependencies:
"@socket.io/component-emitter" "~3.0.0"
debug "~4.3.1"
engine.io-parser "~5.0.0"
has-cors "1.1.0"
parseqs "0.0.6"
parseuri "0.0.6"
ws "~8.2.3"
xmlhttprequest-ssl "~2.0.0"
yeast "0.1.2"

engine.io-parser@~5.0.0:
version "5.0.1"
resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-5.0.1.tgz#6695fc0f1e6d76ad4a48300ff80db5f6b3654939"
integrity sha512-j4p3WwJrG2k92VISM0op7wiq60vO92MlF3CRGxhKHy9ywG1/Dkc72g0dXeDQ+//hrcDn8gqQzoEkdO9FN0d9AA==
dependencies:
base64-arraybuffer "~1.0.1"

enhanced-resolve@^4.3.0:
version "4.5.0"
resolved "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz#2f3cfd84dbe3b487f18f2db2ef1e064a571ca5ec"
Expand Down Expand Up @@ -6540,6 +6584,11 @@ has-bigints@^1.0.0:
resolved "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz#64fe6acb020673e3b78db035a5af69aa9d07b113"
integrity sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==

has-cors@1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/has-cors/-/has-cors-1.1.0.tgz#5e474793f7ea9843d1bb99c23eef49ff126fff39"
integrity sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=

has-flag@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
Expand Down Expand Up @@ -9697,6 +9746,16 @@ parse5@6.0.1:
resolved "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b"
integrity sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==

parseqs@0.0.6:
version "0.0.6"
resolved "https://registry.yarnpkg.com/parseqs/-/parseqs-0.0.6.tgz#8e4bb5a19d1cdc844a08ac974d34e273afa670d5"
integrity sha512-jeAGzMDbfSHHA091hr0r31eYfTig+29g3GKKE/PPbEQ65X0lmMwlEoqmhzu0iztID5uJpZsFlUPDP8ThPL7M8w==

parseuri@0.0.6:
version "0.0.6"
resolved "https://registry.yarnpkg.com/parseuri/-/parseuri-0.0.6.tgz#e1496e829e3ac2ff47f39a4dd044b32823c4a25a"
integrity sha512-AUjen8sAkGgao7UyCX6Ahv0gIK2fABKmYjvP4xmy5JaKvcbTRueIqIPHLAfq30xJddqSE033IOMUSOMCcK3Sow==

parseurl@~1.3.2, parseurl@~1.3.3:
version "1.3.3"
resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4"
Expand Down Expand Up @@ -12282,6 +12341,26 @@ snarkdown@^1.2.2:
resolved "https://registry.yarnpkg.com/snarkdown/-/snarkdown-1.2.2.tgz#0cfe2f3012b804de120fc0c9f7791e869c59cc74"
integrity sha1-DP4vMBK4BN4SD8DJ93kehpxZzHQ=

socket.io-client@^4.3.2:
version "4.3.2"
resolved "https://registry.yarnpkg.com/socket.io-client/-/socket.io-client-4.3.2.tgz#9cfdb8fecac8a24d5723daf8c8749e70c8fdeb25"
integrity sha512-2B9LqSunN60yV8F7S84CCEEcgbYNfrn7ejIInZtLZ7ppWtiX8rGZAjvdCvbnC8bqo/9RlCNOUsORLyskxSFP1g==
dependencies:
"@socket.io/component-emitter" "~3.0.0"
backo2 "~1.0.2"
debug "~4.3.2"
engine.io-client "~6.0.1"
parseuri "0.0.6"
socket.io-parser "~4.1.1"

socket.io-parser@~4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-4.1.1.tgz#0ad53d980781cab1eabe320417d8480c0133e62d"
integrity sha512-USQVLSkDWE5nbcY760ExdKaJxCE65kcsG/8k5FDGZVVxpD1pA7hABYXYkCUvxUuYYh/+uQw0N/fvBzfT8o07KA==
dependencies:
"@socket.io/component-emitter" "~3.0.0"
debug "~4.3.1"

sockjs-client@^1.5.0:
version "1.5.1"
resolved "https://registry.npmjs.org/sockjs-client/-/sockjs-client-1.5.1.tgz#256908f6d5adfb94dabbdbd02c66362cca0f9ea6"
Expand Down Expand Up @@ -14101,6 +14180,11 @@ ws@^7.4.4:
resolved "https://registry.npmjs.org/ws/-/ws-7.4.4.tgz#383bc9742cb202292c9077ceab6f6047b17f2d59"
integrity sha512-Qm8k8ojNQIMx7S+Zp8u/uHOx7Qazv3Yv4q68MiWWWOJhiwG5W3x7iqmRtJo8xxrciZUY4vRxUTJCKuRnF28ZZw==

ws@~8.2.3:
version "8.2.3"
resolved "https://registry.yarnpkg.com/ws/-/ws-8.2.3.tgz#63a56456db1b04367d0b721a0b80cae6d8becbba"
integrity sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==

xml-name-validator@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a"
Expand All @@ -14111,6 +14195,11 @@ xmlchars@^2.2.0:
resolved "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb"
integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==

xmlhttprequest-ssl@~2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.0.0.tgz#91360c86b914e67f44dce769180027c0da618c67"
integrity sha512-QKxVRxiRACQcVuQEYFsI1hhkrMlrXHPegbbd1yn9UHOmRxY+si12nQYzri3vbzt8VdTTRviqcKxcyllFas5z2A==

xtend@^4.0.0, xtend@~4.0.1:
version "4.0.2"
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"
Expand Down Expand Up @@ -14221,6 +14310,11 @@ yargs@^7.0.0:
y18n "^3.2.1"
yargs-parser "^5.0.0"

yeast@0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/yeast/-/yeast-0.1.2.tgz#008e06d8094320c372dbc2f8ed76a0ca6c8ac419"
integrity sha1-AI4G2AlDIMNy28L47XagymyKxBk=

yocto-queue@^0.1.0:
version "0.1.0"
resolved "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"
Expand Down

0 comments on commit 5181340

Please sign in to comment.