Skip to content

Commit

Permalink
Merge branch 'feat/R51-live-status-gateway-on-R50' into release51
Browse files Browse the repository at this point in the history
# Conflicts:
#	packages/live-status-gateway/api/schemas/adLibs.yaml
#	packages/live-status-gateway/src/collections/pieceInstancesHandler.ts
#	packages/live-status-gateway/src/coreHandler.ts
  • Loading branch information
nytamin committed Jul 5, 2024
2 parents c5d04c6 + 8712e51 commit 7c90645
Show file tree
Hide file tree
Showing 10 changed files with 90 additions and 40 deletions.
29 changes: 29 additions & 0 deletions packages/corelib/src/__tests__/error.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { stringifyError } from '@sofie-automation/shared-lib/dist/lib/stringifyError'
import { UserError, UserErrorMessage } from '../error'

describe('UserError', () => {
test('stringifyError', () => {
const rawError = new Error('raw')
rawError.stack = 'mock stack'
const userError = UserError.from(rawError, UserErrorMessage.PartNotFound, { key: 'translatable message' })

expect(stringifyError(userError)).toEqual(
'UserError: ' +
JSON.stringify({
rawError: 'Error: raw, mock stack',
message: {
key: 'The selected part does not exist',
args: {
key: 'translatable message',
},
},
key: 25,
errorCode: 500,
})
)

// serialized and restored
const restored = JSON.parse(userError.toString())
expect(stringifyError(restored)).toEqual('raw, mock stack')
})
})
24 changes: 12 additions & 12 deletions packages/live-status-gateway/src/coreHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,7 @@ import {
PeripheralDeviceType,
} from '@sofie-automation/shared-lib/dist/peripheralDevice/peripheralDeviceAPI'
import { protectString } from '@sofie-automation/shared-lib/dist/lib/protectedString'
import {
PeripheralDeviceCommandId,
PeripheralDeviceId,
StudioId,
} from '@sofie-automation/shared-lib/dist/core/model/Ids'
import { PeripheralDeviceCommandId, StudioId } from '@sofie-automation/shared-lib/dist/core/model/Ids'
import { StatusCode } from '@sofie-automation/shared-lib/dist/lib/status'
import { PeripheralDeviceCommand } from '@sofie-automation/shared-lib/dist/core/model/PeripheralDeviceCommand'
import { LiveStatusGatewayConfig } from './generated/options'
Expand Down Expand Up @@ -152,8 +148,9 @@ export class CoreHandler {
}
// setup observers
const observer = this.core.observe(PeripheralDevicePubSubCollectionsNames.peripheralDeviceForDevice)
observer.added = (id) => this.onDeviceChanged(id)
observer.changed = (id) => this.onDeviceChanged(id)
observer.added = () => this.onDeviceChanged()
observer.changed = () => this.onDeviceChanged()
this.onDeviceChanged() // set initial settings
this.setupObserverForPeripheralDeviceCommands(this)
}
async destroy(): Promise<void> {
Expand Down Expand Up @@ -193,13 +190,16 @@ export class CoreHandler {
this._onConnected = fcn
}

onDeviceChanged(id: PeripheralDeviceId): void {
if (id !== this.core.deviceId) return
onDeviceChanged(): void {
const col = this.core.getCollection(PeripheralDevicePubSubCollectionsNames.peripheralDeviceForDevice)
if (!col) throw new Error('collection "peripheralDeviceForDevice" not found!')
const device = col.findOne(id)

this.deviceSettings = device?.deviceSettings || {}
const device = col.findOne(this.core.deviceId)
if (!device) {
throw new Error(`No "peripheralDeviceForDevice" with id "${this.core.deviceId}" found!`)
}

this.deviceSettings = device.deviceSettings || {}
const logLevel = this.deviceSettings['debugLogging'] ? 'debug' : 'info'
if (logLevel !== this.logger.level) {
this.logger.level = logLevel
Expand All @@ -211,7 +211,7 @@ export class CoreHandler {
this.logger.info('Loglevel: ' + this.logger.level)
}

const studioId = device?.studioId
const studioId = device.studioId
if (studioId === undefined) {
throw new Error(`Live status gateway must be attached to a studio`)
}
Expand Down
4 changes: 1 addition & 3 deletions packages/live-status-gateway/src/topics/activePiecesTopic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,7 @@ export class ActivePiecesTopic
activePieces: [],
})

for (const subscriber of subscribers) {
this.sendMessage(subscriber, message)
}
this.sendMessage(subscribers, message)
}

async update(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,9 +153,7 @@ export class ActivePlaylistTopic
publicData: undefined,
})

for (const subscriber of subscribers) {
this.sendMessage(subscriber, message)
}
this.sendMessage(subscribers, message)
}

private isDataInconsistent() {
Expand Down
4 changes: 1 addition & 3 deletions packages/live-status-gateway/src/topics/adLibsTopic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -236,9 +236,7 @@ export class AdLibsTopic
}
: { event: 'adLibs', rundownPlaylistId: null, adLibs: [], globalAdLibs: [] }

