import { WidgetDAO } from "@/consumer/dao"; import { TracingLogger } from "@/consumer/log"; import { Widget, WidgetT, WidgetRequestT } from "@/shared/schema"; export class ConsumerRequestProcessor implements WidgetRequestProcessor { private widgetDao: WidgetDAO; private logger: TracingLogger; constructor(widgetDao: WidgetDAO, logger: TracingLogger) { this.widgetDao = widgetDao; this.logger = logger; } public async processRequest(widgetRequest: WidgetRequestT) { this.logger.info( `processing RequestId=(${widgetRequest.requestId}) with WidgetRequestType=(${widgetRequest.type})` ); switch (widgetRequest.type) { case "create": await this.createWidget(widgetRequest); break; case "delete": await this.deleteWidget(widgetRequest); break; case "update": await this.updateWidget(widgetRequest); break; default: this.logger.warn( `received WidgetRequestType=(${widgetRequest.type})... don't know what to do!` ); break; } } private async createWidget(widgetRequest: WidgetRequestT) { this.logger.info(`creating new Widget=(${widgetRequest.widgetId})`); const widget = this.widgetFromWidgetRequest(widgetRequest); const currentWidget = await this.widgetDao.retrieve(widget); if (!currentWidget) { await this.widgetDao.save(widget); } else { this.logger.warn( `received creation request for Widget=(${widget.id}) but it already exists... skipping` ); } } private async deleteWidget(widgetRequest: WidgetRequestT) { this.logger.info(`deleting Widget=(${widgetRequest.widgetId})`); const widget = this.widgetFromWidgetRequest(widgetRequest); const currentWidget = await this.widgetDao.retrieve(widget); if (currentWidget) { await this.widgetDao.delete(widget); } else { this.logger.warn( `received deletion request for Widget=(${widget.id}) but it did not exist... skipping` ); } } private async updateWidget(widgetRequest: WidgetRequestT) { this.logger.info(`updating Widget=(${widgetRequest.widgetId})`); const widget = this.widgetFromWidgetRequest(widgetRequest); const currentWidget = await this.widgetDao.retrieve(widget); if (!currentWidget) { this.logger.warn( `attempted to retrieve Widget=(${widgetRequest.widgetId}) to update, but it doesn't exist! skipping...` ); return; } const immutableKeys = ["id", "owner"] as unknown as (keyof WidgetT)[]; for (const key of Object.keys(widget) as unknown as (keyof WidgetT)[]) { const isImmutable = immutableKeys.includes(key); if (!isImmutable && widget[key] === "") { delete widget[key]; delete currentWidget[key]; } else if (isImmutable && widget[key] !== currentWidget[key]) { this.logger.warn( `cannot change ${key} on Widget=(${widget.id}). skipping...` ); return; } } const otherAttributeMap = new Map(); [ ...(currentWidget.otherAttributes ?? []), ...(widget.otherAttributes ?? []), ].forEach(({ name, value }) => { if (value != null) otherAttributeMap.set(name, value); if (value == "") otherAttributeMap.delete(name); }); const otherAttributes = Array.from(otherAttributeMap.entries()).map( ([name, value]) => { return { name, value }; } ); const newWidget: WidgetT = { ...currentWidget, ...widget, }; if (otherAttributes.length) { newWidget.otherAttributes = otherAttributes; } await this.widgetDao.save(newWidget); } private widgetFromWidgetRequest(widgetRequest: WidgetRequestT): WidgetT { const widget: Record = { id: widgetRequest.widgetId, owner: widgetRequest.owner, }; if (widgetRequest.label !== undefined) widget.label = widgetRequest.label; if (widgetRequest.description !== undefined) widget.description = widgetRequest.description; if (widgetRequest.otherAttributes?.length) widget.otherAttributes = widgetRequest.otherAttributes; return Widget.parse(widget); } }