summaryrefslogtreecommitdiff
path: root/Homework/cs5260/consumer/processor
diff options
context:
space:
mode:
authorElizabeth Alexander Hunt <me@liz.coffee>2026-07-02 11:55:17 -0700
committerElizabeth Alexander Hunt <me@liz.coffee>2026-07-02 11:55:17 -0700
commit6bf4b90c90f15f4ab60833bddf5b5756d1a6b1f6 (patch)
treeed97e39ec77c5231ffd2c394493e68d00ddac5a4 /Homework/cs5260/consumer/processor
downloadmisc-undergrad-main.tar.gz
misc-undergrad-main.zip
Diffstat (limited to 'Homework/cs5260/consumer/processor')
-rw-r--r--Homework/cs5260/consumer/processor/ConsumerRequestProcessor.ts133
-rw-r--r--Homework/cs5260/consumer/processor/WidgetRequestProcessor.ts5
-rw-r--r--Homework/cs5260/consumer/processor/index.ts2
3 files changed, 140 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);
+ }
+}
diff --git a/Homework/cs5260/consumer/processor/WidgetRequestProcessor.ts b/Homework/cs5260/consumer/processor/WidgetRequestProcessor.ts
new file mode 100644
index 0000000..fbb96ac
--- /dev/null
+++ b/Homework/cs5260/consumer/processor/WidgetRequestProcessor.ts
@@ -0,0 +1,5 @@
+import { WidgetRequestT } from "@/shared/schema";
+
+export interface WidgetRequestProcessor {
+ processRequest(widgetRequest: WidgetRequestT): Promise<void>;
+}
diff --git a/Homework/cs5260/consumer/processor/index.ts b/Homework/cs5260/consumer/processor/index.ts
new file mode 100644
index 0000000..983da1b
--- /dev/null
+++ b/Homework/cs5260/consumer/processor/index.ts
@@ -0,0 +1,2 @@
+export * from "./ConsumerRequestProcessor";
+export * from "./WidgetRequestProcessor";