|
14 | 14 | 6. [Caching (Redis)](#caching-redis) |
15 | 15 | 7. [User Preferences](#user-preferences) |
16 | 16 | 8. [AI Recipe Assistant](#ai-recipe-assistant) |
17 | | -9. [Project setup](#project-setup) |
18 | | -10. [Environment variables](#environment-variables) |
19 | | -11. [Compile and run the project](#compile-and-run-the-project) |
20 | | -12. [Run tests](#run-tests) |
21 | | -13. [Deployment](#deployment) |
22 | | -14. [License](#license) |
| 17 | +9. [Analytics](#bar_chart-analytics) |
| 18 | +10.[Database Transactional Outbox Pattern](#database-transactional-outbox-pattern) |
| 19 | +11. [Project setup](#project-setup) |
| 20 | +12. [Environment variables](#environment-variables) |
| 21 | +13. [Compile and run the project](#compile-and-run-the-project) |
| 22 | +14. [Run tests](#run-tests) |
| 23 | +15. [Deployment](#deployment) |
| 24 | +16. [License](#license) |
23 | 25 |
|
24 | 26 |
|
25 | 27 | ## SuperChef |
@@ -265,6 +267,52 @@ Sample response: |
265 | 267 | ] |
266 | 268 | ``` |
267 | 269 |
|
| 270 | +## Database Transactional Outbox Pattern |
| 271 | + |
| 272 | +When a user is created in the system two things happen: |
| 273 | + |
| 274 | +1. A new record is created in the users table respectively. |
| 275 | +2. A welcome email is dispatched to the user's inbox. |
| 276 | + |
| 277 | +This alone, could be a problem and lead to data inconsistencies, for example, it could be the case that the user is created successfully in our database but the message broker for whatever reason goes down precisely at that moment and the message is not delivered. |
| 278 | + |
| 279 | +How do we mitigate this ? |
| 280 | + |
| 281 | +By adding a transactional outbox pattern, this is how it works: |
| 282 | + |
| 283 | +1. There's a table holding the outbox events: |
| 284 | + |
| 285 | + ```typescript |
| 286 | + model OutboxEvent { |
| 287 | + id String @id @default(uuid()) |
| 288 | + topic String |
| 289 | + payload Json |
| 290 | + status OutboxStatus @default(PENDING) |
| 291 | + error String? |
| 292 | + attempts Int @default(0) |
| 293 | + createdAt DateTime @default(now()) @map("created_at") |
| 294 | + updatedAt DateTime @default(now()) @map("updated_at") |
| 295 | + |
| 296 | + @@index([status, createdAt]) |
| 297 | + @@map("outbox_event") |
| 298 | + } |
| 299 | + ``` |
| 300 | +
|
| 301 | + Creating the user is done by means of a transaction, this transaction involves updating both the user table and the outbox_event table. |
| 302 | +
|
| 303 | +2. There's a cron job checking the outbox_event table every `5` seconds. |
| 304 | +
|
| 305 | +- If there's a `PENDING` event it will try to send it to the message broker so it can be processed. |
| 306 | +- If the processing fails and the third attempt hasn't been reached the status remains `PENDING` and the attempts count bumps up. |
| 307 | +- If it's the third attempt and the processing fails the status is updated to `FAILED`. |
| 308 | +
|
| 309 | +You can check the entire flow in the image below. |
| 310 | +
|
| 311 | +<p align="center"> |
| 312 | + <img src="./outbox.png" alt="superchef" /> |
| 313 | +</p> |
| 314 | +
|
| 315 | +
|
268 | 316 | ## :credit_card: Stripe Integration |
269 | 317 |
|
270 | 318 | Superchef integrates with Stripe for subscription management, allowing users to subscribe to a basic plan and access enhanced features. |
|
0 commit comments