@tvkitchen/countertop
Version:
The entry point for developers who want to set up a TV Kitchen.
147 lines (129 loc) • 4.26 kB
JavaScript
import { v4 as uuid } from 'uuid'
import { countertopStates } from '../constants'
import { consoleLogger } from '../tools/loggers'
import CountertopWorker from './CountertopWorker'
class CountertopStation {
logger = null
kafka = null
id = null
Appliance = null
applianceSettings = null
workers = []
state = ''
/**
* Create a CountertopStation
*
* @param {Class} Appliance The IAppliance class that this station will manage.
* @param {Object} applianceSettings Settings for the appliance.
* @param {Logger} options.logger A logger with methods for all TV Kitchen logLevels.
*/
constructor(
Appliance,
applianceSettings = {},
{
logger = consoleLogger,
kafka,
} = {},
) {
if (Appliance === undefined) {
throw new Error('CountertopStation requires an Appliance.')
}
this.Appliance = Appliance
this.applianceSettings = applianceSettings
this.logger = logger
this.kafka = kafka
this.id = `${Appliance.name}::${uuid()}`
this.setState(countertopStates.STOPPED)
}
/**
* Replace the station's workers in order to fit a specified topology.
*
* @param {CountertopToplogy} topology The topology to use.
* @return {CountertopWorker[]} The new set of workers.
*/
invokeTopology = (topology) => {
this.logger.trace(`CountertopStation<${this.id}>: invokeTopology()`)
if (this.getState() !== countertopStates.STOPPED) {
throw new Error('CountertopStations must be stopped before invoking a topology.')
}
const stationStreams = topology.streams.filter((stream) => stream.getMouth() === this)
this.workers = stationStreams.map((stream) => new CountertopWorker(
this.Appliance,
this.applianceSettings,
{
stream,
logger: this.logger,
kafka: this.kafka,
},
))
return this.workers
}
/**
* Start the station and begin data processing.
*
* @return {Boolean} Whether the station successfully started.
*/
start = async () => {
this.logger.trace(`CountertopStation<${this.id}>: start()`)
this.state = countertopStates.STARTING
const promises = this.workers.map(async (worker) => worker.start())
const started = (await Promise.all(promises)).every((result) => result)
this.setState(started ? countertopStates.STARTED : countertopStates.ERRORED)
return this.getState() === countertopStates.STARTED
}
/**
* Stop the countertop and halt all data processing.
*
* @return {Boolean} Whether the station successfully stopped.
*/
stop = async () => {
this.logger.trace(`CountertopStation<${this.id}>: stop()`)
this.setState(countertopStates.STOPPING)
const promises = this.workers.map(async (worker) => worker.stop())
const stopped = (await Promise.all(promises)).every((result) => result)
this.setState(stopped ? countertopStates.STOPPED : countertopStates.ERRORED)
return this.getState() === countertopStates.STOPPED
}
/**
* Get the data types that this station processes.
*
* This is determined by the Appliance that the station hosts.
*
* @return {String[]} The data types that this station processes.
*/
getInputTypes = () => this.Appliance.getInputTypes(this.applianceSettings)
/**
* Get the data types that this station produces.
*
* This is determined by the Appliance that the station hosts.
*
* @return {String[]} The data types that this station produces.
*/
getOutputTypes = () => this.Appliance.getOutputTypes(this.applianceSettings)
/**
* Get the current state of the CountertopStation.
*
* @return {String} The state of the CountertopStation.
*/
getState = () => this.state
/**
* Set the current state of the CountertopStation.
*
* This is an internal method.
*/
setState = (state) => { this.state = state }
/**
* Registers a listener to the CountertopStation for a given event type.
*
* Event types are defined in @tvkitchen/base-constants
*
* @param {String} eventType The type of event being listened to.
* @param {Function} listener The listener to be registered for that event.
* @return {CountertopStation} The CountertopStation instance (to enable chaining).
*/
on = (eventType, listener) => {
this.workers.forEach((worker) => worker.on(eventType, listener))
return this
}
}
export default CountertopStation