Skip to content

Commit a0c007a

Browse files
author
shopwareBot
committed
[create-pull-request] automated change
1 parent 83c0737 commit a0c007a

File tree

4 files changed

+347
-0
lines changed

4 files changed

+347
-0
lines changed

SUMMARY.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -452,6 +452,7 @@
452452
* [Tax providers](resources/references/adr/2022-04-28-tax-providers.md)
453453
* [Remove static analysis with psalm](resources/references/adr/2022-05-12-remove-static-analysis-with-psalm.md)
454454
* [Rule condition field abstraction](resources/references/adr/2022-05-23-rule-condition-field-abstraction.md)
455+
* [Integrate app into flow event](resources/references/adr/2022-06-17-integrate-app-into-flow-event.md)
455456
* [Add typescript support for storefront js](resources/references/adr/2022-06-24-add-typescript-support-for-storefront-js.md)
456457
* [Providing the admin extension sdk](resources/references/adr/2022-06-27-providing-the-admin-extension-sdk.md)
457458
* [Blog concept](resources/references/adr/2022-07-19-blog-concept.md)
@@ -479,6 +480,8 @@
479480
* [Mocking repositories](resources/references/adr/2023-04-01-mocking-repositories.md)
480481
* [Disable css autoprefixer](resources/references/adr/2023-04-03-disable-css-autoprefixer.md)
481482
* [Jest test files should be javascript only](resources/references/adr/2023-04-14-jest-test-files-should-be-javascript-only.md)
483+
* [Switch to uuidv7](resources/references/adr/2023-05-22-switch-to-uuidv7.md)
484+
* [Exception log levels](resources/references/adr/2023-05-25-exception-log-levels.md)
482485
* [YYYY MM DD template](resources/references/adr/YYYY-MM-DD-template.md)
483486

