Skip to content

Commit 5b590dd

Browse files
committed
feat: add health endpoints to MOS- and Playout-Gateway
1 parent 69c0465 commit 5b590dd

File tree

10 files changed

+442
-35
lines changed

10 files changed

+442
-35
lines changed

packages/mos-gateway/src/connector.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,26 @@ import {
55
PeripheralDeviceId,
66
loadCertificatesFromDisk,
77
CertificatesConfig,
8+
stringifyError,
9+
HealthConfig,
10+
HealthEndpoints,
811
} from '@sofie-automation/server-core-integration'
912

1013
export interface Config {
1114
certificates: CertificatesConfig
1215
device: DeviceConfig
1316
core: CoreConfig
1417
mos: MosConfig
18+
health: HealthConfig
1519
}
1620
export interface DeviceConfig {
1721
deviceId: PeripheralDeviceId
1822
deviceToken: string
1923
}
2024
export class Connector {
25+
public initialized = false
26+
public initializedError: string | undefined = undefined
27+
2128
private mosHandler: MosHandler | undefined
2229
private coreHandler: CoreHandler | undefined
2330
private _config: Config | undefined
@@ -38,11 +45,18 @@ export class Connector {
3845
this._logger.info('Initializing Core...')
3946
await this.initCore(certificates)
4047

48+
if (!this.coreHandler) throw Error('coreHandler is undefined!')
49+
50+
new HealthEndpoints(this, this.coreHandler, config.health)
51+
4152
this._logger.info('Initializing Mos...')
4253
await this.initMos()
4354

4455
this._logger.info('Initialization done')
56+
this.initialized = true
4557
} catch (e: any) {
58+
this.initializedError = stringifyError(e)
59+
4660
this._logger.error('Error during initialization:', e, e.stack)
4761

4862
this._logger.info('Shutting down in 10 seconds!')

packages/mos-gateway/src/coreHandler.ts

Lines changed: 34 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,12 @@ export class CoreHandler {
3333
core: CoreConnection | undefined
3434
logger: Winston.Logger
3535
public _observers: Array<Observer<any>> = []
36+
public connectedToCore = false
3637
private _deviceOptions: DeviceConfig
3738
private _coreMosHandlers: Array<CoreMosDeviceHandler> = []
3839
private _onConnected?: () => any
3940
private _isInitialized = false
41+
private _isDestroyed = false
4042
private _executedFunctions = new Set<PeripheralDeviceCommandId>()
4143
private _coreConfig?: CoreConfig
4244
private _certificates?: Buffer[]
@@ -54,10 +56,12 @@ export class CoreHandler {
5456

5557
this.core.onConnected(() => {
5658
this.logger.info('Core Connected!')
59+
this.connectedToCore = true
5760
if (this._isInitialized) this.onConnectionRestored()
5861
})
5962
this.core.onDisconnected(() => {
6063
this.logger.info('Core Disconnected!')
64+
this.connectedToCore = false
6165
})
6266
this.core.onError((err) => {
6367
this.logger.error('Core Error: ' + (typeof err === 'string' ? err : err.message || err.toString()))
@@ -74,31 +78,45 @@ export class CoreHandler {
7478
}
7579
await this.core.init(ddpConfig)
7680

77-
if (!this.core) {
78-
throw Error('core is undefined!')
79-
}
80-
81-
this.core
82-
.setStatus({
83-
statusCode: StatusCode.GOOD,
84-
// messages: []
85-
})
86-
.catch((e) => this.logger.warn('Error when setting status:' + e))
87-
// nothing
88-
8981
await this.setupSubscriptionsAndObservers()
9082

9183
this._isInitialized = true
84+
85+
await this.updateCoreStatus()
86+
}
87+
getCoreStatus(): {
88+
statusCode: StatusCode
89+
messages: string[]
90+
} {
91+
let statusCode = StatusCode.GOOD
92+
const messages: string[] = []
93+
94+
if (!this._isInitialized) {
95+
statusCode = StatusCode.BAD
96+
messages.push('Starting up...')
97+
}
98+
if (this._isDestroyed) {
99+
statusCode = StatusCode.FATAL
100+
messages.push('Shut down')
101+
}
102+
return {
103+
statusCode,
104+
messages,
105+
}
92106
}
107+
async updateCoreStatus(): Promise<void> {
108+
if (!this.core) throw Error('core is undefined!')
109+
110+
await this.core.setStatus(this.getCoreStatus())
111+
}
112+
93113
async dispose(): Promise<void> {
114+
this._isDestroyed = true
94115
if (!this.core) {
95116
throw Error('core is undefined!')
96117
}
97118

98-
await this.core.setStatus({
99-
statusCode: StatusCode.FATAL,
100-
messages: ['Shutting down'],
101-
})
119+
await this.updateCoreStatus()
102120

103121
await Promise.all(
104122
this._coreMosHandlers.map(async (cmh: CoreMosDeviceHandler) => {

packages/mos-gateway/src/index.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ let deviceToken: string = process.env.DEVICE_TOKEN || ''
1414
let disableWatchdog: boolean = process.env.DISABLE_WATCHDOG === '1' || false
1515
let unsafeSSL: boolean = process.env.UNSAFE_SSL === '1' || false
1616
const certs: string[] = (process.env.CERTIFICATES || '').split(';') || []
17+
let healthPort: number | undefined = parseInt(process.env.HEALTH_PORT + '') || undefined
1718
let debug = false
1819
let printHelp = false
1920

@@ -46,6 +47,8 @@ process.argv.forEach((val) => {
4647
} else if (val.match(/-unsafeSSL/i)) {
4748
// Will cause the Node applocation to blindly accept all certificates. Not recommenced unless in local, controlled networks.
4849
unsafeSSL = true
50+
} else if (prevProcessArg.match(/-healthPort/i)) {
51+
healthPort = parseInt(val)
4952
}
5053
prevProcessArg = nextPrevProcessArg + ''
5154
})
@@ -207,6 +210,9 @@ const config: Config = {
207210
port: port,
208211
watchdog: !disableWatchdog,
209212
},
213+
health: {
214+
port: healthPort,
215+
},
210216
mos: {
211217
self: {
212218
debug: debug,

packages/playout-gateway/src/config.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ let influxUser: string | undefined = process.env.INFLUX_USER || 'sofie'
2020
let influxPassword: string | undefined = process.env.INFLUX_PASSWORD || undefined
2121
let influxDatabase: string | undefined = process.env.INFLUX_DB || 'sofie'
2222

23+
let healthPort: number | undefined = parseInt(process.env.HEALTH_PORT + '') || undefined
24+
2325
let prevProcessArg = ''
2426
process.argv.forEach((val) => {
2527
val = val + ''
@@ -50,14 +52,18 @@ process.argv.forEach((val) => {
5052
influxPassword = val
5153
} else if (prevProcessArg.match(/-influxDatabase/i)) {
5254
influxDatabase = val
55+
} else if (prevProcessArg.match(/-healthPort/i)) {
56+
healthPort = parseInt(val)
5357

5458
// arguments with no options:
5559
} else if (val.match(/-disableWatchdog/i)) {
5660
disableWatchdog = true
5761
} else if (val.match(/-disableAtemUpload/i)) {
5862
disableAtemUpload = true
5963
} else if (val.match(/-unsafeSSL/i)) {
60-
// Will cause the Node applocation to blindly accept all certificates. Not recommenced unless in local, controlled networks.
64+
// Will cause the Node application to blindly accept all certificates.
65+
// Not recommenced unless in local, controlled networks.
66+
// Instead use "-certificates cert1 cert2"
6167
unsafeSSL = true
6268
}
6369
prevProcessArg = nextPrevProcessArg + ''
@@ -85,6 +91,9 @@ const config: Config = {
8591
password: influxPassword,
8692
database: influxDatabase,
8793
},
94+
health: {
95+
port: healthPort,
96+
},
8897
}
8998

9099
export { config, logPath, logLevel, disableWatchdog, disableAtemUpload }

packages/playout-gateway/src/connector.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ import {
66
CertificatesConfig,
77
PeripheralDeviceId,
88
loadCertificatesFromDisk,
9+
stringifyError,
10+
HealthConfig,
11+
HealthEndpoints,
912
} from '@sofie-automation/server-core-integration'
1013

1114
export interface Config {
@@ -14,13 +17,17 @@ export interface Config {
1417
core: CoreConfig
1518
tsr: TSRConfig
1619
influx: InfluxConfig
20+
health: HealthConfig
1721
}
1822

1923
export interface DeviceConfig {
2024
deviceId: PeripheralDeviceId
2125
deviceToken: string
2226
}
2327
export class Connector {
28+
public initialized = false
29+
public initializedError: string | undefined = undefined
30+
2431
private tsrHandler: TSRHandler | undefined
2532
private coreHandler: CoreHandler | undefined
2633
private _logger: Logger
@@ -38,6 +45,8 @@ export class Connector {
3845

3946
this._logger.info('Initializing Core...')
4047
this.coreHandler = new CoreHandler(this._logger, config.device)
48+
new HealthEndpoints(this, this.coreHandler, config.health)
49+
4150
await this.coreHandler.init(config.core, this._certificates)
4251
this._logger.info('Core initialized')
4352

@@ -47,12 +56,15 @@ export class Connector {
4756
this._logger.info('TSR initialized')
4857

4958
this._logger.info('Initialization done')
59+
this.initialized = true
5060
return
5161
} catch (e: any) {
5262
this._logger.error('Error during initialization:')
5363
this._logger.error(e)
5464
this._logger.error(e.stack)
5565

66+
this.initializedError = stringifyError(e)
67+
5668
try {
5769
if (this.coreHandler) {
5870
this.coreHandler.destroy().catch(this._logger.error)

packages/playout-gateway/src/coreHandler.ts

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ export class CoreHandler {
5959
private _statusInitialized = false
6060
private _statusDestroyed = false
6161

62+
public connectedToCore = false
63+
6264
constructor(logger: Logger, deviceOptions: DeviceConfig) {
6365
this.logger = logger
6466
this._deviceOptions = deviceOptions
@@ -73,11 +75,13 @@ export class CoreHandler {
7375

7476
this.core.onConnected(() => {
7577
this.logger.info('Core Connected!')
78+
this.connectedToCore = true
7679

7780
if (this._onConnected) this._onConnected()
7881
})
7982
this.core.onDisconnected(() => {
8083
this.logger.warn('Core Disconnected!')
84+
this.connectedToCore = false
8185
})
8286
this.core.onError((err: any) => {
8387
this.logger.error('Core Error: ' + (typeof err === 'string' ? err : err.message || err.toString() || err))
@@ -375,9 +379,12 @@ export class CoreHandler {
375379

376380
return Object.fromEntries(this._tsrHandler.getDebugStates().entries())
377381
}
378-
async updateCoreStatus(): Promise<any> {
382+
getCoreStatus(): {
383+
statusCode: StatusCode
384+
messages: string[]
385+
} {
379386
let statusCode = StatusCode.GOOD
380-
const messages: Array<string> = []
387+
const messages: string[] = []
381388

382389
if (!this._statusInitialized) {
383390
statusCode = StatusCode.BAD
@@ -387,11 +394,13 @@ export class CoreHandler {
387394
statusCode = StatusCode.BAD
388395
messages.push('Shut down')
389396
}
390-
391-
return this.core.setStatus({
392-
statusCode: statusCode,
393-
messages: messages,
394-
})
397+
return {
398+
statusCode,
399+
messages,
400+
}
401+
}
402+
async updateCoreStatus(): Promise<any> {
403+
return this.core.setStatus(this.getCoreStatus())
395404
}
396405
}
397406

packages/server-core-integration/package.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,11 +69,17 @@
6969
"rundown",
7070
"production"
7171
],
72+
"devDependencies": {
73+
"@types/koa": "^3.0.0",
74+
"@types/koa__router": "^12.0.4"
75+
},
7276
"dependencies": {
77+
"@koa/router": "^14.0.0",
7378
"@sofie-automation/shared-lib": "1.53.0-in-development",
7479
"ejson": "^2.2.3",
7580
"faye-websocket": "^0.11.4",
7681
"got": "^11.8.6",
82+
"koa": "^3.0.1",
7783
"tslib": "^2.8.1",
7884
"underscore": "^1.13.7"
7985
},

packages/server-core-integration/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
export * from './lib/coreConnection.js'
22
export * from './lib/configManifest.js'
33
export * from './lib/ddpClient.js'
4+
export * from './lib/health.js'
45
export * from './lib/methods.js'
56
export * from './lib/process.js'
67
export { SubscriptionId } from './lib/subscriptions.js'

0 commit comments

Comments
 (0)