summaryrefslogtreecommitdiff
path: root/Homework/cs5260/consumer/processor/ConsumerRequestProcessor.ts
blob: 87e66c1a05700626ac8239473a68362dc37c2f05 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
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);
  }
}