484487
* [App Reference](resources/references/app-reference/README.md)
Lines changed: 266 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,266 @@
1+
---
2+
title: Integrate an app into the flow event
3+
date: 2022-10-11
4+
area: business-ops
5+
tags: [flow, app]
6+
---
7+
8+
# Integrate an app into the flow event
9+
10+
{% hint style="info" %}
11+
This document represents an architecture decision record (ADR) and has been mirrored from the ADR section in our Shopware 6 repository.
12+
You can find the original version [here](https://github.com/shopware/platform/blob/trunk/adr/2022-06-17-integrate-app-into-flow-event.md)
13+
{% endhint %}
14+
15+
# 2022-10-11 - Integrate an app into the flow event
16+
17+
## Context
18+
Currently, apps can not extend the list of available events in the flow builder.
19+
20+
## Decision
21+
We update the flow builder so the apps can expand the list of available trigger events in the flow builder UI.
22+
23+
### Flow aware
24+
We define flow aware classes to detect which data will be available in the event and a function to get them.
25+
26+
**Problems:**
27+
* We are unsure which data will the app event provide
28+
29+
**Solution:**
30+
* We create an interface CustomAppAware that will use as implementation for the custom event from the app.
31+
32+
**Example pseudocode**
33+
```php
34+
interface CustomAppAware
35+
{
36+
public const APP_DATA = 'customAppData';
37+
38+
public function getCustomAppData(): array;
39+
}
40+
```
41+
42+
### Flow storer
43+
Flow data storer saves the data from the event as the [StorableFlow](../../adr/admin/flow-builder/2022-07-21-adding-the-StorableFlow-to-implement-DelayAction-in-Flow-Builder.md), and we use them in flow actions.
44+
45+
**Problems:**
46+
* Currently, we keep the event data in the core but do not store any personalized event data from the application.
47+
48+
**Solution:**
49+
* We create a CustomAppStorer, which is used to store the data from custom app event.
50+
* When the API triggers a custom trigger, the data in the body will be stored in FlowStore by their keys.
51+
52+
*Example to define data from the API:*
53+
```json
54+
{
55+
"customerId": "d20e4d60e35e4afdb795c767eee08fec",
56+
"salesChannelId": "55cb094fd1794d489c63975a6b4b5b90",
57+
"shopName": "Shopware's Shop",
58+
"url": "https://shopware.com"
59+
}
60+
```
61+
62+
*After that, at actions we can get data thought FlowStorer.*
63+
```php
64+
$salesChanelId = $flow->getData(MailAware::SALES_CHANNEL_ID));
65+
$customer = $flow->getData(CustomerAware::CUSTOMER_ID));
66+
```
67+
68+
*Or we can use the data when defining the email template.*
69+
```html
70+
<h3>Welcome to {{ shopName }}</h3>
71+
<h1>Visit us at: {{ url }} </h1>
72+
```
73+
74+
**Example pseudocode**
75+
```php
76+
class CustomAppStore extends FlowStorer
77+
{
78+
public function store(FlowEventAware $event, array $stored): array
79+
{
80+
//check if $event is an instance of CustomAppAware
81+
foreach ($event->getCustomAppData() as $key => $data) {
82+
$stored[ScalarValuesAware::STORE_VALUES][$key] = $data;
83+
$stored[$key] = $data;
84+
}
85+
}
86+
87+
public function restore(StorableFlow $storable): void
88+
{
89+
return;
90+
}
91+
}
92+
```
93+
94+
### Flow Events
95+
Events must implement FlowEventAware to be able to available in the flow builder triggers.
96+
97+
**Problems:**
98+
* We do not possess any `FlowEventAware` event instances that app developers can utilize for custom triggers to be dispatched or triggered from an app.
99+
100+
**Solution:**
101+
* We create a new CustomAppEvent class that can be triggered by the App system.
102+
103+
**Example pseudocode**
104+
```php
105+
class CustomAppEvent extends Event implements CustomAppAware, FlowEventAware
106+
{
107+
private string $name;
108+
109+
private array $data;
110+
111+
// __construct()
112+
//getters
113+
}
114+
```
115+
116+
### BusinessEventCollector
117+
BusinessEventCollector collects events that implemented FlowEventAware and output to flow builder.
118+
119+
**Problems:**
120+
* We currently collect events that implemented FlowEventAware. So the collector does not contain the events from the activated app.
121+
122+
**Solution:**
123+
* We will collect all `CustomAppEvent` events from activated apps.
124+
125+
**Example pseudocode**
126+
```php
127+
public function collect(Context $context): BusinessEventCollectorResponse
128+
{
129+
//fetch app event
130+
$this->fetchAppEvents(new BusinessEventCollectorResponse)
131+
}
132+
133+
private function fetchAppEvents(BusinessEventCollectorResponse $result): BusinessEventCollectorResponse
134+
{
135+
//check valid app events from the database
136+
return $this->createCustomAppEvent();
137+
}
138+
139+
private function createCustomAppEvent(): CustomAppEvent
140+
{
141+
// return new CustomAppEvent
142+
}
143+
```
144+
145+
### Trigger app custom events API
146+
We will provide an APIs to trigger CustomAppEvent.
147+
148+
**Problems:**
149+
* Currently, the events are provided and triggered from the core when the user performs specific actions from the storefront or admin, like checkout order or user recovery. 3rd parties can not add custom triggers and trigger them by themself.
150+
151+
**Solution:**
152+
* We will provide an API. The app calls the API to trigger the custom event and needs to provide the event name and the data. The API will create a CustomAppEvent object and dispatch it with the information provided.
153+
154+
**Example pseudocode**
155+
```php
156+
/**
157+
* @Since("6.5.2.0")
158+
*/
159+
#[Route(path: '/api/_action/trigger-event/{eventName}', name: 'api.action.trigger_event', methods: ['POST'])]
160+
public function flowCustomTrigger(string $eventName, Request $request, Context $context): JsonResponse
161+
{
162+
$data = $request->request->all();
163+
164+
$criteria = new Criteria([$data['flowAppEventId']])
165+
$criteria->addFilter(new EqualsFilter('appId', $data['flowId']));
166+
$criteria->addFilter(new EqualsFilter('app.active', 1));
167+
168+
$flowEvent = $flowAppEventRepository->search($criteria);
169+
//return http status code 404 if $flowEvent is empty
170+
171+
$this->eventDispatcher->dispatch(new CustomAppEvent($flowEvent->getName(), $data));
172+
//return http status code 200 and success message
173+
}
174+
175+
```
176+
177+
## Defining an App flow event in Xml
178+
The flow events are configured in a `<appRoot>/src/Resources/flow.xml` file. We can store the following information for a flow event, Also, we can define more than one event in one app:
179+
180+
1. `<name>` - The technical name - is unique and should be prefixed with the app vendor prefix, used when dispatching CustomAppEvent.php.
181+
2. `<aware>` - Use for deciding what flow actions will be allowed to show after the event.
182+
183+
- The list of aware supported following:
184+
- `orderAware`
185+
- `customerAware`
186+
- `mailAware`
187+
- `userAware`
188+
- `salesChannelAware`
189+
- `productAware`
190+
- `customerGroupAware`
191+
192+
- _Example:_
193+
194+
_`<aware>orderAware</aware>`_
195+
196+
_We will have a list of actions related to Order that can be selected at the flow below:_
197+
198+
- action.add.order.tag,
199+
- action.remove.order.tag,
200+
- action.generate.document,
201+
- action.grant.download.access,
202+
- action.set.order.state,
203+
- action.add.order.affiliate.and.campaign.code,
204+
- action.set.order.custom.field,
205+
- action.stop.flow
206+
207+
_`<aware>customerAware</aware>`_
208+
209+
_We will have a list of actions related to Customer that can be selected at the flow below:_
210+
211+
- action.add.customer.tag
212+
- action.remove.customer.tag
213+
- action.change.customer.group
214+
- action.change.customer.status
215+
- action.set.customer.custom.field
216+
- action.add.customer.affiliate.and.campaign.code
217+
- action.stop.flow
218+
219+
A complete XML structure looks like this:
220+
```xml
221+
<flow-extensions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://test-flow.com/flow-1.0.xsd">
222+
<flow-events>
223+
<flow-event>
224+
<name>swag.before.open.the.doors</name>
225+
<aware>customerAware</aware>
226+
<aware>orderAware</aware>
227+
</flow-event>
228+
<flow-event>
229+
...
230+
</flow-event>
231+
</flow-events>
232+
</flow-extensions>
233+
```
234+
235+
## Defining translated
236+
We support defining translation for custom trigger events to show in the trigger tree and the trigger's name in the flow list.
237+
238+
* We will create the snippet file in folder `<appRoot>/src/Resources/app/administration/snippet/`. The structure of the snippet should follow some principles below:
239+
* `sw-flow-custom-event` is a fixed key instance for snippets using at the trigger event.
240+
* `event-tree` is a fixed key. The keys are defined inside this key based on the specified trigger name at `name` in `flow.xml` used to translate in trigger tree.
241+
* `flow-list` is a fixed key, The keys defined inside the key based on the trigger name defined at `name` in `flow.xml` used to translate in the trigger tree.
242+
**Example pseudocode**
243+
```json
244+
{
245+
"sw-flow-custom-event": {
246+
"event-tree": {
247+
"swag": "Swag",
248+
"before": "Before",
249+
"openTheDoors": "Open the doors"
250+
},
251+
"flow-list": {
252+
"swag_before_open_the_doors": "Before open the doors"
253+
}
254+
}
255+
}
256+
```
257+
258+
## Database migration
259+
* We will create a new table `app_flow_event` to save defined data from the `<appRoot>/src/Resources/flow.xml` file.
260+
* The table will have columns like bellow:
261+
* `id` BINARY(16) NOT NULL,
262+
* `app_id` BINARY(16) NOT NULL,
263+
* `name` VARCHAR(255) NOT NULL UNIQUE,
264+
* `aware` JSON NOT NULL,
265+
* `created_at` DATETIME(3) NOT NULL,
266+
* `updated_at` DATETIME(3) NULL,
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
---
2+
title: Switch to UUIDv7
3+
date: 2023-05-22
4+
area: core
5+
tags: [DAL]
6+
---
7+
8+
# Switch to UUIDv7
9+
10+
{% hint style="info" %}
11+
This document represents an architecture decision record (ADR) and has been mirrored from the ADR section in our Shopware 6 repository.
12+
You can find the original version [here](https://github.com/shopware/platform/blob/trunk/adr/2023-05-22-switch-to-uuidv7.md)
13+
{% endhint %}
14+
15+
## Context
16+
17+
Using UUIDs as primary keys eases the integration of several different datasources,
18+
but it also brings some performance issues.
19+
20+
Currently, we're using UUIDv4, which is a random UUID the completely random prefix means
21+
that the B-tree indexes of the database are not very efficient.
22+
23+
UUIDv7 time based prefix is less spread than that of UUIDv4, this helps the database to keep the index more compact.
24+
It allows the Index to allocate fewer new pages and to keep the index smaller.
25+
26+
## Decision
27+
28+
Considering there is little risk to using UUIDv7, as v4 and v7 share the same
29+
length and are indistinguishable for shopware, we can switch to v7 without any risk
30+
of breaking anything.
31+
32+
The effort is also very low as we only need to change the
33+
implementation of the `Uuid` class. As using UUIDv7 will improve the speed of
34+
bulk product inserts by about 8 %, we think the effort is worth the measurable and
35+
theoretical gain.
36+
37+
## Consequences
38+
39+
We will switch to UUIDv7 as default and add performance guides promoting v7.
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
---
2+
title: Exception Log Level configuration
3+
date: 2023-05-25
4+
area: core
5+
tags: [core, devops, observability]
6+
---
7+
8+
# Exception Log Level configuration
9+
10+
{% hint style="info" %}
11+
This document represents an architecture decision record (ADR) and has been mirrored from the ADR section in our Shopware 6 repository.
12+
You can find the original version [here](https://github.com/shopware/platform/blob/trunk/adr/2023-05-25-exception-log-levels.md)
13+
{% endhint %}
14+
15+
## Context
16+
By default every exception that is thrown in the PHP stack and not catched will be logged by the `symfony/monolog-bridge` on `error` level.
17+
But there are some cases where the exception is caused by clients accessing the API wrong (missing fields etc.) and throwing an `ShopwareHttpException` with a HTTP-Status-Code of 40x is our way of handling such situations and returning a correct HTTP-Status-Code to the client.
18+
So those cases are in fact no "errors" that need to be analyzed, but are expected given a malformed API request.
19+
Logging those cases as "errors" produces a lot of noice, which makes it harder to actually find errors in the logs.
20+
21+
For our cloud product we already used a configuration list that configures that some Exception classes should only be logged as notices.
22+
23+
## Decision
24+
25+
We add configuration to the platform that degrades the error level of specific exceptions to notices. This way external hosters can also profit from our classification.
26+
We use [symfony's `exceptions` configuration](https://symfony.com/doc/current/reference/configuration/framework.html#exceptions) for this.
27+
28+
This has the benefit that for specific projects this configuration could be adjusted, for example for cases where you also controll all clients that access the shop, you may want to log also every client error, just to help debugging the client.
29+
30+
Another solution could be to do the configuration of the log level directly in the exception class either by attributes or a separate method specifying the log level, but that would make overwriting it for a specific project harder, so we stick to the default symfony configuration.
31+
32+
## Consequences
33+
34+
We will add the `exceptions` configuration to the platform, that way the error logging in existing projects might change. But in general we assume that this change is for the better.
35+
36+
Additionally we will need to extend on the default symfony configuration as that is not compatible with our new [domain exceptions](./2022-02-24-domain-exceptions.md) as there are multiple exception cases in one file/class.
37+
Therefore we will add a similiar configuration option, that does not rely on the FQCN, but instead we will use the shopware specific `error code` from the shopware exception as that is unique to the exception case.
38+
39+
On a side note we should be able to get rid of most the cloud specific configuration for the exception logging mapping.

0 commit comments

Comments
 (0)