for (const subscriber of subscribers) {
this.sendMessage(subscriber, adLibsStatus)
}
this.sendMessage(subscribers, adLibsStatus)
}

async update(
Expand Down
2 changes: 1 addition & 1 deletion packages/live-status-gateway/src/topics/root.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ export class RootChannel extends WebSocketTopicBase implements WebSocketTopic {

constructor(logger: Logger) {
super('Root', logger)
this._heartbeat = setInterval(() => this._subscribers.forEach((ws) => this.sendHeartbeat(ws)), 2000)
this._heartbeat = setInterval(() => this.sendHeartbeat(this._subscribers), 2000)
}

close(): void {
Expand Down
4 changes: 1 addition & 3 deletions packages/live-status-gateway/src/topics/segmentsTopic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,7 @@ export class SegmentsTopic
}),
}

for (const subscriber of subscribers) {
this.sendMessage(subscriber, segmentsStatus)
}
this.sendMessage(subscribers, segmentsStatus)
}

async update(source: string, data: DBRundownPlaylist | DBSegment[] | DBPart[] | undefined): Promise<void> {
Expand Down
5 changes: 2 additions & 3 deletions packages/live-status-gateway/src/topics/studioTopic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,8 @@ export class StudioTopic
name: '',
playlists: [],
}
for (const subscriber of subscribers) {
this.sendMessage(subscriber, studioStatus)
}

this.sendMessage(subscribers, studioStatus)
}

async update(source: string, data: DBStudio | DBRundownPlaylist[] | undefined): Promise<void> {
Expand Down
29 changes: 22 additions & 7 deletions packages/live-status-gateway/src/wsHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,24 @@ export abstract class WebSocketTopicBase {
this._logger.error(`Process ${this._name} message not expected '${JSON.stringify(msg)}'`)
}

sendMessage(ws: WebSocket, msg: object): void {
const msgStr = JSON.stringify(msg)
this._logger.debug(`Send ${this._name} message '${msgStr}'`)
ws.send(msgStr)
sendMessage(recipients: WebSocket | Iterable<WebSocket>, msg: object): void {
recipients = isIterable(recipients) ? recipients : [recipients]

let count = 0
let msgStr = ''
for (const ws of recipients) {
if (!msgStr) msgStr = JSON.stringify(msg) // Optimization: only stringify if there are any recipients
count++
ws.send(msgStr)
}
this._logger.silly(`Send ${this._name} message '${msgStr}' to ${count} recipients`)
}

sendHeartbeat(ws: WebSocket): void {
sendHeartbeat(recipients: Set<WebSocket>): void {
const msgStr = JSON.stringify({ event: 'heartbeat' })
this._logger.silly(`Send ${this._name} message '${msgStr}'`)
ws.send(msgStr)
for (const ws of recipients.values()) {
ws.send(msgStr)
}
}

protected logUpdateReceived(collectionName: string, source: string, extraInfo?: string): void {
Expand Down Expand Up @@ -165,3 +173,10 @@ export interface CollectionObserver<T> {
observerName: string
update(source: string, data: T | undefined): Promise<void>
}
function isIterable<T>(obj: T | Iterable<T>): obj is Iterable<T> {
// checks for null and undefined
if (obj == null) {
return false
}
return typeof (obj as any)[Symbol.iterator] === 'function'
}
25 changes: 20 additions & 5 deletions packages/shared-lib/src/lib/stringifyError.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,13 @@ export function stringifyError(error: unknown, noStack = false): string {
// Has a custom toString() method
str = `${(error as any).toString()}`
} else {
str = ''
if ((error as Error).message) str += `${(error as Error).message} ` // Is an Error
if ((error as any).reason) str += `${(error as any).reason} ` // Is a Meteor.Error
if ((error as any).details) str += `${(error as any).details} `
const strings: (string | undefined)[] = [
stringify((error as any).rawError), // UserError
stringify((error as Error).message), // Error
stringify((error as any).reason), // Meteor.Error
stringify((error as any).details),
]
str = strings.filter(Boolean).join(', ')
}

if (!str) {
Expand All @@ -34,7 +37,7 @@ export function stringifyError(error: unknown, noStack = false): string {
}

if (!noStack) {
if (error && typeof error === 'object' && (error as any).stack) {
if (error && typeof error === 'object' && typeof (error as any).stack === 'string') {
str += ', ' + (error as any).stack
}
}
Expand All @@ -43,3 +46,15 @@ export function stringifyError(error: unknown, noStack = false): string {

return str
}

function stringify(v: any): string | undefined {
// Tries to stringify objects if they have a toString() that returns something sensible
if (v === undefined) return undefined
if (v === null) return 'null'

if (typeof v === 'object') {
const str = `${v}`
if (str !== '[object Object]') return str
return undefined
} else return `${v}`
}

0 comments on commit 7c90645

Please sign in to comment.