chore: initial commit

This commit is contained in:
2024-04-16 22:27:52 +01:00
commit 531b5dabe2
194 changed files with 27071 additions and 0 deletions

120
docs/EVENTS.md Normal file
View File

@@ -0,0 +1,120 @@
# Stocklet Docs: Events
## Table of Contents
* [Repository Overview](/README.md)
* [Documentation: Overview](/docs/README.md)
* [Documentation: Events](/docs/EVENTS.md)
* [Documentation: Feature Roadmap](/docs/ROADMAP.md)
## Overview
The events are schemed and serialised using [protocol buffers](https://protobuf.dev/). The events schemas can be found in [``/schema/protobufs/stocklet/events/``](/schema/protobufs/stocklet/events/)
They are dispatched using the [transactional outbox pattern](https://microservices.io/patterns/data/transactional-outbox.html). Debezium is used as a relay to publish events from database outbox tables to the message broker (Kafka). The Debezium connectors are configured by the ``service-init`` containers, which are also responsible for performing database migrations for their respective services.
## Services
### Auth Service
**Produces:**
* n/a
**Consumes:**
* UserDeletedEvent
### Order Service
**Produces:**
* OrderCreatedEvent
* OrderPendingEvent
* OrderRejectedEvent
* OrderApprovedEvent
**Consumes:**
* ProductPriceQuoteEvent
* StockReservationEvent
* ShipmentAllocationEvent
* PaymentProcessedEvent
### Payment Service
**Produces:**
* BalanceCreatedEvent
* BalanceCreditedEvent
* BalanceDebitedEvent
* BalanceClosedEvent
* TransactionLoggedEvent
* TransactionReversedEvent *(currently unused)*
* PaymentProcessedEvent
**Consumes:**
* UserCreatedEvent
* UserDeletedEvent
* ShipmentAllocationEvent
### Product Service
**Produces:**
* ProductCreatedEvent
* ProductPriceUpdatedEvent
* ProductDeletedEvent
* ProductPriceQuoteEvent
**Consumes:**
* OrderCreatedEvent
### Shipping Service
**Produces:**
* ShipmentAllocationEvent
* ShipmentDispatchedEvent *(currently unused)*
**Consumes:**
* StockReservationEvent
* PaymentProcessedEvent
### User Service
**Produces:**
* UserCreatedEvent
* UserEmailUpdatedEvent
* UserDeletedEvent
**Consumes:**
* n/a
### Warehouse Service
**Produces:**
* StockCreatedEvent
* StockAddedEvent *(currently unused)*
* StockRemovedEvent
* StockReservationEvent
**Consumes:**
* OrderPendingEvent
* ShipmentAllocationEvent
* PaymentProcessedEvent
## Miscellaneous
### Place Order Saga
The place order [saga](https://microservices.io/patterns/data/saga.html) is initiated when a new order is created.
![Place Order Saga](/docs/imgs/placeordersaga.svg)

18
docs/README.md Normal file
View File

@@ -0,0 +1,18 @@
# Stocklet Docs
## Table of Contents
* [Repository Overview](/README.md)
* [Documentation: Overview](/docs/README.md)
* [Documentation: Events](/docs/EVENTS.md)
* [Documentation: Feature Roadmap](/docs/ROADMAP.md)
## Formatting, styling, etc
The code has been formatted using [`gofmt`](https://pkg.go.dev/cmd/gofmt).
The protobuf schema files have been formatted using [`buf format`](https://buf.build/docs/reference/cli/buf/format).
The markdown files have been linted and formatted using [markdownlint](https://github.com/DavidAnson/markdownlint).
I used [PlantUML](https://plantuml.com/) as the tool to help make the diagrams. The PlantUML files are avaliable alongside the resulting images: [`/docs/imgs/overview.plantuml`](/docs/imgs/overview.plantuml) and [`/docs/imgs/placeordersaga.plantuml`](/docs/imgs/placeordersaga.plantuml)

35
docs/ROADMAP.md Normal file
View File

@@ -0,0 +1,35 @@
# Stocklet Docs: Feature Roadmap
## Table of Contents
* [Repository Overview](/README.md)
* [Documentation: Overview](/docs/README.md)
* [Documentation: Events](/docs/EVENTS.md)
* [Documentation: Feature Roadmap](/docs/ROADMAP.md)
## Prologue
This document should be considered a brainstorm of ideas.
There is no guarantee that I will implement any listed features or functionality below. After all, I initially made this application as an experiment with EDA, and there are areas that could use improvement and expansion (the application is a prototype in current format). Some of the current implemented functionality is quite bare-bones, so if I come to revisit this project at a later date this document is where I'd first look.
However, contributions are welcome; if you feel like implementing something (already below or not), or otherwise spot other areas that could use improvement, then please feel free to open an issue to discuss or a pull request with your implementation.
## Feature Ideas
* Front-end user interface
* Allow interfaces with the application through alternatives means
* Notification service
* Send notifications to users (e.g. through a mock email or a unread messages mechanism) upon reciept of events related to order status changes (i.e. OrderApprovedEvent)
* Product recommendation service
* Provide a list of recommended products catered to specific customers
## Miscellaneous Ideas
* Integration tests
* Ensured idempotency in event consumers (service-side)
* Clear-up of event processes
* Kubernetes deployment (prepare manifest files)
* Interchangable infrastructure
* Support for NATS as a message broker
* Support for MongoDB as a database

125
docs/imgs/overview.plantuml Normal file
View File

@@ -0,0 +1,125 @@
' Copyright (C) 2024 Declan Teevan
'
' This program is free software: you can redistribute it and/or modify
' it under the terms of the GNU Affero General Public License as published by
' the Free Software Foundation, either version 3 of the License, or
' (at your option) any later version.
'
' This program is distributed in the hope that it will be useful,
' but WITHOUT ANY WARRANTY; without even the implied warranty of
' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
' GNU Affero General Public License for more details.
'
' You should have received a copy of the GNU Affero General Public License
' along with this program. If not, see <https://www.gnu.org/licenses/>.
@startuml overview
!theme mars
cloud "API Gateway (Envoy)" as APIGateway
queue "Message Broker (Kafka)" as MsgBroker
collections "Message Relay (Debezium)" as OutboxConnector
database "Auth Database" as AuthDB
database "Order Database" as OrderDB
database "Payment Database" as PaymentDB
database "Product Database" as ProductDB
database "Shipping Database" as ShippingDB
database "User Database" as UserDB
database "Warehouse Database" as WarehouseDB
rectangle "Auth Service" as AuthService {
agent "gRPC Gateway" as AuthGateway
agent "Event Consumer" as AuthConsumer
usecase "gRPC Service" as AuthGrpc
AuthGrpc <-u- AuthGateway
AuthGrpc <-u- AuthConsumer
AuthGrpc --> AuthDB
}
rectangle "Order Service" as OrderService {
agent "gRPC Gateway" as OrderGateway
agent "Event Consumer" as OrderConsumer
usecase "gRPC Service" as OrderGrpc
OrderGrpc <-u- OrderGateway
OrderGrpc <-u- OrderConsumer
OrderGrpc --> OrderDB
}
rectangle "Payment Service" as PaymentService {
agent "gRPC Gateway" as PaymentGateway
agent "Event Consumer" as PaymentConsumer
usecase "gRPC Service" as PaymentGrpc
PaymentGrpc <-u- PaymentGateway
PaymentGrpc <-u- PaymentConsumer
PaymentGrpc --> PaymentDB
}
rectangle "Product Service" as ProductService {
agent "gRPC Gateway" as ProductGateway
agent "Event Consumer" as ProductConsumer
usecase "gRPC Service" as ProductGrpc
ProductGrpc <-u- ProductGateway
ProductGrpc <-u- ProductConsumer
ProductGrpc --> ProductDB
}
rectangle "Shipping Service" as ShippingService {
agent "gRPC Gateway" as ShippingGateway
agent "Event Consumer" as ShippingConsumer
usecase "gRPC Service" as ShippingGrpc
ShippingGrpc <-u- ShippingGateway
ShippingGrpc <-u- ShippingConsumer
ShippingGrpc --> ShippingDB
}
rectangle "User Service" as UserService {
agent "gRPC Gateway" as UserGateway
usecase "gRPC Service" as UserGrpc
UserGrpc <-u- UserGateway
UserGrpc --> UserDB
}
rectangle "Warehouse Service" as WarehouseService {
agent "gRPC Gateway" as WarehouseGateway
agent "Event Consumer" as WarehouseConsumer
usecase "gRPC Service" as WarehouseGrpc
WarehouseGrpc <-u- WarehouseGateway
WarehouseGrpc <-u- WarehouseConsumer
WarehouseGrpc --> WarehouseDB
}
APIGateway ....> AuthGateway : "HTTP"
APIGateway ....> OrderGateway : "HTTP"
APIGateway ....> PaymentGateway : "HTTP"
APIGateway ....> ProductGateway : "HTTP"
APIGateway ....> ShippingGateway : "HTTP"
APIGateway ....> UserGateway : "HTTP"
APIGateway ....> WarehouseGateway : "HTTP"
UserGrpc .l.> AuthGrpc : "gRPC "
AuthDB ---[hidden]> OutboxConnector
OrderDB ---> OutboxConnector : "Outbox"
PaymentDB ---> OutboxConnector : "Outbox"
ProductDB ---> OutboxConnector : "Outbox"
ShippingDB ---> OutboxConnector : "Outbox"
UserDB ---> OutboxConnector : "Outbox"
WarehouseDB ---> OutboxConnector : "Outbox"
OutboxConnector ..> MsgBroker : "Publish Events"
MsgBroker ...> AuthConsumer
MsgBroker ...> OrderConsumer
MsgBroker ...> PaymentConsumer
MsgBroker ...> ProductConsumer
MsgBroker ...> ShippingConsumer
MsgBroker ...> WarehouseConsumer
@enduml

235
docs/imgs/overview.svg Normal file
View File

@@ -0,0 +1,235 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg style="width:2273px;height:799px;background:#F9F9F9;" contentStyleType="text/css" preserveAspectRatio="none" version="1.1" viewBox="0 0 2273 799" width="2273px" height="799px" xmlns="http://www.w3.org/2000/svg" zoomAndPan="magnify">
<rect x="355" y="240.33" width="324" height="180.98" rx="3.5" ry="3.5" fill="none" stroke="#393939"/>
<text x="466.5" y="255.3255" fill="#aa0000" font-family="sans-serif" font-size="14" font-weight="bold" textLength="101">Auth Service</text>
<rect x="899" y="240.33" width="324" height="180.98" rx="3.5" ry="3.5" fill="none" stroke="#393939"/>
<text x="1006" y="255.3255" fill="#aa0000" font-family="sans-serif" font-size="14" font-weight="bold" textLength="110">Order Service</text>
<rect x="7" y="240.33" width="324" height="180.98" rx="3.5" ry="3.5" fill="none" stroke="#393939"/>
<text x="103" y="255.3255" fill="#aa0000" font-family="sans-serif" font-size="14" font-weight="bold" textLength="132">Payment Service</text>
<rect x="1595" y="240.33" width="324" height="180.98" rx="3.5" ry="3.5" fill="none" stroke="#393939"/>
<text x="1694" y="255.3255" fill="#aa0000" font-family="sans-serif" font-size="14" font-weight="bold" textLength="126">Product Service</text>
<rect x="1247" y="240.33" width="324" height="180.98" rx="3.5" ry="3.5" fill="none" stroke="#393939"/>
<text x="1343" y="255.3255" fill="#aa0000" font-family="sans-serif" font-size="14" font-weight="bold" textLength="132">Shipping Service</text>
<rect x="703" y="240.33" width="172" height="180.98" rx="3.5" ry="3.5" fill="none" stroke="#393939"/>
<text x="738.5" y="255.3255" fill="#aa0000" font-family="sans-serif" font-size="14" font-weight="bold" textLength="101">User Service</text>
<rect x="1943" y="240.33" width="324" height="180.98" rx="3.5" ry="3.5" fill="none" stroke="#393939"/>
<text x="2028" y="255.3255" fill="#aa0000" font-family="sans-serif" font-size="14" font-weight="bold" textLength="154">Warehouse Service</text>
<rect x="541.5" y="275.33" width="121" height="36.297" rx="3.5" ry="3.5" fill="#313139" stroke="#E7E7E7" stroke-width=".5"/>
<text x="551.5" y="298.3255" fill="#FFFFFF" font-family="sans-serif" font-size="14" textLength="101">gRPC Gateway</text>
<rect x="371.5" y="275.33" width="135" height="36.297" rx="3.5" ry="3.5" fill="#313139" stroke="#E7E7E7" stroke-width=".5"/>
<text x="381.5" y="298.3255" fill="#FFFFFF" font-family="sans-serif" font-size="14" textLength="115">Event Consumer</text>
<ellipse cx="548" cy="388.97" rx="69.695" ry="16.339" fill="#313139" stroke="#E7E7E7" stroke-width=".5"/>
<text x="498.9952" y="392.7169" fill="#FFFFFF" font-family="sans-serif" font-size="14" textLength="92">gRPC Service</text>
<rect x="1085.5" y="275.33" width="121" height="36.297" rx="3.5" ry="3.5" fill="#313139" stroke="#E7E7E7" stroke-width=".5"/>
<text x="1095.5" y="298.3255" fill="#FFFFFF" font-family="sans-serif" font-size="14" textLength="101">gRPC Gateway</text>
<rect x="915.5" y="275.33" width="135" height="36.297" rx="3.5" ry="3.5" fill="#313139" stroke="#E7E7E7" stroke-width=".5"/>
<text x="925.5" y="298.3255" fill="#FFFFFF" font-family="sans-serif" font-size="14" textLength="115">Event Consumer</text>
<ellipse cx="1084" cy="388.97" rx="69.695" ry="16.339" fill="#313139" stroke="#E7E7E7" stroke-width=".5"/>
<text x="1034.9952" y="392.7169" fill="#FFFFFF" font-family="sans-serif" font-size="14" textLength="92">gRPC Service</text>
<rect x="193.5" y="275.33" width="121" height="36.297" rx="3.5" ry="3.5" fill="#313139" stroke="#E7E7E7" stroke-width=".5"/>
<text x="203.5" y="298.3255" fill="#FFFFFF" font-family="sans-serif" font-size="14" textLength="101">gRPC Gateway</text>
<rect x="23.5" y="275.33" width="135" height="36.297" rx="3.5" ry="3.5" fill="#313139" stroke="#E7E7E7" stroke-width=".5"/>
<text x="33.5" y="298.3255" fill="#FFFFFF" font-family="sans-serif" font-size="14" textLength="115">Event Consumer</text>
<ellipse cx="245" cy="388.97" rx="69.695" ry="16.339" fill="#313139" stroke="#E7E7E7" stroke-width=".5"/>
<text x="195.9952" y="392.7169" fill="#FFFFFF" font-family="sans-serif" font-size="14" textLength="92">gRPC Service</text>
<rect x="1611.5" y="275.33" width="121" height="36.297" rx="3.5" ry="3.5" fill="#313139" stroke="#E7E7E7" stroke-width=".5"/>
<text x="1621.5" y="298.3255" fill="#FFFFFF" font-family="sans-serif" font-size="14" textLength="101">gRPC Gateway</text>
<rect x="1767.5" y="275.33" width="135" height="36.297" rx="3.5" ry="3.5" fill="#313139" stroke="#E7E7E7" stroke-width=".5"/>
<text x="1777.5" y="298.3255" fill="#FFFFFF" font-family="sans-serif" font-size="14" textLength="115">Event Consumer</text>
<ellipse cx="1684" cy="388.97" rx="69.695" ry="16.339" fill="#313139" stroke="#E7E7E7" stroke-width=".5"/>
<text x="1634.9952" y="392.7169" fill="#FFFFFF" font-family="sans-serif" font-size="14" textLength="92">gRPC Service</text>
<rect x="1263.5" y="275.33" width="121" height="36.297" rx="3.5" ry="3.5" fill="#313139" stroke="#E7E7E7" stroke-width=".5"/>
<text x="1273.5" y="298.3255" fill="#FFFFFF" font-family="sans-serif" font-size="14" textLength="101">gRPC Gateway</text>
<rect x="1419.5" y="275.33" width="135" height="36.297" rx="3.5" ry="3.5" fill="#313139" stroke="#E7E7E7" stroke-width=".5"/>
<text x="1429.5" y="298.3255" fill="#FFFFFF" font-family="sans-serif" font-size="14" textLength="115">Event Consumer</text>
<ellipse cx="1333" cy="388.97" rx="69.695" ry="16.339" fill="#313139" stroke="#E7E7E7" stroke-width=".5"/>
<text x="1283.9952" y="392.7169" fill="#FFFFFF" font-family="sans-serif" font-size="14" textLength="92">gRPC Service</text>
<rect x="733.5" y="275.33" width="121" height="36.297" rx="3.5" ry="3.5" fill="#313139" stroke="#E7E7E7" stroke-width=".5"/>
<text x="743.5" y="298.3255" fill="#FFFFFF" font-family="sans-serif" font-size="14" textLength="101">gRPC Gateway</text>
<ellipse cx="789" cy="388.97" rx="69.695" ry="16.339" fill="#313139" stroke="#E7E7E7" stroke-width=".5"/>
<text x="739.9952" y="392.7169" fill="#FFFFFF" font-family="sans-serif" font-size="14" textLength="92">gRPC Service</text>
<rect x="1959.5" y="275.33" width="121" height="36.297" rx="3.5" ry="3.5" fill="#313139" stroke="#E7E7E7" stroke-width=".5"/>
<text x="1969.5" y="298.3255" fill="#FFFFFF" font-family="sans-serif" font-size="14" textLength="101">gRPC Gateway</text>
<rect x="2115.5" y="275.33" width="135" height="36.297" rx="3.5" ry="3.5" fill="#313139" stroke="#E7E7E7" stroke-width=".5"/>
<text x="2125.5" y="298.3255" fill="#FFFFFF" font-family="sans-serif" font-size="14" textLength="115">Event Consumer</text>
<ellipse cx="2029" cy="388.97" rx="69.695" ry="16.339" fill="#313139" stroke="#E7E7E7" stroke-width=".5"/>
<text x="1979.9952" y="392.7169" fill="#FFFFFF" font-family="sans-serif" font-size="14" textLength="92">gRPC Service</text>
<path d="m1070 15.172c5.4911-6.4527 10.042-5.2213 14.147 1.4901 2.7313-5.4791 7.0687-5.7562 11.295-1.7871 3.576-5.5135 9.4015-6.3142 12.857 0.1297 2.6823-7.4612 9.5927-8.132 14.188-1.9965 3.8339-5.0856 8.5963-6.5214 12.24 0.1971 3.0805-6.9608 9.13-5.7752 12.622-0.4224 3.6635-6.7824 9.7619-5.3161 13.163 0.2793 4.9362-5.2013 9.0352-5.1569 13.045 1.0585 3.0979-5.8676 8.3856-6.6034 12.147-0.6841 3.7356-5.9711 9.003-3.9224 11.553 1.2315 3.9632-6.1481 10.525-7.7457 14.63-0.1506 5.4721-4.6659 9.3889-3.7267 12.679 2.5322 9.9117 0.8413 10.886 6.7954 6.8826 14.323 4.5218 7.4814 1.516 15.979-8.3014 16.038-4.3159 6.2151-8.7435 6.3016-13.012-0.0493-3.4762 5.7854-7.6474 7.2374-12.601 1.6346-2.6926 6.8991-8.3328 6.5007-12.641 1.7541-2.9934 5.9135-8.361 6.5345-12.089 0.7594-3.6337 7.4321-7.797 8.2751-13.21 1.6749-4.2643 6.3206-9.4279 6.7135-13.142-0.5331-3.5472 5.4016-8.6662 5.0352-12.113-0.1153-4.2878 5.5717-9.3755 3.5168-12.014-1.8172-3.7949 6.6718-9.5568 5.9823-12.732-0.5957-3.7371 6.1477-9.2733 5.3515-12.709-0.3236-5.1111 6.4543-9.9946 5.1088-13.264-1.8249-4.7758 6.2175-11.49 4.2948-13.852-2.5578-7.6724-2.0457-8.6329-7.251-4.694-13.372-5.5616-7.9984-3.6489-13 4.9242-16.873" fill="#313139" stroke="#E7E7E7" stroke-width=".5"/>
<text x="1076.5" y="35.0355" fill="#FFFFFF" font-family="sans-serif" font-size="14" textLength="139">API Gateway (Envoy)</text>
<path d="m1032 765.9h174c5 0 5 13.148 5 13.148s0 13.148-5 13.148h-174c-5 0-5-13.148-5-13.148s0-13.148 5-13.148" fill="#E55756" stroke="#191919" stroke-width="1.5"/>
<path d="m1206 765.9c-5 0-5 13.148-5 13.148 0 13.148 5 13.148 5 13.148" fill="none" stroke="#191919" stroke-width="1.5"/>
<text x="1032" y="783.8955" fill="#FFFFFF" font-family="sans-serif" font-size="14" textLength="164">Message Broker (Kafka)</text>
<rect x="1018.5" y="656.61" width="205" height="32.297" rx="3.5" ry="3.5" fill="#E55756" stroke="#191919" stroke-width="1.5"/>
<rect x="1014.5" y="652.61" width="205" height="32.297" rx="3.5" ry="3.5" fill="#E55756" stroke="#191919" stroke-width="1.5"/>
<text x="1022.5" y="673.6055" fill="#ffffff" font-family="sans-serif" font-size="14" textLength="189">Message Relay (Debezium)</text>
<path d="m629 478.31c0-10 61-10 61-10s61 0 61 10v25.297c0 10-61 10-61 10s-61 0-61-10v-25.297" fill="#A4DBD8" stroke="#191919" stroke-width=".5"/>
<path d="m629 478.31c0 10 61 10 61 10s61 0 61-10" fill="none" stroke="#191919" stroke-width=".5"/>
<text x="639" y="505.3055" fill="#191919" font-family="sans-serif" font-size="14" textLength="102">Auth Database</text>
<path d="m1014.5 478.31c0-10 64.5-10 64.5-10s64.5 0 64.5 10v25.297c0 10-64.5 10-64.5 10s-64.5 0-64.5-10v-25.297" fill="#A4DBD8" stroke="#191919" stroke-width=".5"/>
<path d="m1014.5 478.31c0 10 64.5 10 64.5 10s64.5 0 64.5-10" fill="none" stroke="#191919" stroke-width=".5"/>
<text x="1024.5" y="505.3055" fill="#191919" font-family="sans-serif" font-size="14" textLength="109">Order Database</text>
<path d="m440 478.31c0-10 77-10 77-10s77 0 77 10v25.297c0 10-77 10-77 10s-77 0-77-10v-25.297" fill="#A4DBD8" stroke="#191919" stroke-width=".5"/>
<path d="m440 478.31c0 10 77 10 77 10s77 0 77-10" fill="none" stroke="#191919" stroke-width=".5"/>
<text x="450" y="505.3055" fill="#191919" font-family="sans-serif" font-size="14" textLength="134">Payment Database</text>
<path d="m1364 478.31c0-10 72-10 72-10s72 0 72 10v25.297c0 10-72 10-72 10s-72 0-72-10v-25.297" fill="#A4DBD8" stroke="#191919" stroke-width=".5"/>
<path d="m1364 478.31c0 10 72 10 72 10s72 0 72-10" fill="none" stroke="#191919" stroke-width=".5"/>
<text x="1374" y="505.3055" fill="#191919" font-family="sans-serif" font-size="14" textLength="124">Product Database</text>
<path d="m1179 478.31c0-10 75-10 75-10s75 0 75 10v25.297c0 10-75 10-75 10s-75 0-75-10v-25.297" fill="#A4DBD8" stroke="#191919" stroke-width=".5"/>
<path d="m1179 478.31c0 10 75 10 75 10s75 0 75-10" fill="none" stroke="#191919" stroke-width=".5"/>
<text x="1189" y="505.3055" fill="#191919" font-family="sans-serif" font-size="14" textLength="130">Shipping Database</text>
<path d="m786 478.31c0-10 61-10 61-10s61 0 61 10v25.297c0 10-61 10-61 10s-61 0-61-10v-25.297" fill="#A4DBD8" stroke="#191919" stroke-width=".5"/>
<path d="m786 478.31c0 10 61 10 61 10s61 0 61-10" fill="none" stroke="#191919" stroke-width=".5"/>
<text x="796" y="505.3055" fill="#191919" font-family="sans-serif" font-size="14" textLength="102">User Database</text>
<path d="m1905.5 478.31c0-10 84.5-10 84.5-10s84.5 0 84.5 10v25.297c0 10-84.5 10-84.5 10s-84.5 0-84.5-10v-25.297" fill="#A4DBD8" stroke="#191919" stroke-width=".5"/>
<path d="m1905.5 478.31c0 10 84.5 10 84.5 10s84.5 0 84.5-10" fill="none" stroke="#191919" stroke-width=".5"/>
<text x="1915.5" y="505.3055" fill="#191919" font-family="sans-serif" font-size="14" textLength="149">Warehouse Database</text>
<g stroke="#191919">
<path d="m591.84 312.07c-10.02 17.35-22.187 38.426-31.807 55.066" fill="none"/>
<polygon points="557.03 372.33 565 366.54 559.53 368 558.07 362.54" fill="#191919"/>
</g>
<g stroke="#191919">
<path d="m459.5 312.07c20.48 17.56 47.055 40.354 66.415 56.954" fill="none"/>
<polygon points="530.47 372.93 526.24 364.04 526.67 369.68 521.03 370.11" fill="#191919"/>
</g>
<g stroke="#191919">
<path d="m569.26 404.94c23.67 16.67 57.274 40.325 84.424 59.445" fill="none"/>
<polygon points="658.59 467.84 653.53 459.39 654.5 464.96 648.93 465.93" fill="#191919"/>
</g>
<g stroke="#191919">
<path d="m1134.3 312.07c-11.51 17.35-25.613 38.62-36.653 55.26" fill="none"/>
<polygon points="1094.4 372.33 1102.7 367.04 1097.1 368.16 1096 362.62" fill="#191919"/>
</g>
<g stroke="#191919">
<path d="m1002 312.07c18.85 17.45 43.066 39.865 61.026 56.485" fill="none"/>
<polygon points="1067.4 372.63 1063.5 363.58 1063.8 369.23 1058.1 369.45" fill="#191919"/>
</g>
<g stroke="#191919">
<path d="m1083.2 405.59c-0.84 16.81-1.8786 37.668-2.8286 56.558" fill="none"/>
<polygon points="1080.1 468.14 1084.5 459.35 1080.3 463.15 1076.5 458.95" fill="#191919"/>
</g>
<g stroke="#191919">
<path d="m252.31 312.07c-1.67 17.35-3.6257 37.648-5.2257 54.288" fill="none"/>
<polygon points="246.51 372.33 251.35 363.75 246.99 367.35 243.39 362.99" fill="#191919"/>
</g>
<g stroke="#191919">
<path d="m119.97 312.07c29.1 17.66 68.311 41.466 95.621 58.046" fill="none"/>
<polygon points="220.72 373.23 215.1 365.14 216.45 370.64 210.95 371.98" fill="#191919"/>
</g>
<g stroke="#191919">
<path d="m281.4 403.35c44.88 16.5 116.15 42.7 169.85 62.44" fill="none"/>
<polygon points="456.88 467.86 449.81 461 452.19 466.14 447.05 468.51" fill="#191919"/>
</g>
<g stroke="#191919">
<path d="m1674.3 312.07c2.22 17.35 4.8382 37.669 6.9682 54.309" fill="none"/>
<polygon points="1682 372.33 1684.8 362.9 1681.4 367.37 1676.9 363.91" fill="#191919"/>
</g>
<g stroke="#191919">
<path d="m1806.6 312.07c-28.54 17.66-66.908 41.422-93.698 58.002" fill="none"/>
<polygon points="1707.8 373.23 1717.6 371.9 1712.1 370.6 1713.3 365.09" fill="#191919"/>
</g>
<g stroke="#191919">
<path d="m1650 403.66c-40.99 16.53-104.91 42.296-153.55 61.906" fill="none"/>
<polygon points="1490.9 467.81 1500.8 468.15 1495.6 465.94 1497.8 460.74" fill="#191919"/>
</g>
<g stroke="#191919">
<path d="m1325.7 312.07c1.67 17.35 3.6257 37.648 5.2257 54.288" fill="none"/>
<polygon points="1331.5 372.33 1334.6 362.99 1331 367.35 1326.6 363.75" fill="#191919"/>
</g>
<g stroke="#191919">
<path d="m1458 312.07c-29.1 17.66-68.311 41.466-95.621 58.046" fill="none"/>
<polygon points="1357.3 373.23 1367 371.98 1361.6 370.64 1362.9 365.14" fill="#191919"/>
</g>
<g stroke="#191919">
<path d="m1321 405.16c-13.21 16.71-30.841 39.032-45.881 58.072" fill="none"/>
<polygon points="1271.4 467.94 1280.1 463.36 1274.5 464.02 1273.8 458.4" fill="#191919"/>
</g>
<g stroke="#191919">
<path d="m793.06 312.07c-0.93 17.35-2.0095 37.629-2.8995 54.269" fill="none"/>
<polygon points="789.84 372.33 794.32 363.56 790.11 367.34 786.33 363.13" fill="#191919"/>
</g>
<g stroke="#191919">
<path d="m798.06 405.59c9.75 16.81 22.321 38.469 33.271 57.359" fill="none"/>
<polygon points="834.34 468.14 833.29 458.35 831.83 463.81 826.37 462.36" fill="#191919"/>
</g>
<g stroke="#191919">
<path d="m2021.7 312.07c1.67 17.35 3.6257 37.648 5.2257 54.288" fill="none"/>
<polygon points="2027.5 372.33 2030.6 362.99 2027 367.35 2022.6 363.75" fill="#191919"/>
</g>
<g stroke="#191919">
<path d="m2154 312.07c-29.1 17.66-68.311 41.466-95.621 58.046" fill="none"/>
<polygon points="2053.3 373.23 2063 371.98 2057.6 370.64 2058.9 365.14" fill="#191919"/>
</g>
<g stroke="#191919">
<path d="m2022.9 405.59c-6.56 16.81-14.849 38.07-22.219 56.96" fill="none"/>
<polygon points="1998.5 468.14 2005.5 461.21 2000.3 463.48 1998.1 458.3" fill="#191919"/>
</g>
<path d="m1091.2 53.75c-84.62 35.35-251.59 107.17-388.2 178.58-25.5 13.34-48.457 27.059-68.517 39.549" fill="none" stroke="#191919" stroke-dasharray="7.0,7.0"/>
<polygon points="629.39 275.05 639.14 273.69 633.63 272.41 634.92 266.9" fill="#191919" stroke="#191919"/>
<text x="881" y="158.3972" fill="#d40000" font-family="sans-serif" font-size="13" textLength="32">HTTP</text>
<path d="m1146 53.46v215.39" fill="none" stroke="#191919" stroke-dasharray="7.0,7.0"/>
<polygon points="1146 274.85 1150 265.85 1146 269.85 1142 265.85" fill="#191919" stroke="#191919"/>
<text x="1147" y="158.3972" fill="#d40000" font-family="sans-serif" font-size="13" textLength="32">HTTP</text>
<path d="m1061.2 44.48c-147.63 24.93-459.62 85.62-706.19 187.85-27.52 11.42-51.519 26.034-71.349 39.354" fill="none" stroke="#191919" stroke-dasharray="7.0,7.0"/>
<polygon points="278.67 275.03 288.37 273.33 282.82 272.24 283.91 266.69" fill="#191919" stroke="#191919"/>
<text x="608" y="158.3972" fill="#d40000" font-family="sans-serif" font-size="13" textLength="32">HTTP</text>
<path d="m1197.8 53.79c80.83 35.69 241.35 108.29 373.19 178.54 25.22 13.44 47.957 27.014 68.007 39.414" fill="none" stroke="#191919" stroke-dasharray="7.0,7.0"/>
<polygon points="1644.1 274.9 1638.6 266.76 1639.9 272.27 1634.4 273.57" fill="#191919" stroke="#191919"/>
<text x="1433" y="158.3972" fill="#d40000" font-family="sans-serif" font-size="13" textLength="32">HTTP</text>
<path d="m1161.2 53.46c34.72 50.97 115.99 170.28 147.43 216.43" fill="none" stroke="#191919" stroke-dasharray="7.0,7.0"/>
<polygon points="1312 274.85 1310.2 265.16 1309.2 270.72 1303.6 269.66" fill="#191919" stroke="#191919"/>
<text x="1236" y="158.3972" fill="#d40000" font-family="sans-serif" font-size="13" textLength="32">HTTP</text>
<path d="m1115.7 53.69c-68.87 51.13-231.12 171.57-293.15 217.62" fill="none" stroke="#191919" stroke-dasharray="7.0,7.0"/>
<polygon points="817.71 274.89 827.32 272.74 821.72 271.91 822.55 266.31" fill="#191919" stroke="#191919"/>
<text x="991" y="158.3972" fill="#d40000" font-family="sans-serif" font-size="13" textLength="32">HTTP</text>
<path d="m1230.9 45.15c145.06 25.63 448.21 86.93 688.11 187.18 27.49 11.49 51.497 26.098 71.327 39.398" fill="none" stroke="#191919" stroke-dasharray="7.0,7.0"/>
<polygon points="1995.3 275.07 1990.1 266.74 1991.2 272.29 1985.6 273.38" fill="#191919" stroke="#191919"/>
<text x="1723" y="158.3972" fill="#d40000" font-family="sans-serif" font-size="13" textLength="32">HTTP</text>
<path d="m624.03 388.97h95.18" fill="none" stroke="#191919" stroke-dasharray="7.0,7.0"/>
<polygon points="618.03 388.97 627.03 392.97 623.03 388.97 627.03 384.97" fill="#191919" stroke="#191919"/>
<text x="636" y="382.0372" fill="#d40000" font-family="sans-serif" font-size="13" textLength="33">gRPC</text>
<path d="m1083.9 513.76c8.04 35.7 22.512 100.07 29.862 132.7" fill="none" stroke="#191919"/>
<polygon points="1115.1 652.31 1117 642.65 1114 647.43 1109.2 644.41" fill="#191919" stroke="#191919"/>
<text x="1102" y="587.6772" fill="#d40000" font-family="sans-serif" font-size="13" textLength="46">Outbox</text>
<path d="m584.8 514.07c64.03 20.69 162.86 52.14 249.2 77.54 74.32 21.86 154.32 43.577 212.2 58.977" fill="none" stroke="#191919"/>
<polygon points="1052 652.13 1044.3 645.95 1047.2 650.84 1042.3 653.68" fill="#191919" stroke="#191919"/>
<text x="835" y="587.6772" fill="#d40000" font-family="sans-serif" font-size="13" textLength="46">Outbox</text>
<path d="m1396.8 513.94c-63.77 35.77-183.49 102.92-241.55 135.48" fill="none" stroke="#191919"/>
<polygon points="1150 652.35 1159.8 651.44 1154.4 649.9 1155.9 644.46" fill="#191919" stroke="#191919"/>
<text x="1289" y="587.6772" fill="#d40000" font-family="sans-serif" font-size="13" textLength="46">Outbox</text>
<path d="m1237.4 513.76c-27.11 35.7-76.79 101.14-101.58 133.77" fill="none" stroke="#191919"/>
<polygon points="1132.2 652.31 1140.9 647.56 1135.3 648.33 1134.5 642.72" fill="#191919" stroke="#191919"/>
<text x="1191" y="587.6772" fill="#d40000" font-family="sans-serif" font-size="13" textLength="46">Outbox</text>
<path d="m880.63 513.94c54.72 35.77 156.91 102.57 206.73 135.13" fill="none" stroke="#191919"/>
<polygon points="1092.4 652.35 1087 644.08 1088.2 649.62 1082.7 650.78" fill="#191919" stroke="#191919"/>
<text x="999" y="587.6772" fill="#d40000" font-family="sans-serif" font-size="13" textLength="46">Outbox</text>
<path d="m1937.1 514.06c-26.65 10.46-59.69 22.41-90.1 30.55-218.03 58.35-474.41 94.886-617.08 112.48" fill="none" stroke="#191919"/>
<polygon points="1224 657.82 1233.4 660.69 1228.9 657.21 1232.4 652.75" fill="#191919" stroke="#191919"/>
<text x="1717" y="587.6772" fill="#d40000" font-family="sans-serif" font-size="13" textLength="46">Outbox</text>
<path d="m1119 689.31v70.16" fill="none" stroke="#191919" stroke-dasharray="7.0,7.0"/>
<polygon points="1119 765.47 1123 756.47 1119 760.47 1115 756.47" fill="#191919" stroke="#191919"/>
<text x="1120" y="731.9672" fill="#d40000" font-family="sans-serif" font-size="13" textLength="92">Publish Events</text>
<g stroke="#191919">
<path d="m1026.7 774.11c-196.78-9.64-639.66-38.43-639.66-102.36v-283.78c0-29.53 16.147-53.891 31.347-71.561" fill="none" stroke-dasharray="7.0,7.0"/>
<polygon points="422.26 311.86 413.36 316.07 419 315.65 419.42 321.29" fill="#191919"/>
</g>
<g stroke="#191919">
<path d="m1065.1 765.54c-45.77-14.2-104.07-42.38-104.07-93.79v-283.78c0-27.01 6.8378-51.603 13.308-70.193" fill="none" stroke-dasharray="7.0,7.0"/>
<polygon points="976.28 312.11 969.54 319.3 974.64 316.83 977.1 321.93" fill="#191919"/>
</g>
<g stroke="#191919">
<path d="m1026.5 777.94c-249.82-1.53-919.51-14.21-919.51-106.19v-283.78c0-26.84-5.0216-51.582-9.7316-70.242" fill="none" stroke-dasharray="7.0,7.0"/>
<polygon points="95.8 311.91 94.124 321.62 97.024 316.76 101.88 319.66" fill="#191919"/>
</g>
<g stroke="#191919">
<path d="m1211.5 773.51c190.62-10.6 609.5-40.82 609.5-101.76v-283.78c0-26.75 4.3884-51.481 8.5084-70.171" fill="none" stroke-dasharray="7.0,7.0"/>
<polygon points="1830.8 311.94 1825 319.87 1829.7 316.82 1832.8 321.59" fill="#191919"/>
</g>
<g stroke="#191919">
<path d="m1211.4 774.37c129.57-7.72 349.61-31.34 349.61-102.62v-283.78c0-31.88-22.059-55.527-43.399-72.267" fill="none" stroke-dasharray="7.0,7.0"/>
<polygon points="1512.9 312 1517.5 320.7 1516.8 315.09 1522.4 314.41" fill="#191919"/>
</g>
<g stroke="#191919">
<path d="m1211.3 778.21c254.53-0.79 947.71-11.62 947.71-106.46v-283.78c0-27.15 7.4748-51.763 14.535-70.303" fill="none" stroke-dasharray="7.0,7.0"/>
<polygon points="2175.7 312.06 2168.7 319.05 2173.9 316.73 2176.2 321.89" fill="#191919"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 22 KiB

View File

@@ -0,0 +1,81 @@
' Copyright (C) 2024 Declan Teevan
'
' This program is free software: you can redistribute it and/or modify
' it under the terms of the GNU Affero General Public License as published by
' the Free Software Foundation, either version 3 of the License, or
' (at your option) any later version.
'
' This program is distributed in the hope that it will be useful,
' but WITHOUT ANY WARRANTY; without even the implied warranty of
' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
' GNU Affero General Public License for more details.
'
' You should have received a copy of the GNU Affero General Public License
' along with this program. If not, see <https://www.gnu.org/licenses/>.
@startuml placeordersaga
!theme mars
|Order|
start
:OrderCreatedEvent;
|Product|
:ProductPriceQuoteEvent;
if (type) is (<color:red>UNAVALIABLE) then
|Order|
:<color:red>OrderRejectedEvent;
kill
else (<color:green>AVALIABLE)
endif
|Order|
:OrderPendingEvent;
|Warehouse|
:StockReservationEvent;
if (type) is (<color:red>INSUFFICIENT_STOCK) then
|Order|
:<color:red>OrderRejectedEvent;
kill
else (<color:green>STOCK_RESERVED)
endif
|Shipping|
:ShipmentAllocationEvent;
if (type) is (<color:red>FAILED) then
|Warehouse|
:StockReservationEvent\n<color:grey>type: STOCK_RETURNED;
|Order|
:<color:red>OrderRejectedEvent;
kill
else (<color:green>ALLOCATED)
endif
|Payment|
:PaymentProcessedEvent;
if (type) is (<color:red>FAILED) then
|Shipping|
:ShipmentAllocationEvent\n<color:grey>type: ALLOCATION_RELEASED;
|Warehouse|
:StockReservationEvent\n<color:grey>type: STOCK_RETURNED;
|Order|
:<color:red>OrderRejectedEvent;
kill
else (<color:green>SUCCESS)
endif
fork
|Warehouse|
:StockReservationEvent\n<color:grey>type: STOCK_CONSUMED;
kill
fork again
|Order|
:<color:green>OrderApprovedEvent;
stop
end merge
@enduml

View File

@@ -0,0 +1,142 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg style="width:1250px;height:1276px;background:#F9F9F9;" contentStyleType="text/css" preserveAspectRatio="none" version="1.1" viewBox="0 0 1250 1276" width="1250px" height="1276px" xmlns="http://www.w3.org/2000/svg" zoomAndPan="magnify">
<rect width="1250" height="1276" fill="#F9F9F9"/>
<rect x="15" y="12.745" width="1217" height="20.953" fill="none"/>
<ellipse cx="93.5" cy="48.698" rx="10" ry="10" fill="#222" stroke="#222"/>
<rect x="23.5" y="78.698" width="140" height="33.969" rx="3.5" ry="3.5" fill="#F1F1F1" stroke="#181818" stroke-width=".5"/>
<text x="33.5" y="99.8369" fill="#000000" font-family="sans-serif" font-size="12" textLength="120">OrderCreatedEvent</text>
<rect x="21" y="235.04" width="145" height="33.969" rx="3.5" ry="3.5" fill="#F1F1F1" stroke="#181818" stroke-width=".5"/>
<text x="31" y="256.1768" fill="#FF0000" font-family="sans-serif" font-size="12" textLength="125">OrderRejectedEvent</text>
<rect x="23" y="311.01" width="141" height="33.969" rx="3.5" ry="3.5" fill="#F1F1F1" stroke="#181818" stroke-width=".5"/>
<text x="33" y="332.1455" fill="#000000" font-family="sans-serif" font-size="12" textLength="121">OrderPendingEvent</text>
<rect x="21" y="467.35" width="145" height="33.969" rx="3.5" ry="3.5" fill="#F1F1F1" stroke="#181818" stroke-width=".5"/>
<text x="31" y="488.4854" fill="#FF0000" font-family="sans-serif" font-size="12" textLength="125">OrderRejectedEvent</text>
<rect x="21" y="723.61" width="145" height="33.969" rx="3.5" ry="3.5" fill="#F1F1F1" stroke="#181818" stroke-width=".5"/>
<text x="31" y="744.7471" fill="#FF0000" font-family="sans-serif" font-size="12" textLength="125">OrderRejectedEvent</text>
<rect x="21" y="1037.8" width="145" height="33.969" rx="3.5" ry="3.5" fill="#F1F1F1" stroke="#181818" stroke-width=".5"/>
<text x="31" y="1058.9619" fill="#FF0000" font-family="sans-serif" font-size="12" textLength="125">OrderRejectedEvent</text>
<rect x="118" y="1172.9" width="149" height="33.969" rx="3.5" ry="3.5" fill="#f1f1f1" stroke="#181818" stroke-width=".5"/>
<text transform="translate(0 33.158)" x="128" y="1160.9307" fill="#008000" font-family="sans-serif" font-size="12px" textLength="129">OrderApprovedEvent</text>
<circle cx="192.5" cy="1252.9" r="11" fill="none" stroke="#222"/>
<circle cx="192.5" cy="1252.9" r="6" fill="#222" stroke="#222"/>
<line x1="15" x2="15" y1="12.745" y2="1264.8" stroke="#000" stroke-width="1.5"/>
<rect x="277" y="132.67" width="173" height="33.969" rx="3.5" ry="3.5" fill="#F1F1F1" stroke="#181818" stroke-width=".5"/>
<text x="287" y="153.8057" fill="#000000" font-family="sans-serif" font-size="12" textLength="153">ProductPriceQuoteEvent</text>
<polygon points="351.5 186.64 375.5 186.64 387.5 198.64 375.5 210.64 351.5 210.64 339.5 198.64" fill="#F1F1F1" stroke="#181818" stroke-width=".5"/>
<text x="367.5" y="220.8462" fill="#FF0000" font-family="sans-serif" font-size="11" textLength="74">UNAVALIABLE</text>
<text x="351.5" y="202.4438" fill="#000000" font-family="sans-serif" font-size="11" textLength="24">type</text>
<text x="387.5" y="196.0415" fill="#008000" font-family="sans-serif" font-size="11" textLength="58">AVALIABLE</text>
<line x1="271" x2="271" y1="12.745" y2="1264.8" stroke="#000" stroke-width="1.5"/>
<rect x="574.5" y="364.98" width="164" height="33.969" rx="3.5" ry="3.5" fill="#F1F1F1" stroke="#181818" stroke-width=".5"/>
<text x="584.5" y="386.1143" fill="#000000" font-family="sans-serif" font-size="12" textLength="144">StockReservationEvent</text>
<polygon points="644.5 418.94 668.5 418.94 680.5 430.94 668.5 442.94 644.5 442.94 632.5 430.94" fill="#F1F1F1" stroke="#181818" stroke-width=".5"/>
<text x="660.5" y="453.1548" fill="#FF0000" font-family="sans-serif" font-size="11" textLength="120">INSUFFICIENT_STOCK</text>
<text x="644.5" y="434.7524" fill="#000000" font-family="sans-serif" font-size="11" textLength="24">type</text>
<text x="680.5" y="428.3501" fill="#008000" font-family="sans-serif" font-size="11" textLength="103">STOCK_RESERVED</text>
<rect x="573.5" y="645.69" width="166" height="47.938" rx="3.5" ry="3.5" fill="#F1F1F1" stroke="#181818" stroke-width=".5"/>
<text x="583.5" y="666.8252" fill="#000000" font-family="sans-serif" font-size="12" textLength="144">StockReservationEvent</text>
<text x="583.5" y="680.7939" fill="#808080" font-family="sans-serif" font-size="12" textLength="146">type: STOCK_RETURNED</text>
<rect x="573.5" y="969.89" width="166" height="47.938" rx="3.5" ry="3.5" fill="#F1F1F1" stroke="#181818" stroke-width=".5"/>
<text x="583.5" y="991.0244" fill="#000000" font-family="sans-serif" font-size="12" textLength="144">StockReservationEvent</text>
<text x="583.5" y="1004.9932" fill="#808080" font-family="sans-serif" font-size="12" textLength="146">type: STOCK_RETURNED</text>
<rect x="483" y="1161.3" width="170" height="47.938" rx="3.5" ry="3.5" fill="#F1F1F1" stroke="#181818" stroke-width=".5"/>
<text x="493" y="1182.4463" fill="#000000" font-family="sans-serif" font-size="12" textLength="144">StockReservationEvent</text>
<text x="493" y="1196.415" fill="#808080" font-family="sans-serif" font-size="12" textLength="150">type: STOCK_CONSUMED</text>
<line x1="465" x2="465" y1="12.745" y2="1264.8" stroke="#000" stroke-width="1.5"/>
<rect x="816.5" y="543.32" width="175" height="33.969" rx="3.5" ry="3.5" fill="#F1F1F1" stroke="#181818" stroke-width=".5"/>
<text x="826.5" y="564.4541" fill="#000000" font-family="sans-serif" font-size="12" textLength="155">ShipmentAllocationEvent</text>
<polygon points="892 597.28 916 597.28 928 609.28 916 621.28 892 621.28 880 609.28" fill="#F1F1F1" stroke="#181818" stroke-width=".5"/>
<text x="908" y="631.4946" fill="#FF0000" font-family="sans-serif" font-size="11" textLength="37">FAILED</text>
<text x="892" y="613.0923" fill="#000000" font-family="sans-serif" font-size="11" textLength="24">type</text>
<text x="928" y="606.6899" fill="#008000" font-family="sans-serif" font-size="11" textLength="65">ALLOCATED</text>
<rect x="805.5" y="901.95" width="197" height="47.938" rx="3.5" ry="3.5" fill="#F1F1F1" stroke="#181818" stroke-width=".5"/>
<text x="815.5" y="923.0869" fill="#000000" font-family="sans-serif" font-size="12" textLength="155">ShipmentAllocationEvent</text>
<text x="815.5" y="937.0557" fill="#808080" font-family="sans-serif" font-size="12" textLength="177">type: ALLOCATION_RELEASED</text>
<line x1="799.5" x2="799.5" y1="12.745" y2="1264.8" stroke="#000" stroke-width="1.5"/>
<rect x="1022" y="799.58" width="175" height="33.969" rx="3.5" ry="3.5" fill="#F1F1F1" stroke="#181818" stroke-width=".5"/>
<text x="1032" y="820.7158" fill="#000000" font-family="sans-serif" font-size="12" textLength="155">PaymentProcessedEvent</text>
<polygon points="1097.5 853.55 1121.5 853.55 1133.5 865.55 1121.5 877.55 1097.5 877.55 1085.5 865.55" fill="#F1F1F1" stroke="#181818" stroke-width=".5"/>
<text x="1113.5" y="887.7563" fill="#FF0000" font-family="sans-serif" font-size="11" textLength="37">FAILED</text>
<text x="1097.5" y="869.354" fill="#000000" font-family="sans-serif" font-size="11" textLength="24">type</text>
<text x="1133.5" y="862.9517" fill="#008000" font-family="sans-serif" font-size="11" textLength="55">SUCCESS</text>
<line x1="1016" x2="1016" y1="12.745" y2="1264.8" stroke="#000" stroke-width="1.5"/>
<line x1="1230" x2="1230" y1="12.745" y2="1264.8" stroke="#000" stroke-width="1.5"/>
<line x1="93.5" x2="93.5" y1="58.698" y2="78.698" stroke="#191919"/>
<polygon points="89.5 68.698 93.5 78.698 97.5 68.698 93.5 72.698" fill="#191919" stroke="#191919"/>
<line x1="192.5" x2="192.5" y1="1206.9" y2="1241.9" stroke="#191919"/>
<polygon transform="translate(0 33.158)" points="192.5 1208.8 196.5 1198.8 192.5 1202.8 188.5 1198.8" fill="#191919" stroke="#191919"/>
<line x1="387.5" x2="446" y1="198.64" y2="198.64" stroke="#191919"/>
<polygon points="442 247.77 446 257.77 450 247.77 446 251.77" fill="#191919" stroke="#191919"/>
<line x1="446" x2="446" y1="198.64" y2="296.01" stroke="#191919"/>
<line x1="446" x2="93.5" y1="296.01" y2="296.01" stroke="#191919"/>
<line x1="93.5" x2="93.5" y1="296.01" y2="311.01" stroke="#191919"/>
<polygon points="89.5 301.01 93.5 311.01 97.5 301.01 93.5 305.01" fill="#191919" stroke="#191919"/>
<line x1="363.5" x2="363.5" y1="166.64" y2="186.64" stroke="#191919"/>
<polygon points="359.5 176.64 363.5 186.64 367.5 176.64 363.5 180.64" fill="#191919" stroke="#191919"/>
<line x1="680.5" x2="904" y1="430.94" y2="430.94" stroke="#191919"/>
<polygon points="900 488.83 904 498.83 908 488.83 904 492.83" fill="#191919" stroke="#191919"/>
<line x1="904" x2="904" y1="430.94" y2="543.32" stroke="#191919"/>
<polygon points="900 533.32 904 543.32 908 533.32 904 537.32" fill="#191919" stroke="#191919"/>
<line x1="656.5" x2="656.5" y1="398.94" y2="418.94" stroke="#191919"/>
<polygon points="652.5 408.94 656.5 418.94 660.5 408.94 656.5 412.94" fill="#191919" stroke="#191919"/>
<line x1="568" x2="568" y1="1124.3" y2="1156.8" stroke="#181818" stroke-width=".88559"/>
<polygon points="564 1151.3 568 1161.3 572 1151.3 568 1155.3" fill="#181818" stroke="#181818"/>
<line x1="928" x2="1109.5" y1="609.28" y2="609.28" stroke="#191919"/>
<polygon points="1105.5 703.62 1109.5 713.62 1113.5 703.62 1109.5 707.62" fill="#191919" stroke="#191919"/>
<line x1="1109.5" x2="1109.5" y1="609.28" y2="799.58" stroke="#191919"/>
<polygon points="1105.5 789.58 1109.5 799.58 1113.5 789.58 1109.5 793.58" fill="#191919" stroke="#191919"/>
<line x1="904" x2="904" y1="577.28" y2="597.28" stroke="#191919"/>
<polygon points="900 587.28 904 597.28 908 587.28 904 591.28" fill="#191919" stroke="#191919"/>
<line x1="1133.5" x2="1211" y1="865.55" y2="865.55" stroke="#191919"/>
<polygon points="1207 982.62 1211 992.62 1215 982.62 1211 986.62" fill="#191919" stroke="#191919"/>
<line x1="1211" x2="1211" y1="865.55" y2="1098.8" stroke="#191919"/>
<line x1="1211" x2="656.5" y1="1098.8" y2="1098.8" stroke="#191919"/>
<line x1="656.5" x2="656.5" y1="1098.3" y2="1115.8" stroke="#191919" stroke-width="1.0794"/>
<polygon transform="translate(0 8.1941)" points="656.5 1113.8 660.5 1103.8 656.5 1107.8 652.5 1103.8" fill="#191919" stroke="#191919"/>
<line x1="1109.5" x2="1109.5" y1="833.55" y2="853.55" stroke="#191919"/>
<polygon points="1105.5 843.55 1109.5 853.55 1113.5 843.55 1109.5 847.55" fill="#191919" stroke="#191919"/>
<line x1="93.5" x2="93.5" y1="112.67" y2="117.67" stroke="#191919"/>
<line x1="93.5" x2="363.5" y1="117.67" y2="117.67" stroke="#191919"/>
<line x1="363.5" x2="363.5" y1="117.67" y2="132.67" stroke="#191919"/>
<polygon points="359.5 122.67 363.5 132.67 367.5 122.67 363.5 126.67" fill="#191919" stroke="#191919"/>
<line x1="363.5" x2="363.5" y1="210.64" y2="222.84" stroke="#191919"/>
<line x1="363.5" x2="93.5" y1="222.84" y2="222.84" stroke="#191919"/>
<line x1="93.5" x2="93.5" y1="222.84" y2="235.04" stroke="#191919"/>
<polygon points="89.5 225.04 93.5 235.04 97.5 225.04 93.5 229.04" fill="#191919" stroke="#191919"/>
<line x1="93.5" x2="93.5" y1="344.98" y2="349.98" stroke="#191919"/>
<line x1="93.5" x2="656.5" y1="349.98" y2="349.98" stroke="#191919"/>
<line x1="656.5" x2="656.5" y1="349.98" y2="364.98" stroke="#191919"/>
<polygon points="652.5 354.98 656.5 364.98 660.5 354.98 656.5 358.98" fill="#191919" stroke="#191919"/>
<line x1="656.5" x2="656.5" y1="442.94" y2="455.15" stroke="#191919"/>
<line x1="656.5" x2="93.5" y1="455.15" y2="455.15" stroke="#191919"/>
<line x1="93.5" x2="93.5" y1="455.15" y2="467.35" stroke="#191919"/>
<polygon points="89.5 457.35 93.5 467.35 97.5 457.35 93.5 461.35" fill="#191919" stroke="#191919"/>
<line x1="656.5" x2="656.5" y1="693.62" y2="706.11" stroke="#191919"/>
<line x1="656.5" x2="93.5" y1="706.11" y2="706.11" stroke="#191919"/>
<line x1="93.5" x2="93.5" y1="706.11" y2="723.61" stroke="#191919"/>
<polygon points="89.5 713.61 93.5 723.61 97.5 713.61 93.5 717.61" fill="#191919" stroke="#191919"/>
<line x1="904" x2="904" y1="621.28" y2="633.49" stroke="#191919"/>
<line x1="904" x2="656.5" y1="633.49" y2="633.49" stroke="#191919"/>
<line x1="656.5" x2="656.5" y1="633.49" y2="645.69" stroke="#191919"/>
<polygon points="652.5 635.69 656.5 645.69 660.5 635.69 656.5 639.69" fill="#191919" stroke="#191919"/>
<line x1="904" x2="904" y1="949.89" y2="954.89" stroke="#191919"/>
<line x1="904" x2="656.5" y1="954.89" y2="954.89" stroke="#191919"/>
<line x1="656.5" x2="656.5" y1="954.89" y2="969.89" stroke="#191919"/>
<polygon points="652.5 959.89 656.5 969.89 660.5 959.89 656.5 963.89" fill="#191919" stroke="#191919"/>
<line x1="656.5" x2="656.5" y1="1017.8" y2="1022.8" stroke="#191919"/>
<line x1="656.5" x2="93.5" y1="1022.8" y2="1022.8" stroke="#191919"/>
<line x1="93.5" x2="93.5" y1="1022.8" y2="1037.8" stroke="#191919"/>
<polygon points="89.5 1027.8 93.5 1037.8 97.5 1027.8 93.5 1031.8" fill="#191919" stroke="#191919"/>
<line x1="1109.5" x2="1109.5" y1="877.55" y2="889.75" stroke="#191919"/>
<line x1="1109.5" x2="904" y1="889.75" y2="889.75" stroke="#191919"/>
<line x1="904" x2="904" y1="889.75" y2="901.95" stroke="#191919"/>
<polygon points="900 891.95 904 901.95 908 891.95 904 895.95" fill="#191919" stroke="#191919"/>
<line x1="657.13" x2="192.5" y1="1123.8" y2="1123.8" stroke="#191919" stroke-width=".90845"/>
<line x1="192.5" x2="192.5" y1="1123.3" y2="1166.1" stroke="#191919" stroke-width="1.6355"/>
<polygon transform="translate(0 31.666)" points="192.5 1139.8 196.5 1129.8 192.5 1133.8 188.5 1129.8" fill="#191919" stroke="#191919"/>
<text x="117" y="29.4531" fill="#000000" font-family="sans-serif" font-size="18" textLength="52">Order</text>
<text x="334" y="29.4531" fill="#000000" font-family="sans-serif" font-size="18" textLength="68">Product</text>
<text x="582.25" y="29.4531" fill="#000000" font-family="sans-serif" font-size="18" textLength="100">Warehouse</text>
<text x="869.75" y="29.4531" fill="#000000" font-family="sans-serif" font-size="18" textLength="76">Shipping</text>
<text x="1084" y="29.4531" fill="#000000" font-family="sans-serif" font-size="18" textLength="78">Payment</text>
</svg>

After

Width:  |  Height:  |  Size: 14 KiB