diff options
| author | Elizabeth Alexander Hunt <me@liz.coffee> | 2026-07-02 11:55:17 -0700 |
|---|---|---|
| committer | Elizabeth Alexander Hunt <me@liz.coffee> | 2026-07-02 11:55:17 -0700 |
| commit | 6bf4b90c90f15f4ab60833bddf5b5756d1a6b1f6 (patch) | |
| tree | ed97e39ec77c5231ffd2c394493e68d00ddac5a4 /Homework/cs5260/consumer/processor/ConsumerRequestProcessor.ts | |
| download | misc-undergrad-6bf4b90c90f15f4ab60833bddf5b5756d1a6b1f6.tar.gz misc-undergrad-6bf4b90c90f15f4ab60833bddf5b5756d1a6b1f6.zip | |
Diffstat (limited to 'Homework/cs5260/consumer/processor/ConsumerRequestProcessor.ts')
| -rw-r--r-- | Homework/cs5260/consumer/processor/ConsumerRequestProcessor.ts | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/Homework/cs5260/consumer/processor/ConsumerRequestProcessor.ts b/Homework/cs5260/consumer/processor/ConsumerRequestProcessor.ts new file mode 100644 index 0000000..87e66c1 --- /dev/null +++ b/Homework/cs5260/consumer/processor/ConsumerRequestProcessor.ts @@ -0,0 +1,133 @@ +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<string, string>(); + [ + ...(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<string, any> = { + 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); + } +} |
